見出し画像

マンカラ×遺伝的アルゴリズム

「遺伝的アルゴリズム」という文字列を見ただけで、ちょっとワクワクするようになったら、もうそれは、末期です。

そんな末期患者の妄想に、お付き合いください。


今日はマンカラ

アソビ大全にも収録されていたし、昔よりはルールを知っている人が増えたんじゃないかな?単純なゲームと侮っているとドツボにはまると思う。…で、これで満足できないぞ、という人はぜひ、「トラヤヌス」というボードゲームを調べてみて(or機会があれば遊んでみて)ほしい。なんでここにマンカラ要素を入れたかな、とびっくりできると思う。

設計してみよう!(してもらおう?)

…さて本題。遺伝的アルゴリズムで強いマンカラプレイヤーを作るには、どういうパラメータ設計をすればいいだろうか?4oくんの意見を聞いてみよう。

マンカラをテーマに遺伝的アルゴリズムを用いてAIを作成する場合、以下のようなパラメータを調整することが考えられます:

### 1. 遺伝子表現
- **個体(遺伝子)の表現方法**:
- 個体の遺伝子をマンカラの盤面状態とするか、次の手を選ぶための戦略パターンとするかを決めます。
- 例:次の手を決めるルールセットを遺伝子として表現する。

### 2. 初期集団の生成
- **初期個体の生成方法**:
- ランダムに生成するか、ある程度のルールに基づいて生成するかを決めます。
- ランダム生成の場合、非常に多様な個体を初期集団として用意できます。

### 3. 適応度関数
- **評価方法**:
- 各個体のパフォーマンスを評価するための基準を設けます。
- 勝利数、石の数、戦略の多様性などを評価ポイントとします。

### 4. 選択方法
- **選択アルゴリズム**:
- 適応度の高い個体を選択する方法を決めます。
- ルーレット選択、トーナメント選択、エリート選択などがあります。
- 選択圧を調整するために、選択の確率を調整します。

### 5. 交叉(クロスオーバー)
- **交叉方法**:
- 遺伝子をどのように組み合わせるかを決めます。
- 一点交叉、二点交叉、均一交叉などがあります。

### 6. 突然変異
- **突然変異の確率と方法**:
- 突然変異をどの程度の確率で発生させるかを決めます。
- 突然変異の内容も調整します(例えば、手をランダムに変更するなど)。

### 7. 世代交代
- **世代交代の方法**:
- 親個体と子個体のどちらを次の世代に残すかを決めます。
- 世代交代率を調整し、エリート個体の保持を考慮します。

### 8. 収束判定
- **アルゴリズムの停止条件**:
- 一定の世代数、一定の適応度に達した場合、収束したとみなす条件を設定します。

### パラメータの例
population_size = 100 # 初期集団のサイズ
num_generations = 1000 # 進化の世代数
mutation_rate = 0.01 # 突然変異の確率
crossover_rate = 0.7 # 交叉の確率
selection_method = 'tournament' # 選択方法
tournament_size = 5 # トーナメント選択のサイズ
elite_size = 5 # エリート選択の個体数

これらのパラメータを調整しながら、最適な設定を見つけていくことで、マンカラのAIを進化させることができます。また、各パラメータの効果を実験しながら観察することが重要です。

ChatGPTの出力

掘り下げて面白そうなのは、断然1の「遺伝子をどう作るか」のところだと思うので、掘り下げてもらおうと思います。

遺伝子の構築例

次の手を決めるルールセットを遺伝子として表現する具体例について説明します。ここでは、マンカラのゲームの次の手を決定するためのいくつかのルールを遺伝子として表現し、それらのルールを基に行動を選択する方法を示します。

ルールセットの遺伝子表現

マンカラでは、各手で選択するピット(穴)を決定する必要があります。以下のようなルールセットを遺伝子として表現することができます:
ルールのタイプ:ルールには複数のタイプがあります。例えば、以下のようなルールタイプがあります。
攻撃ルール:相手の石を奪うことを優先する。
防御ルール:自分の石を安全に守る。
貯蓄ルール:自分のストアに石を集める。
ルールの条件:ルールが適用される条件を定義します。
石の数:特定のピットに何個の石があるか。
相手のピットの状態:相手の特定のピットに何個の石があるか。
自分のストアの状態:自分のストアに何個の石があるか。
行動:条件が満たされたときに取る行動を定義します。
ピットの選択:特定のピットから石を動かす。

