自分の手で知的生活を創造する世界経験の創造

「再帰呼び出し」や「バカ」という用語を使用せずに1日をかけて、実際に2009年にコードの誰かがつづりを間違えたために会計システムの単純な変更がほぼ1週間遅れる理由を主任会計士に説明することがあります。 そのような日には、この世界を創造した賢い人に手を引き、すべてをゼロから書き直したいと思います。



画像



TL; DR

カットの下で、Pythonを学習するための練習として、機械学習と神を使ったエージェントベースのモデリング用のライブラリを開発する方法についてのストーリー。



githubへのリンク 。 箱から出して作業するには、 pygameが必要です。 試用例でsklearnが必要です。



アイデアの起源



私が話をする自転車を作るというアイデアは徐々に現れました。 まず、機械学習のトピックの人気は私を追い越しませんでした。 トレーナーに関するいくつかのコースは、関与の虚偽の感覚を与えました。 いくつかの公開コンテストとkaggleでの登録は、わずかに自尊心を修正しましたが、熱意を弱めることはありませんでした。



第二に、国内のITコミュニティの手に負えないカーストの代表として、私の大好きなPythonを練習する機会はめったにありません。 そして、賢い人たちから、この点であなたのプロジェクトはまさに私たちが必要とするものだと聞いた。



しかし、推進力はノーマンズスカイの失望でした。 技術的には素晴らしいアイデアですが、手続き的に生成された世界は空であることが判明しました。 そして、失望したファンのように、彼らが私に尋ねたらどうするか考え始めました。 そして彼は、世界は空であるという考えを思いつきました。なぜなら、そこには本当に知的生命がほとんどないからです。 無限のオープンスペース、自分だけに頼る習慣、発見者の喜び-もちろん、これはすべて良いことです。 しかし、基地に戻って市場を散策したり、飲食店で最新のゴシップを見つけたりする機会は十分ではありません。 小包を配達し、最終的に100ゴールドを取得します。 ゲームにおける都市、対話、探求は、生きている人の仕事の成果であり、そのような巨大な世界に人間の力による生命を投入することは不可能であることは明らかです。 しかし、必要性、小さな物語、クエストを備えたNPCを手続き的に生成できるとしたらどうでしょうか?



概略計画



だから、いくつかのライブラリのアイデア、あるいはあなたが私を許すなら、次の使用シナリオを持つフレームワークが現れました:



  1. 古典的なエージェントモデリング (その存在は、この記事を書くために座ったときにしか見つかりませんでした)。 ワールドを作成し、このワールド内のエージェントのアクションを記述し、何が起こったのかを確認し、いくつかのパラメーターを変更して、シミュレーションを再度実行します。 そして、個々のエージェントの行動の変化が全体像にどのように影響するかがわかるまで、円で囲みます。 非常に便利なもの。



  2. 強化トレーニング強化学習でもあります)。 特定の環境と対話するように適応する学習モデルを構築します。 簡単な例は、ルールがわからないゲームを教えることですが、いつでもゲームの状態に関する情報を取得し、特定のアクションセットの1つを選択して、獲得したポイント数にどのように影響するかを確認できます(ただし、 このトピック競争は既に終了しています) ) 分類子または回帰の通常のモデルとは多くの違いがあります。 これは、結果の遅延、計画の必要性、およびその他の多くの機能です。



  3. そして最後に、私たちが世界を作成し、合理的であまり良くない生き物を入れた後、個人的にそこに行き、忠実なブラスター、最愛の剣、多目的つるはしまたは赤い爪切りをつかむことができればうれしいです。


いくつかの技術的な詳細



