Skip to content

Instantly share code, notes, and snippets.

@itarato
Created August 13, 2015 07:40
Show Gist options
  • Select an option

  • Save itarato/f258a36a482fa7be69b1 to your computer and use it in GitHub Desktop.

Select an option

Save itarato/f258a36a482fa7be69b1 to your computer and use it in GitHub Desktop.
Sort of genetic algorithm for an imaginary consumption-waste cycle process
import random
import Journey
import copy
__pool_size__ = 90
__survival_limit__ = 30
__mutation_rate__ = 5
def generate_first_generation():
gens = []
for idx in range(__pool_size__):
food = []
waste = []
size = random.randint(1, 3)
for j in range(Journey.__length__):
food.append(random.randint(0, 1))
waste.append(random.randint(0, 1))
gens.append(Journey.Journey(food, waste, size))
return gens
def mutation(gens):
new_breed = []
for gen in gens:
for _ in range(2):
child = copy.deepcopy(gen)
new_breed.append(child)
for _ in range(__mutation_rate__):
assert isinstance(gen, Journey.Journey)
randint = random.randint(0, Journey.__length__ - 1)
child.food_map[randint] = 1 - child.food_map[randint]
randint = random.randint(0, Journey.__length__ - 1)
child.waste_map[randint] = 1 - child.waste_map[randint]
for child in new_breed:
gens.append(child)
def selection(gens):
l = []
total = 0
for gen in gens:
score = gen.score
total += score
l.append([gen, score])
second = lambda x: x[1]
l.sort(key=second, reverse=True)
mean_score = total / len(gens)
print("Iteration mean: %d (total %d out of %d) " % (mean_score, total, len(gens)))
return map(lambda x: x[0], l[:__survival_limit__])
if __name__ == '__main__':
first_generation = generate_first_generation()
survivors = selection(first_generation)
for _ in range(1000):
mutation(survivors)
survivors = selection(survivors)
for pos in range(10):
print('Position #%d' % pos)
survivors[pos].pretty_print()
print('---')
from Queue import FixedSizeQueue
__length__ = 128
__not_hungry_punishment__ = -0.5
__not_wasted_punishment__ = -0.5
class Journey:
def __init__(self, food, waste, size, debug = False):
"""
Food and waste is a "bitmap" represented by a binary array of 0s and 1s.
Every index is a step (day or iteration) for the test.
Food val 1 ~ there is food
Food val 0 ~ no food
Waste val 1 ~ there is an options to release waste (toilet)
Waste val 0 ~ no waste release
:param food: int[128]
:param waste: int[128]
:param size: 1 v 2 v 3
"""
self.food_map = food
self.waste_map = waste
self.size = size
self.length = __length__
self.debug = debug
@property
def score(self):
hunger = 0
waste_total = 0
waste_queue = FixedSizeQueue(self.size + 1)
score = 0
for step in range(self.length):
if self.food_map[step]:
if hunger == 1:
score += __not_hungry_punishment__
hunger = 0
hunger += 1
waste_total += waste_queue.peek
waste_queue.push(self.food_map[step])
if self.waste_map[step]:
if waste_total == 0:
score += __not_wasted_punishment__
waste_total = 0
if hunger >= self.size + 2:
if self.debug: print("Died by starvation")
return score
if waste_total >= self.size + 2:
if self.debug: print("Died by waste")
return score
score += 1
if self.debug: print("Survived")
return score
def pretty_print(self):
print('Size: %d' % self.size)
print('Food: %s' % ''.join(map(str, self.food_map)))
print('Waste: %s' % ''.join(map(str, self.waste_map)))
print('Score: %d' % self.score)
__default_value__ = 0
class FixedSizeQueue:
def __init__(self, size):
self.size = size
self.queue = [__default_value__] * self.size
def push(self, value = 0):
for idx in range(self.size - 2, -1, -1):
self.queue[idx + 1] = self.queue[idx]
self.queue[0] = value
@property
def peek(self):
return self.queue[self.size - 1]
if __name__ == '__main__':
iq = FixedSizeQueue(3)
for i in range(6):
print(iq.peek)
iq.push(i + 10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment