Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/model_population.py
diff options
context:
space:
mode:
Diffstat (limited to 'model_population.py')
-rw-r--r--model_population.py243
1 files changed, 243 insertions, 0 deletions
diff --git a/model_population.py b/model_population.py
new file mode 100644
index 0000000..93ae43e
--- /dev/null
+++ b/model_population.py
@@ -0,0 +1,243 @@
+# coding: UTF8
+# Copyright 2009 Thomas Jourdan
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import pickle
+import sys
+import os.path
+import random
+import ka_debug
+import ka_random
+import model_protozoon
+
+STATE_INIT = 'I'
+STATE_RANDOMIZED = 'R'
+STATE_EVOLVED = 'E'
+
+class KandidModel(object):
+ """
+ inv: self.size >= 2
+ inv: 1 <= self.fade_away <= self.size
+ #inv: 0.0 <= self._flurry_rate <= 9.0
+ inv: len(self.fitness) == self.size
+ inv: forall(self.fitness, lambda f: 0.0 <= f <= 9.0)
+ inv: len(self.protozoans) == self.size
+ inv: forall(self.protozoans, lambda p: p is not None)
+ # all protozoans must be distinct objects, maybe with equal content
+ inv: all_uniqe_reference(self.protozoans)
+ """
+
+ def __init__(self, init_size):
+ self._state = STATE_INIT
+ self.size = init_size
+ self.fade_away = init_size / 2
+ #self._flurry_rate = 5.0
+ self.protozoans = [model_protozoon.Protozoon() for i in range(self.size)]
+ self.fitness = [4.0 for i in range(self.size)]
+ ka_debug.info('initializing model with population size %u' % init_size)
+
+ def get_flurry_rate(self):
+ return ka_random.get_flurry()
+# return self._flurry_rate
+
+ def set_flurry_rate(self, value):
+ """
+ pre: 0 <= value <= 9
+ """
+ ka_random.set_flurry(value)
+# self._flurry_rate = value
+
+ def is_overwrite_allowed(self):
+ """Preserve an already evolved population from over writing."""
+ return not self._state == STATE_EVOLVED
+
+ def classify(self):
+ """
+ # __return__[0] -> good
+ # __return__[1] -> moderate
+ # __return__[2] -> poor
+ post: len(__return__[0])+len(__return__[1])+len(__return__[2]) == self.size
+ post: len(__return__[0]) >= 1
+ post: len(__return__[2]) >= 1
+
+ # mutual exclusive
+ post: forall(__return__[0], lambda x: not contains_reference(x, __return__[1]))
+ post: forall(__return__[0], lambda x: not contains_reference(x, __return__[2]))
+ post: forall(__return__[2], lambda x: not contains_reference(x, __return__[0]))
+ post: forall(__return__[2], lambda x: not contains_reference(x, __return__[1]))
+ """
+ good, moderate, poor = [], [], []
+ sorted_fitness = sorted(self.fitness)
+ poor_level = sorted_fitness[self.fade_away-1]
+ good_level = sorted_fitness[-1]
+ for protoz, fit in zip(self.protozoans, self.fitness):
+ if fit >= good_level and len(good) < 1:
+ good.append(protoz)
+ elif fit <= poor_level:
+ if len(poor) >= self.fade_away:
+ index = random.randint(0, len(poor)-1)
+ moderate.append(poor[index])
+ del poor[index]
+ poor.append(protoz)
+ else:
+ moderate.append(protoz)
+ return good, moderate, poor
+
+ def reduce_fitness(self, index):
+ """
+ pre: 0 <= index < len(self.fitness)
+ post: self.fitness.count(0.0) == 1
+ """
+ for raise_at, fit in enumerate(self.fitness):
+ if fit < 1.0:
+ self.fitness[raise_at] = 1.0
+ self.fitness[index] = 0.0
+
+ def raise_fitness(self, index):
+ """
+ pre: 0 <= index < len(self.fitness)
+ post: self.fitness.count(9.0) == 1
+ """
+ for lower_at, fit in enumerate(self.fitness):
+ if 5.0 < fit:
+ self.fitness[lower_at] = round(self.fitness[lower_at] - 1.0)
+ self.fitness[index] = 9.0
+
+ def randomize(self):
+ self._state = STATE_RANDOMIZED
+ for protoz in self.protozoans:
+ protoz.randomize()
+
+ def random(self):
+ """
+ post: len(__return__) > 0
+ post: forall(__return__, lambda x: 0 <= x < self.size)
+ """
+ new_indices = []
+ self._state = STATE_EVOLVED
+ good, moderate, poor = self.classify()
+ for new_at, protoz in enumerate(self.protozoans):
+ if protoz in poor:
+ self.protozoans[new_at].randomize()
+ self.fitness[new_at] = 4.0
+ new_indices.append(new_at)
+ print 'new_indices', new_indices
+ return new_indices
+
+ def breed(self):
+ """
+ post: len(__return__) > 0
+ post: forall(__return__, lambda x: 0 <= x < self.size)
+ """
+ new_indices = []
+ self._state = STATE_EVOLVED
+ good, moderate, poor = self.classify()
+ index = 0
+ for new_at, protoz in enumerate(self.protozoans):
+ if protoz in poor:
+ new_one = good[0].crossingover(moderate[index % len(moderate)])
+ new_one.shuffle()
+ new_one.mutate()
+ self.protozoans[new_at] = new_one
+ self.fitness[new_at] = 4.0
+ new_indices.append(new_at)
+ index += 1
+ print 'new_indices', new_indices
+ return new_indices
+
+ def replace(self, new_one):
+ """Replace protozoon with lowest fitness.
+ pre: isinstance(new_one, model_protozoon.Protozoon)
+ """
+ poor_level = 999999.9
+ for protoz, fit in zip(self.protozoans, self.fitness):
+ if fit < poor_level:
+ poor_level = fit
+ poor = protoz
+ for new_at, protoz in enumerate(self.protozoans):
+ if protoz is poor:
+ self.protozoans[new_at] = new_one
+ self.fitness[new_at] = 5.0
+ return new_at
+ return -1
+
+ flurry_rate = property(get_flurry_rate, set_flurry_rate)
+
+
+def from_buffer(str_buffer):
+ ka_debug.info('read from_buffer')
+ obj = None
+ try:
+ obj = pickle.loads(str_buffer)
+ except:
+ ka_debug.err('failed reading buffer [%s] [%s]' % \
+ (sys.exc_info()[0], sys.exc_info()[1]))
+ ka_debug.info('[%s]' % str_buffer)
+ return obj
+
+def to_buffer(obj):
+ ka_debug.info('write %s to_buffer' % type(obj))
+ try:
+ return pickle.dumps(obj)
+ except:
+ ka_debug.err('failed writing buffer [%s] [%s]' % \
+ (sys.exc_info()[0], sys.exc_info()[1]))
+
+def read_file(file_path):
+ model = None
+ if os.path.isfile(file_path):
+ in_file = None
+ try:
+ in_file = open(file_path, 'r')
+ ka_debug.info('in_file [%s]' % in_file.name)
+ model = pickle.load(in_file)
+ except:
+ ka_debug.err('failed reading [%s] [%s] [%s]' % \
+ (in_file.name, sys.exc_info()[0], sys.exc_info()[1]))
+ finally:
+ if in_file:
+ in_file.close()
+ return model
+
+def write_file(file_path, model):
+ out_file = None
+ try:
+ out_file = open(file_path, 'w')
+ ka_debug.info('write out_file [%s]' % out_file.name)
+ pickle.dump(model, out_file)
+ except:
+ ka_debug.err('failed writing [%s] [%s] [%s]' % \
+ (out_file.name, sys.exc_info()[0], sys.exc_info()[1]))
+ finally:
+ if out_file:
+ out_file.close()
+
+def all_uniqe_reference(sequ):
+ # Brute force is all that's left.
+ unique = []
+ for elem in sequ:
+ if contains_reference(elem, unique):
+ return False
+ else:
+ unique.append(elem)
+ return len(unique) == len(sequ)
+
+def contains_reference(find_elem, sequ):
+ for elem in sequ:
+ if id(find_elem) == id(elem):
+ return True
+ return False
+