したがって、まず、世界の低レベルの物理学を決定する必要があります。 シンプルでありながら、さまざまな状況をシミュレートするのに十分な柔軟性が必要です。



  1. 基本として、通常のセルラーオートマトン、つまり各オブジェクトが2乗のプランク長を占める2次元の長方形の離散世界を考えてみましょう。 Planckの長さより短い距離は意味がありません。2つのセルの間にオブジェクトを配置することはできません。オブジェクトを完全にではなく、複数のセルを占めるように配置することはできません。



  2. 距離は4方向のステップでのみ測定されます。つまり、セルは8ではなく4に隣接します。対角線上のセルには2つのステップがあります。



  3. 結果のデザインの堅牢性をわずかに希釈するには、少し深さを追加します。各オブジェクトには開通性の兆候があります。 世界の同じ空間座標によると、少なくとも1つ、ただし2つ以下のオブジェクトが存在する可能性があります:通過可能および/または通過不可能なオブジェクト。 これは、オブジェクトが立ち上がって動く表面として想像できます。 表面のタイプも異なり、オブジェクトのタイプも異なります。 カーペット(通過できないオブジェクト)に縁石(通過できないオブジェクト)を置くことができます。 しかし、リノリウムを積層板に置くことはできません(誰がこれを行うのですか?)そして、台座に椅子を置くことはできません。



  4. ただし、縁石にはさまざまなオブジェクトを格納できます。 そして、カーペットの中や、アクティブなオブジェクトのポケットの中にもあります。 つまり、任意のオブジェクトをオブジェクトのコンテナにすることができます。 しかし、他のオブジェクトについてはそうではありません。そうでない場合、私たちは第三法に違反します。



  5. 時間も離散的です。 各ステップ、各オブジェクトは1つのプランク時間に存在し、その間、彼はこの時代の彼の周りの世界に関する情報を外部から取得できます。 これが最も弱い点です。オブジェクトは順番に動作する必要があります。そのため、特定の非同期が発生します。 「移動」の対象となるオブジェクトは、この時代にすでに「似ている」オブジェクトの状態を考慮する必要があります。 オブジェクトが時代の初めにのみ集中できるようにすると、たとえば、2つの通過できないオブジェクトが時代の初めに同じ自由なセルの上に立つという事実につながる可能性があります。 または、ドレッサーから同じ靴下を取り除きます。 これは、各時代のオブジェクトをランダムな順序で参照することでわずかに平準化できますが、このアプローチでは問題を完全に解決することはできません。


これにより、世界自体(フィールド)、この世界のオブジェクト(エンティティ)、およびオブジェクト(物質)という、いくつかの必要な基本オブジェクトが得られます。 以下、記事のコードは単なる説明です。 github のライブラリですべて見ることができます。



エンティティクラスと例
class Entity(object): def __init__(self): # home universe self.board = None # time-space coordinates self.x = None self.y = None self.z = None # lifecycle properties self.age = 0 self.alive = False self.time_of_death = None # common properties self.passable = False self.scenery = True self._container = [] # visualization properties self.color = None def contains(self, substance_type): for element in self._container: if type(element) == substance_type: return True return False def live(self): self.z += 1 self.age += 1 class Blank(Entity): def __init__(self): super(Blank, self).__init__() self.passable = True self.color = "#004400" def live(self): super(Blank, self).live() if random.random() <= 0.0004: self._container.append(substances.Substance()) if len(self._container) > 0: self.color = "#224444" else: self.color = "#004400" class Block(Entity): def __init__(self): super(Block, self).__init__() self.passable = False self.color = "#000000"
      
      







フィールドクラス
 class Field(object): def __init__(self, length, height): self.__length = length self.__height = height self.__field = [] self.__epoch = 0 self.pause = False for y in range(self.__height): row = [] self.__field.append(row) for x in range(self.__length): if y == 0 or x == 0 or y == (height - 1) or x == (length - 1): init_object = Block() else: init_object = Blank() init_object.x = x init_object.y = y init_object.z = 0 row.append([init_object])
      
      







サブスタンスクラスは意味をなさず、その中には何もありません。



時間が経つにつれて、世界自体が責任を負います。 時代ごとに、彼はその中のすべてのオブジェクトを調べ、それらに強制的に移動させます。 彼らがこの動きをどのように行うかは彼ら次第です。



どうぞ!
 class Field(object): ... def make_time(self): if self.pause: return for y in range(self.height): for x in range(self.length): for element in self.__field[y][x]: if element.z == self.epoch: element.live() self.__epoch += 1 ...
      
      







