牌語備忘録 -pygo

あくまでもメモです。なるべくオフィシャルの情報を参照してください。

牌語備忘録 -pygo

『マッチ箱の脳』GAアルゴリズムをクラスでやってみた

修正:『マッチ箱の脳』人工知能ジェネテックアルゴリズムをPythonでやってみた - 牌語備忘録 - pygoの最後に乗せてた失敗版のコードをエントリーばらした。



Rubyで書いてみた〜人工知能ジェネテックアルゴリズム - 牌語備忘録 - pygo』をやるときにPythonのコードを読み返したら、いろいろ修正したくなったのでやってみた

  1. クラスでやってみた
  2. 無駄にながいとこ若干短く
  3. 変数名とか解りやすく?
  4. 汎用性?
  5. 処理終了時の表示を若干変更
#!/usr/bin/env python
# *-# -*- coding: utf-8 -*-
# Genetic Algorithm
# ga2.py

import random

class GeneticAlgorithm:

    def matchbox(self, num = 10, to_kind = 3):
        return [random.randint(1, to_kind) for n in range(num)]

    def amount_of_box(self, amount = 10):
        return [self.matchbox() for count in range(amount)]

    def del_repetition_new_add(self, amount_of_box_seq):
        amount = len(amount_of_box_seq)
        set_tuple = set(map(tuple,amount_of_box_seq))
        tuple_to_lst = map(list, set_tuple)
        lst_len = len(tuple_to_lst)
        if lst_len < 10:
            return tuple_to_lst + self.amount_of_box(amount - lst_len)
        return amount_of_box_seq

    def rating(self, ans, amount_of_box_seq, point = 10):
        score_lst = []
        for box in amount_of_box_seq:
            score = 0
            for a, b in zip(ans, box):
                if a == b:
                    score += point
            score_lst.append([score, box])
        return sorted(score_lst, reverse = True)

    def parent(self, rate_seq):
        return [rate_seq[0][1], rate_seq[1][1]]

    def mutation(self, kids_seq):
        p = random.randint(0, len(kids_seq))
        if p < 10:
            change = lambda x:x + 1 if x < 3 else x - 2
            kids_seq[p] = change(kids_seq[p])
        return kids_seq

    def recombination(self, parent_seq):
        amount_of_stick = len(parent_seq[0])
        crossing = random.randint(0, amount_of_stick)
        kid_a = parent_seq[1][:crossing] + parent_seq[0][crossing:]
        kid_b = parent_seq[0][:crossing] + parent_seq[1][crossing:]
        return [self.mutation(kid_a), self.mutation(kid_b)]

    def answer_display(self, ans, limit_count = 200):
        log = []
        all_box = self.amount_of_box()
        for count in range(1, limit_count + 1):
            non_repetition_seq = self.del_repetition_new_add(all_box)
            rate_seq = self.rating(ans, non_repetition_seq)[:]
            log.append("Generation: %d" % (count))
            log.append("\n".join(["%d %s" % (score, lst)
                                  for score, lst in rate_seq]))
            all_box = [lst for scor, lst in rate_seq]
            parent_seq = self.parent(rate_seq)
            top = all_box[:2]
            tail = all_box[2:-2]
            all_box = self.recombination(parent_seq) + tail + top
            if rate_seq[0][0] == 100:
                log.append('\nAI: "The answer is %s !" (%d generations)'
                           % (rate_seq[0][1], count))
                break
        else:
            log.append("\nbreak: exceeded %d generations of the upper limit."
                       % count)
        return "\n".join(log)


if __name__ == "__main__":
    answer = [3, 1, 2, 2, 2, 3, 1, 3, 2, 1]
    ga = GeneticAlgorithm()
    #test
    #print ga.matchbox()
    #print ga.amount_of_box()
    #print ga.del_repetition_new_add(ga.amount_of_box())
    #print ga.rating(answer, ga.amount_of_box())
    #print ga.parent(ga.rating(answer, ga.amount_of_box()))
    #print ga.mutation([3, 1, 2, 2, 2, 3, 1, 3, 2, 1])
    #print ga.recombination(ga.parent(rate_lst))
    print ga.answer_display(answer)