From 5256ff7091a7dd75ba18165562ee9b4bf6b2b805 Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Fri, 29 Dec 2017 17:05:18 -0800 Subject: [PATCH] first genetic algo bot --- Pipfile | 1 + Pipfile.lock | 2 +- genetic.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ matrixbot.py | 22 +++++++++++++++ supply.py | 19 +++++++++++-- 5 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 genetic.py create mode 100644 matrixbot.py diff --git a/Pipfile b/Pipfile index ebf08b0..93dc74d 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ name = "pypi" [packages] matplotlib = "*" +numpy = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index af518f9..987dd84 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "aed9c28be63899aa45429206673c5a773fc0eca0acea8ec8909e1f1fcd6b4e7c" + "sha256": "1a39e45c62576713be6123d9287975b50115164b6bad65cf1b5c879588893f83" }, "host-environment-markers": { "implementation_name": "cpython", diff --git a/genetic.py b/genetic.py new file mode 100644 index 0000000..0893a18 --- /dev/null +++ b/genetic.py @@ -0,0 +1,88 @@ +import supply +import random +import matrixbot +import numpy as np +from operator import itemgetter + +SOLD_BENEFIT = 2 + +def run_generation(pop, i): + print("Generation %d" % i) + ranking = [] + for x in pop: + score = evaluate(x) + ranking.append((score, x)) + ranking.sort(key=itemgetter(0)) + print("Best of generation: ", ranking[0]) + newpop = [x[1] for x in ranking[:len(ranking)//2]] + newpop = breed(newpop, len(pop), i) + return newpop + +def evaluate(mem): + g = supply.variableRequestGenerator(supply.TURNS, 8, 14) + #chain = [StupidAI(12), PlayerChain("Manufacturer", 12), Base()] + chain = [matrixbot.MatrixBot(mem[:25], mem[25:], 12), supply.Base()] + total_sold = 0 + history = [] + for topreq in g: + requests = [x.request() for x in chain] + requests = requests[:-1] + requests.insert(0, topreq) + got = 0 + for i, c in reversed(list(enumerate(chain))): + got = c.reconcile(requests[i], got) + #print("Sold ", got, " units.") + total_sold += got + history.append([x.cost() for x in chain]) + total_cost = [sum([x[0] * supply.SUPPLY_COST + x[1] * supply.BACKLOG_COST for x in y]) for y in history] + cost = supply.integrate(total_cost)[-1] - (total_sold * SOLD_BENEFIT) + return cost + + +def mate(a, b): + out = [] + for x in range(len(a)): + if random.random() < 0.5: + out.append(a[x]) + else: + out.append(b[x]) + return np.array(out) + +def mutate(a): + for i in range(5): + x = random.randint(0, len(a) - 1) + amt = random.uniform(-0.5, 0.5) + a[x] = a[x] + amt + +WEIGHT = 0.9 +LATE_WEIGHT = 0.2 +GENS = 500 + +def breed(pop, n, i): + global WEIGHT + mut_chance = (WEIGHT - LATE_WEIGHT) * (GENS - i / GENS) + LATE_WEIGHT + total = n - len(pop) + newbies = [] + while total != 0: + a = random.choice(pop) + b = random.choice(pop) + c = mate(a, b) + if random.random() < mut_chance: + mutate(c) + newbies.append(c) + total -= 1 + c = pop[:] + c.extend(newbies) + return c + +def main(): + starting_pop = [] + for i in range(300): + x = np.random.uniform(low=-2, high=2, size=30) + starting_pop.append(x) + pop = starting_pop + for gen in range(GENS): + pop = run_generation(pop, gen+1) + +if __name__ == "__main__": + main() diff --git a/matrixbot.py b/matrixbot.py new file mode 100644 index 0000000..41fc9a7 --- /dev/null +++ b/matrixbot.py @@ -0,0 +1,22 @@ +import supply +import numpy as np + +class MatrixBot(supply.Chain): + def __init__(self, hidden1, hidden2, initial): + a = np.matrix(hidden1).reshape(5,5) + b = np.matrix(hidden2).reshape(1,5) + self.mat = np.matmul(b, a) + super().__init__(initial) + def request(self): + x = [self.backlog, self.last_got, self.last_req, self.last_ship, self.supply] + out = np.matmul(self.mat, np.matrix(x).transpose()) + n = out.tolist()[0][0] + if n < 0: + return 0 + if n > 200: + return 200 + return int(n) + +if __name__ == "__main__": + m = MatrixBot(np.random.uniform(low=-3, high=3, size=25), np.random.uniform(low=-3, high=3, size=5), 12) + print(m.request()) diff --git a/supply.py b/supply.py index b033c69..90bf01d 100644 --- a/supply.py +++ b/supply.py @@ -1,6 +1,7 @@ import math import random import matplotlib.pyplot as plt +import matrixbot BACKLOG_COST = 25 SUPPLY_COST = 5 @@ -100,8 +101,22 @@ def main(): global SUPPLY_COST global BACKLOG_COST g = variableRequestGenerator(TURNS, 8, 14) - #chain = [StupidAI(12), PlayerChain("Manufacturer", 12), Base()] - chain = [PlayerChain("me", 12), LessStupidAI(12), LessStupidAI(12), LessStupidAI(12), Base()] + #chain = [PlayerChain("Manufacturer", 12), Base()] + #chain = [PlayerChain("me", 12), LessStupidAI(12), LessStupidAI(12), LessStupidAI(12), Base()] + mb1 = matrixbot.MatrixBot([ 0.29963248, 0.08142691, -0.86641011, 0.23675042, 0.7086182 , + -0.06441882, 0.03062067, -1.18299915, 0.68115478, 0.16068485, + -1.7178326 , -0.29003603, -0.83202861, 1.73222139, -1.98878473, + -0.96036021, 0.65793096, 1.50552035, -1.18544224, 0.03207729, + 0.78074126, -0.91446605, 2.92469872, 0.48680479, -0.34067442], + [-0.07150818, -0.10019835, -0.02610447, -0.02049193, 0.42415006], 12) + mb2 = matrixbot.MatrixBot([ 0.29963248, 0.08142691, -0.86641011, 0.23675042, 0.7086182 , + -0.06441882, 0.03062067, -1.18299915, 0.68115478, 0.16068485, + -1.7178326 , -0.29003603, -0.83202861, 1.73222139, -1.98878473, + -0.96036021, 0.65793096, 1.50552035, -1.18544224, 0.03207729, + 0.78074126, -0.91446605, 2.92469872, 0.48680479, -0.34067442], + [-0.07150818, -0.10019835, -0.02610447, -0.02049193, 0.42415006], 12) + chain = [mb1, PlayerChain("me", 12), mb2, Base()] + import pdb; pdb.set_trace() turn = 0 total_sold = 0 history = []