しかし、なぜ私たちは世界を必要とし、それを見ることができなければ、主人公をそこに配置する計画された機会でさえも? 一方、グラフィックスを扱うようになると、気が散ってしまい、世界の支配が無期限に延期されます。 したがって、時間を無駄にすることなく、 pygameを使用したプラットフォーマーの作成に関するこの素晴らしい記事をマスターし(実際、記事の最初の3分の1だけが必要です)、各オブジェクトに色属性を与えます。



可視化コード
 class Field(object): ... def list_obj_representation(self): representation = [] for y in range(self.height): row_list = [] for cell in self.__field[y]: row_list.append(cell[-1]) representation.append(row_list) return representation .... def visualize(field): pygame.init() screen = pygame.display.set_mode(DISPLAY) pygame.display.set_caption("Field game") bg = Surface((WIN_WIDTH, WIN_HEIGHT)) bg.fill(Color(BACKGROUND_COLOR)) myfont = pygame.font.SysFont("monospace", 15) f = field tick = 10 timer = pygame.time.Clock() go_on = True while go_on: timer.tick(tick) for e in pygame.event.get(): if e.type == QUIT: raise SystemExit, "QUIT" if e.type == pygame.KEYDOWN: if e.key == pygame.K_SPACE: f.pause = not f.pause elif e.key == pygame.K_UP: tick += 10 elif e.key == pygame.K_DOWN and tick >= 11: tick -= 10 elif e.key == pygame.K_ESCAPE: go_on = False screen.blit(bg, (0, 0)) f.integrity_check() f.make_time() level = f.list_obj_representation() label = myfont.render("Epoch: {0}".format(f.epoch), 1, (255, 255, 0)) screen.blit(label, (630, 10)) stats = f.get_stats() for i, element in enumerate(stats): label = myfont.render("{0}: {1}".format(element, stats[element]), 1, (255, 255, 0)) screen.blit(label, (630, 25 + (i * 15))) x = y = 0 for row in level: for element in row: pf = Surface((PLATFORM_WIDTH, PLATFORM_HEIGHT)) pf.fill(Color(element.color)) screen.blit(pf, (x, y)) x += PLATFORM_WIDTH y += PLATFORM_HEIGHT x = 0 pygame.display.update()
      
      







もちろん、後でわかりやすい視覚化モジュールを作成することはできますが、モジュールを作成することはできません。 しかし、マルチカラーのランニングスクエアは、新生の雰囲気に浸るのに十分です。 さらに、ファンタジーを展開します。



画像



ここで、活性剤がどのように作用するかを考える必要があります。 まず、すべての重要なアクションはオブジェクトになります(ワールドオブジェクトではなくPythonオブジェクトです。あいまいさをおaびします)。 そのため、たとえ同じタイプであっても、ストーリーを維持し、その状態を操作し、あるアクションと別のアクションを区別できます。 そのため、アクションは次のようになります。



  1. 各アクションには件名が必要です。 アクションの対象は、私たちの世界のオブジェクト(エンティティ)のみです。



  2. すべてのアクションには結果が必要です。 少なくとも「完了/未完了」および「目標達成/目標未達成」。 ただし、アクションのタイプに応じて追加のアクションが存在する場合があります。たとえば、アクション「Find the Nearest Pizzeria」は、必要な結果に加えて、ピッツェリア自体の座標またはオブジェクトを持つことができます。



  3. 各アクションには、パラメーターのセットがある場合とない場合があります。 たとえば、「Pour Cup Coffee」アクションには、明確にする必要がないため、パラメーターがない場合がありますが、「Pour」アクションには、何をどこに注ぐかを明確にする機能が必要です。



  4. アクションは瞬間的または非瞬間的です。 1つの時代では、1つのオブジェクトが実行できる非瞬時アクションは1つだけで、瞬時アクションはいくつでも実行できます。 これは議論の余地のある点です。離散的なスペースがあり、セルの半分を移動できない場合、1つの時代に無制限のアクションを実行する機能は奇妙に見え、明確な離散的な時間の流れを多少損ないます。 また、各タイプのアクションに費やす時間を0〜1の範囲で尋ねるという考えもありました。1のアクションは時代全体を占めます。 離散時間を明確にするために、瞬時ではなくシミュレーションに必要なすべてのアクションをいつでも実行できるため、オプションをインスタント性の兆候で解決しましたが、期間のオプションは非常に複雑です。


