Created
November 5, 2012 10:52
-
-
Save alf239/4016609 to your computer and use it in GitHub Desktop.
Genetic algorithm for a 7-form home task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# encoding: utf-8 | |
""" | |
robot.py | |
Created by Alexey Filippov on 2012-11-03. | |
Copyright (c) 2012 Alexey Filippov. All rights reserved. | |
""" | |
import sys | |
import os | |
import random | |
def sqr(x): | |
return x*x | |
class Cell: | |
def __init__(this, code): | |
this.code = code | |
this.moves = dict() | |
def move(this, move): | |
if move in this.moves: | |
return this.moves[move] | |
return this | |
def canReach(this): | |
visited = set() | |
queue = [this] | |
while True: | |
c = queue.pop() | |
if not c.code in visited: | |
visited |= set([c.code]) | |
queue = queue + [x for x in c.moves.values() if not x.code in visited] | |
if not queue: | |
break | |
return visited | |
def __str__(this): | |
return "%d" % (this.code) | |
def __hash__(this): | |
return this.code | |
class Field: | |
def __init__(this, map): | |
this.code = map | |
this.cells = [Cell(i) for i in range(9)] | |
if 0 != (map & 0b100000000000): this.link(0, 1, 'rl') | |
if 0 != (map & 0b010000000000): this.link(1, 2, 'rl') | |
if 0 != (map & 0b001000000000): this.link(0, 3, 'du') | |
if 0 != (map & 0b000100000000): this.link(1, 4, 'du') | |
if 0 != (map & 0b000010000000): this.link(2, 5, 'du') | |
if 0 != (map & 0b000001000000): this.link(3, 4, 'rl') | |
if 0 != (map & 0b000000100000): this.link(4, 5, 'rl') | |
if 0 != (map & 0b000000010000): this.link(3, 6, 'du') | |
if 0 != (map & 0b000000001000): this.link(4, 7, 'du') | |
if 0 != (map & 0b000000000100): this.link(5, 8, 'du') | |
if 0 != (map & 0b000000000010): this.link(6, 7, 'rl') | |
if 0 != (map & 0b000000000001): this.link(7, 8, 'rl') | |
def link(this, f, t, m): | |
this.cells[f].moves[m[0]] = this.cells[t] | |
this.cells[t].moves[m[1]] = this.cells[f] | |
def linked(this): | |
return len(this.cells[0].canReach()) == 9 | |
def log(this): | |
print "map", this.code | |
for i in range(9): | |
print this.cells[i].code, "->", [c.code for c in | |
this.cells[i].moves.values()] | |
class Robot: | |
def __init__(this, cell): | |
this.c = cell | |
def move(this, move): | |
this.c = this.c.move(move) | |
def execute(this, s): | |
seen = set([this.c]) | |
for c in s: | |
this.move(c) | |
seen |= set([this.c]) | |
return seen | |
def dna(): | |
return ''.join(random.choice("lrud") for n in xrange(60)) | |
def fields(): | |
return [f for f in [Field(i) for i in xrange(2**12)] if f.linked()] | |
def score(program, test_set, fields = 10, positions = 3): | |
passed = 0.0 | |
for field in random.sample(test_set, fields): | |
for start in random.sample(range(9), positions): | |
r = Robot(field.cells[start]) | |
seen = r.execute(program) | |
passed += sqr(len(seen) / 9.) | |
return sqr(passed / fields / positions) | |
def select(colony, f): | |
scores = sorted([(robot, f(robot)) for robot in colony], key = lambda s: -s[1]) | |
print "\n".join(["%s: %.6f" % s for s in scores[:10]]) | |
if test_program(scores[0][0]): | |
print "Solved", scores[0][0], scores[0][1] | |
else: | |
scores = scores[1:] | |
return [s[0] for s in scores if s[1] > random.lognormvariate(0.5, 0.2) - 1] | |
def baby(a,b): | |
return a[:random.randint(0, len(a) - 1)] + b[-random.randint(0,len(b)-1):] | |
def grow(colony, n): | |
print "survivors:", len(colony) | |
num = n - len(colony) | |
cl = [s for s in random.sample(colony, min(num/2, len(colony)))] | |
clones = [] | |
for c in cl: | |
i = random.randint(0, len(c)) | |
clones.append(c[:i] + c[i+1:]) | |
print "mutations:", len(clones) | |
children = [baby(random.choice(colony), random.choice(colony)) | |
for i in xrange(num / 2)] | |
print "children:", len(children) | |
return colony + clones + children | |
def genetic(test_set, n = 1000, generations = 10000): | |
colony = [dna() for i in xrange(n)] | |
for i in xrange(generations): | |
print i, "generation" | |
colony = select(colony, lambda bot: score(bot, test_set)) | |
colony = grow(colony, n) | |
def test_program(s): | |
test_set = fields() | |
for f in test_set: | |
for c in xrange(9): | |
r = Robot(f.cells[c]) | |
seen = r.execute(s) | |
if (len(seen) != 9): return False | |
return True | |
def main(): | |
genetic(fields(), n = 1000) | |
# print test_program("urrdludrrduddulurudullruuldrulrdrdrrdllululrruluddrlluuddurrlrrdrrrlulllrduldlrdddlrurulrllddlruurlruulurllduulrrdddlddrrdulurruldrrrdurldlurlrlrdulurddrdullldulrdruuddluddddludlldddrddrulrrluldllrdldrdrrdludrrduuulllrrdlurururdurdddurlruululuuuddrrrurduulruruulrrdddlddrrdulurrulrdldluludldruddrrldluuluduurudrdrrdrlldruuduruulldurruuluuuudlddllrlrlludrududrdurddruuuldrdrrdldrdrrurur") | |
if __name__ == '__main__': | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
urrdludrrduddulurudullruuldrulrdrdrrdllululrruluddrlluuddurr lrrdrrrlulllrduldlrdddlrurulrllddlruurlruulurllduulrrdddlddr rdulurruldrrrdurldlurlrlrdulurddrdullldulrdruuddluddddludlld ddrddrulrrluldllrdldrdrrdludrrduuulllrrdlurururdurdddurlruul uluuuddrrrurduulruruulrrdddlddrrdulurrulrdldluludldruddrrldl...
November 4 - Comment - Share - Edit
tl;dr, piggym⚇use, Reineke and 4 other people liked this
ಠ_ಠ - volatile void
oopsie - You (edit | delete)
Ты кошку завёл? - blacklion
Нет, коллега-подрывник подсунул задачку из седьмого класса. Это ответ. - You (edit | delete)
Спрячь под кат. - piggym⚇use
Риальне. У меня френдфидик в браузере разнесло как ёмоё. - piggym⚇use
А ты etot генетикой нашёл? - piggym⚇use
Ну да, пока я в кино ходил, он и вырос. Я, правда, ожидал чего-нибудь более радостного, типа решение за секунды, думать не надо — а он тут лопатит себе лениво, никуда особо не торопится. - You (edit | delete)
Локальне оптимум. Решение-то наверняка не единственное. - piggym⚇use
А что за задачка-то? - blacklion
^ like - earlyadopter
Есть поле 3*3. Соседние клетки могут быть разделены перегородкой, но поле полносвязное. Исполнителя типа "робот тупой, одна штука", с командами вверх-вниз-вправо-влево-проверить скидывают в случайную клетку поля. Задача: написать последовательность команд, которая "проверит" каждую клетку поля, при том, что у робота нет никакой логики (только конечная лента команд, памяти нет) и никакой обратной связи (если робот идёт в стенку, он просто остаётся на месте). - You (edit | delete)
All work and no play makes Jack a DULLRDLURRRDDLURRDRRUDLL - псы в рапиде
URLD заменяем на ACGT и опа! :) - tl;dr
а на что натравливал генетику. нагенерил какое-то количество полей? или множество всех возможных полей не так велико? - :D
2^12 возможных полей, 431 валидное поле, 9 стартовых позиций. Я в итоге проверяю для всех полей начиная со случайной позиции. - You (edit | delete)
Решение сейчас выглядит так: https://gist.github.com/4016609 — советы принимаются, про то что код говно я и так знаю. - You (edit | delete)
"нам учитель задает с иксами задачи...." :) не, не буду пока отдавать ребенка в 533... - Звериная серьёзность
Лёша, можт в DA газету это дело тиснуть? отчего-то мне кажется что тема зажгет народ. :) - tl;dr
Можно, только писать же придётся. Последние мои две попытки разбились одна об перфекционизм, другая о мизантропию :) - You (edit | delete)
Кстати, секунды не секунды, а за пару минул налопачивает. Ещё бы длину попридержать... Но лень. - You (edit | delete)
И, кстати, Реша сцуко наобманул. Задачка была проще. - You (edit | delete)
^ робот помнит клетку с которой пришел? :) - tl;dr
Нет, цель — эагнать чувака в правую нижнюю клетку. Обходить поле не нужно :) - You (edit | delete)
Кстати, Реша опять гонит, похоже. Побывать в правой нижней клетке просто. Вот оставить чувака в ней, вслепую-то — это задача не для слабых. - You (edit | delete)