具体例
以下に、遺伝子としてのルールセットの具体例を示します。ここでは、遺伝子をリストとして表現し、各要素がルールを示します。

# ルールの遺伝子をリストで表現
# 各ルールは (ルールタイプ, 条件, 行動) のタプルで表現される
# ルールタイプは整数値で表現(1: 攻撃ルール, 2: 防御ルール, 3: 貯蓄ルール)
# 条件は (条件タイプ, ピット番号, 石の数) のタプルで表現
# 行動は (選択するピット) で表現

genome = [
(1, (1, 3, 4), 2), # 攻撃ルール:ピット3に4個の石があるなら、ピット2を選択
(2, (2, 5, 2), 1), # 防御ルール:ピット5に2個の石があるなら、ピット1を選択
(3, (3, 0, 0), 6), # 貯蓄ルール:ストアが空なら、ピット6を選択
]

ChatGPTの出力

「タプル」って、組とか、そういう意味なんだと思うんだけど、Pythonの人しか使わないまであるよね?そんなことない?

条件1、条件2、条件3…と条件6くらいまでに引っかからなかった時は行動7みたいな形にしておけば、面倒くさい例外処理も書かなくて済みそう。

適応度関数

遺伝子を評価するための適応度関数も必要です。適応度関数は、ルールセットがどれだけ効果的かを評価します。例えば、以下のようにして適応度を計算できます:

def evaluate_genome(genome):
score = 0
# マンカラのシミュレーションを実行し、得点を計算
# 各ルールを適用し、ゲームの勝利数やストアの石の数を評価
for game in range(num_simulations):
score += run_mancala_simulation(genome)
return score / num_simulations

遺伝的アルゴリズムの実装例

以下は、遺伝的アルゴリズムの基本的な流れの実装例です:

import random

def create_initial_population(size):
return [create_random_genome() for _ in range(size)]

def create_random_genome():
# ランダムにルールセットを生成
return [(random.randint(1, 3), (random.randint(1, 3), random.randint(0, 5), random.randint(0, 6)), random.randint(0, 5)) for _ in range(num_rules)]

def crossover(parent1, parent2):
crossover_point = random.randint(0, len(parent1))
return parent1[:crossover_point] + parent2[crossover_point:]

def mutate(genome, mutation_rate):
for i in range(len(genome)):
if random.random() < mutation_rate:
genome[i] = create_random_rule()
return genome

def create_random_rule():
return (random.randint(1, 3), (random.randint(1, 3), random.randint(0, 5), random.randint(0, 6)), random.randint(0, 5))

# 適応度の評価と世代交代
population = create_initial_population(population_size)
for generation in range(num_generations):
population = sorted(population, key=lambda genome: evaluate_genome(genome), reverse=True)
next_generation = population[:elite_size]
while len(next_generation) < population_size:
parent1, parent2 = random.choices(population[:tournament_size], k=2)
child = crossover(parent1, parent2)
child = mutate(child, mutation_rate)
next_generation.append(child)
population = next_generation

best_genome = population[0]

このようにして、マンカラの次の手を決めるルールセットを遺伝子として表現し、遺伝的アルゴリズムを用いて最適なルールセットを進化させることができます。

ChatGPTの出力

4oくん、ここまで考えてくれるのね。

まとめ

久々に遺伝的アルゴリズム分を補給しました。私はホクホクでしたが、皆さんはいかがだったでしょうか。(プログラム類アレルギーの方には、申し訳ない回になってしまいました。いい感じに読み飛ばしていただければ…ってここに書いても遅いか)

そのうち、遺伝的アルゴリズムに使えそうな部品群を揃えておいて、どんなゲームでもそれなりの強さまで引き上げられるセットを用意しておきたいな、と思えるようになりました。それがChatGPTとちょっと会話したらつかえるとかになったらボードゲームをテストしたい人にはいいよなぁ、と。

…というわけで、今日は、ちょっと夢が広がった、ということで、このへんで。ほなね!

例のAI画像のコーナー

マンカラも、かなり生成しにくいゲームな気がするなぁ。。。と思いながら画像を出していたのですが、案の定。

兄弟でマンカラを遊ぶ。渋い。

マンカラというか、囲碁というか、なんというか、そういう盤面のものが生成され続けましたとさ。



いただいたサポートは、きっと、ドイツアマゾンからの送料に変わると思います。 温かいご支援、お待ちしております。