したがって、技術的な観点から見ると、アクションのオブジェクト(Action)は一種の関数であり、パラメーターを設定し、実行し、結果を取得し、同時に、渡されたパラメーターと結果、およびその他のことを保存することができます呼び出し元の実装から始まり、実行中の世界の状態で終わる実装に関連付けられています。 したがって、一度に作成し、別のパラメーターを設定し、3番目に実行し、戻り値を取得して、さらに分析するためにシェルフに配置できます。



アクションオブジェクト
 class Action(object): def __init__(self, subject): self.subject = subject self.accomplished = False self._done = False self.instant = False def get_objective(self): return {} def set_objective(self, control=False, **kwargs): valid_objectives = self.get_objective().keys() for key in kwargs.keys(): if key not in valid_objectives: if control: raise ValueError("{0} is not a valid objective".format(key)) else: pass # maybe need to print else: setattr(self, "_{0}".format(key), kwargs[key]) def action_possible(self): return True def do(self): self.check_set_results() self._done = True def check_set_results(self): self.accomplished = True @property def results(self): out = {"done": self._done, "accomplished": self.accomplished} return out def do_results(self): self.do() return self.results
      
      







私以外の誰かがこのライブラリの助けを借りて居心地の良い小さな世界を突然作成したい場合、箱から出してすぐに必要な低レベルのアクションのセットが含まれていると想定されます-座標による移動、オブジェクトの追跡、特定のオブジェクトまたはオブジェクトの検索、オブジェクトのピックアップなど。 d。 これらのアクションは、単独で使用することも、組み合わせて何らかの複雑な操作を生成することもできます。 このような複雑なアクションの例については、最初の実験の説明でさらに説明します。



第二に、すべての自尊心のあるアクティブなエージェントは、行動を計画できなければなりません。 したがって、この時代の活動のフェーズを計画と行動の2つの段階に分けます。 計画ツールとして、一貫して実行するアクションの単純なキューがあります。 しかし、すでに計画を立てている場合、もう一度考えることはありません。迅速に、断固として行動しなければなりません。 ターンの開始時に、アクティブオブジェクトがこの移動を計画する必要があるかどうかを判断し(開始のために、アクションのキューが空の場合に必要なものを検討します)、必要であると判断した場合に計画し、最終的にアクションを実行します。 計画が、急ぎに耐えない深刻なプロセスとして、コース全体をとるべきかどうかは議論の余地のある問題です。 私の目的のために、私はこれまでのところそうではないものに落ち着きました-私のエージェントは長い間考えず、同じ動きで計画を実行し始めます。



計画と行動
 class Agent(Entity): ... def live(self): ... if self.need_to_update_plan(): self.plan() if len(self.action_queue) > 0: current_action = self.action_queue[0] self.perform_action(current_action) while len(self.action_queue) > 0 and self.action_queue[0].instant: current_action = self.action_queue[0] self.perform_action(current_action) def need_to_update_plan(self): return len(self.action_queue) == 0 def perform_action(self, action): results = action.do_results() if results["done"] or not action.action_possible(): self.action_log.append(self.action_queue.pop(0)) return results ... ...
      
      







これに加えて、オブジェクトの状態などのエンティティを導入すると便利であるように思われます。 確かに、エージェントは気分ではなく、疲れていたり、濡れたり、毒になったり、あるいはその逆であったり、陽気でエネルギーに満ちているかもしれません。 時には同時にも。 したがって、オブジェクトに状態の配列を追加します。各状態は、時代の初めにオブジェクトに影響します。



状態コード
 class State(object): def __init__(self, subject): self.subject = subject self.duration = 0 def affect(self): self.duration += 1 class Entity(object): def __init__(self): ... self._states_list = [] ... ... def get_affected(self): for state in self._states_list: state.affect() def live(self): self.get_affected() self.z += 1 self.age += 1 ...
      
      







モデリングとトレーニングを行うには、アクションのアルゴリズムをどれだけうまく記述したか、トレーニングモデルを選択したかを評価できる必要があります。 これを行うには、シミュレーションの終了を判断し、結果を収集する方法を記述する機能を備えた単純なシミュレーションおよび評価モジュールを追加します。



このようなもの
 import copy def run_simulation(initial_field, check_stop_function, score_function, times=5, verbose=False): list_results = [] for iteration in range(times): field = copy.deepcopy(initial_field) while not check_stop_function(field): field.make_time() current_score = score_function(field) list_results.append(current_score) if verbose: print "Iteration: {0} Score: {1})".format(iteration+1, current_score) return list_results
      
      







この段階では、原則として、すべてが、ライブラリを使用する最初のシナリオであるエージェントをトレーニングしたくないが、アクションのロジックを独立して処方したい場合のモデリングを閉じる準備ができています。 この場合の手順は次のとおりです。



  1. 壁、山、家具、表面の種類など、世界で見たい静的オブジェクトを決定します。 それらを記述し、Entityクラスを継承します。 オブジェクトとSubstanceクラスでも同じことを行います。
  2. 適切なサイズの世界を作成し、これらのオブジェクトとオブジェクトの風景で埋めます。
  3. Actionクラスを継承し、必要なすべてのアクションを記述します。 Stateクラスについても同じことを行い、シミュレーションに必要な場合はそれらを示します。
  4. エージェントを継承して、エージェントのクラスを作成します。 サービス機能を追加し、計画プロセスを説明します。
  5. 私たちは、アクティブなエージェントで私たちの世界に住んでいます。
  6. アクションをデバッグし、作成の熟考を楽しむために、視覚化を推進できます。
  7. 最後に、視覚化を十分に行った後、シミュレーションを実行し、作成した世界で作成したルールに従って、作成したエージェントがどれだけうまく動作するかを評価します。


概念実証i



そこで、最初の実験の条件を発表します。





私たちの仕事は、生き物の集団ができるだけ早く増殖するように、真の性的生き物の計画手順を書くことです。



この場所を読んで、感謝の気持ちを込めて長いイラストで退屈することはありません。

ペアリングの例に関する複雑なアクションの実装の変形
 class GoMating(Action): def __init__(self, subject): super(GoMating, self).__init__(subject) self.search_action = SearchMatingPartner(subject) self.move_action = MovementToEntity(subject) self.mate_action = Mate(subject) self.current_action = self.search_action def action_possible(self): if not self.current_action: return False return self.current_action.action_possible() def do(self): if self.subject.has_state(states.NotTheRightMood): self._done = True return if self.results["done"]: return if not self.action_possible(): self._done = True return first = True while first or (self.current_action and self.current_action.instant) and not self.results["done"]: first = False current_results = self.current_action.do_results() if current_results["done"]: if current_results["accomplished"]: if isinstance(self.current_action, SearchMatingPartner): if current_results["accomplished"]: self.current_action = self.move_action self.current_action.set_objective(**{"target_entity": current_results["partner"]}) elif isinstance(self.current_action, MovementXY): self.current_action = self.mate_action self.current_action.set_objective(**{"target_entity": self.search_action.results["partner"]}) elif isinstance(self.current_action, Mate): self.current_action = None self.accomplished = True self._done = True else: self.current_action = None self._done = True else: break def check_set_results(self): self.accomplished = self._done
      
      







そして、モデルが機能すると判断した計画オプション
 class Creature(Agent): ... def plan(self): nearest_partner = actions.SearchMatingPartner(self).do_results()["partner"] if nearest_partner is None: chosen_action = actions.HarvestSubstance(self) chosen_action.set_objective(** {"target_substance_type": type(substances.Substance())}) self.queue_action(chosen_action) else: self_has_substance = self.count_substance_of_type(substances.Substance) partner_has_substance = nearest_partner.count_substance_of_type(substances.Substance) if partner_has_substance - self_has_substance > 2: self.queue_action(actions.GoMating(self)) else: chosen_action = actions.HarvestSubstance(self) chosen_action.set_objective(**{"target_substance_type": type(substances.Substance())}) self.queue_action(chosen_action) ...
      
      







機械学習と神々について



単純なモデリングが機能することを確認したら、楽しみの度合いを増やし、機械学習の可能性を追加し始めます。 この記事の執筆時点では、計画されているすべての機能が実装されているわけではありませんが、神について話すことを約束しました。



しかし、最初に、クリーチャーをどのように訓練したいかを決める必要があります。 リソースの検索とペアリングで同じタスクを実行します。 従来の方法で解決する場合は、最初に一連の機能を決定し、それに基づいて決定を下す必要があります。 次に、ランダムにまたは何らかの形で行動し、トレーニングとテストデータセットを収集して保存します。 次に、これらのデータセットでいくつかのモデルをトレーニングし、それらを比較して最適なモデルを選択します。 最後に、このモデルを使用して計画プロセスを書き直し、シミュレーションを実行して、何が起こるかを確認します。 そして、データを再コンパイルし、モデルを再トレーニングし、モデルを相互に再比較し、何が起こるかを再確認するために再起動することを意味する新しい機能を使用することになりました。



そして、理想的には何が欲しいでしょうか? 理想的には、機能セットを定義し、トレーニングモデルを構成し、既にデータセットを収集し、モデルをトレーニングし、それを計画プロセスに接続し、他のモデルまたは他のセットの結果と比較できる複数の実行の最終結果を提供するシミュレーションを実行したいと思いますサイン。



そして、ここに私がそれを想像する方法があります:





ここでは、いくつかの新しいオブジェクトが必要です。 まず、クリーチャーには、データセットを格納する何らかの種類のメモリが必要です。 彼女は、標識のセットを別々に覚えられるべきです。 別途、この機能セットで行われた決定の結果を追加します。 便利な形式でデータセットを返します。 さて、大学で教えられたすべてを忘れてください。



記憶の秘密
 class LearningMemory(object): def __init__(self, host): self.host = host self.memories = {} def save_state(self, state, action): self.memories[action] = {"state": state} def save_results(self, results, action): if action in self.memories: self.memories[action]["results"] = results else: pass def make_table(self, action_type): table_list = [] for memory in self.memories: if isinstance(memory, action_type): if "state" not in self.memories[memory] or "results" not in self.memories[memory]: continue row = self.memories[memory]["state"][:] row.append(self.memories[memory]["results"]) table_list.append(row) return table_list def obliviate(self): self.memories = {}
      
      







次に、エージェントにタスクを取得し、そのアクションの状況と結果を記憶する方法を教える必要があります。



割り当てを受け取る
 class Agent(Entity): def __init__(self): ... self.memorize_tasks = {} .... ... def set_memorize_task(self, action_types, features_list, target): if isinstance(action_types, list): for action_type in action_types: self.memorize_tasks[action_type] = {"features": features_list, "target": target} else: self.memorize_tasks[action_types] = {"features": features_list, "target": target} def get_features(self, action_type): if action_type not in self.memorize_tasks: return None features_list_raw = self.memorize_tasks[action_type]["features"] features_list = [] for feature_raw in features_list_raw: if isinstance(feature_raw, dict): if "kwargs" in feature_raw: features_list.append(feature_raw["func"](**feature_raw["kwargs"])) else: features_list.append(feature_raw["func"]()) elif callable(feature_raw): features_list.append(feature_raw()) else: features_list.append(feature_raw) return features_list def get_target(self, action_type): if action_type not in self.memorize_tasks: return None target_raw = self.memorize_tasks[action_type]["target"] if callable(target_raw): return target_raw() elif isinstance(target_raw, dict): if "kwargs" in target_raw: return target_raw["func"](**target_raw["kwargs"]) else: return target_raw["func"]() else: return target_raw def queue_action(self, action): if type(action) in self.memorize_tasks: self.private_learning_memory.save_state(self.get_features(type(action)), action) self.public_memory.save_state(self.get_features(type(action)), action) self.action_queue.append(action) def perform_action_save_memory(self, action): self.chosen_action = action if type(action) in self.memorize_tasks: results = self.perform_action(action) if results["done"]: self.private_learning_memory.save_results(self.get_target(type(action)), action) self.public_memory.save_results(self.get_target(type(action)), action) else: results = self.perform_action(action) ...
      
      







, , , - , , , , , , . , , - -, , , .



Demiurge, . , , insert_object. , :



 class Demiurge(object): def handle_creation(self, creation, refuse): pass class Field(object): def __init__(self, length, height): ... self.demiurge = None ... def insert_object(self, x, y, entity_object, epoch_shift=0): if self.demiurge is not None: refuse = False self.demiurge.handle_creation(entity_object, refuse) if refuse: return assert x < self.length assert y < self.height self.__field[y][x][-1] = entity_object entity_object.z = self.epoch + epoch_shift entity_object.board = self entity_object.x = x entity_object.y = y ...
      
      







:





. — - . . — , , . , — . — , , .



Proof of concept II



だから、リソースと偽りの性の生き物を集めることで同じ問題を解決してみましょう。タスクは非常に単純なので、厳密に定義されたアルゴリズムの助けを借りて可能になるよりも、機械学習の助けを借りてそれを解決できる可能性は低いです。しかし、作業コンセプトを認識するために、私たちのコレクターが種として不本意または繁殖不能から絶滅しないようにすれば十分です。



以下は、このような問題を解決する例の全文です。





 # Create deity class Priapus(field.Demiurge): # Create deity def __init__(self): self.public_memory = brain.LearningMemory(self) self.public_decision_model = SGDClassifier(warm_start=True) def handle_creation(self, creation, refuse): if isinstance(creation, entities.Creature): creation.public_memory = self.public_memory creation.public_decision_model = self.public_decision_model creation.memory_type = "public" creation.model_type = "public" creation.memory_batch_size = 20 if creation.sex: def difference_in_num_substance(entity): nearest_partner = actions.SearchMatingPartner(entity).do_results()["partner"] if nearest_partner is None: return 9e10 else: self_has_substance = entity.count_substance_of_type(substances.Substance) partner_has_substance = nearest_partner.count_substance_of_type(substances.Substance) return partner_has_substance - self_has_substance def possible_partners_exist(entity): find_partner = actions.SearchMatingPartner(entity) search_results = find_partner.do_results() return float(search_results["accomplished"]) features = [{"func": lambda creation: float(creation.has_state(states.NotTheRightMood)), "kwargs": {"creation": creation}}, {"func": difference_in_num_substance, "kwargs": {"entity": creation}}, {"func": possible_partners_exist, "kwargs": {"entity": creation}}] creation.set_memorize_task(actions.GoMating, features, {"func": lambda creation: creation.chosen_action.results["accomplished"], "kwargs": {"creation": creation}}) def plan(creature): if creature.sex: try: # raise NotFittedError current_features = creature.get_features(actions.GoMating) current_features = np.asarray(current_features).reshape(1, -1) if creature.public_decision_model.predict(current_features): go_mating = actions.GoMating(creature) creature.queue_action(go_mating) return else: harvest_substance = actions.HarvestSubstance(creature) harvest_substance.set_objective( **{"target_substance_type": type(substances.Substance())}) creature.queue_action(harvest_substance) return except NotFittedError: chosen_action = random.choice( [actions.GoMating(creature), actions.HarvestSubstance(creature)]) if isinstance(chosen_action, actions.HarvestSubstance): chosen_action.set_objective( **{"target_substance_type": type(substances.Substance())}) creature.queue_action(chosen_action) return else: harvest_substance = actions.HarvestSubstance(creature) harvest_substance.set_objective(**{"target_substance_type": type(substances.Substance())}) creature.queue_action(harvest_substance) creation.plan_callable = plan universe = field.Field(60, 40) # Create sample universe (length, height universe.set_demiurge(Priapus()) # Assign deity to universe # Fill universe with blanks, blocks, other scenery if necessary for y in range(10, 30): universe.insert_object(20, y, field.Block()) for x in range(21, 40): universe.insert_object(x, 10, field.Block()) for y in range(10, 30): universe.insert_object(40, y, field.Block()) universe.populate(entities.Creature, 20) # Populate universe with creatures def check_stop_function(field): return field.epoch >= 500 def score_function(field): stats = field.get_stats() if "Creature" not in stats: return 0 else: return stats["Creature"] res = modelling.run_simulation(universe, check_stop_function, score_function, verbose=True, times=30) print res print np.asarray(res).mean()
      
      







おわりに



, , - . ( ) . :





, , , -, , -, . , , - , -, , . , , . , .



github. pygame sklearn , .



All Articles