集団の進化をPython を用いてシミュレーションしてみる。 第2回。


先日からPythonの勉強を兼ねて、孤独なミュータント問題の進化の形質の伝播をシミュレートするということに取り組んでいる。

今回、違う形での可視化に挑戦している。

具体的には、散布図的な表現ではなく、ピクセルのような形で可視化をしている。

実際に書いたコードがこちら。

# 必要なライブラリのインポート
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import random

# 初期設定
# Parameters
population_size = 1000
generations = 30
survival_rate = 0.5
trait_propagation_probability = 0.5
max_trials = 50  # Number of trials to simulate

# 個体群の初期化(0: 形質を持たない個体, 1: 形質を持つ個体, -1: 死んだ個体)
population = np.zeros(population_size)  # 全ての個体は最初形質を持たない

# 形質を持つ個体の初期設定
# ケース1: 1個体のみ形質を持つ
population[0] = 1
# ケース2: ランダムな2個体が形質を持つ
population[random.sample(range(population_size), 2)] = 1


# 2次元空間での個体群の初期配置
# 個体群の位置をランダムに生成(0から1の範囲内)
positions = np.random.rand(population_size, 2)

# 形質の伝播と可視化のための修正されたコードをここに実装します。
# 各世代の状態を保存するリストを再初期化
generation_states = [population.copy()]


def simulate_trait_spread_with_trials(population_size, generations, survival_rate, trait_propagation_probability, max_trials):
    side_length = int(np.sqrt(population_size))
    trial_results = []

    for trial in range(1, max_trials + 1):
        grid = np.zeros((side_length, side_length))
        first_trait_x, first_trait_y = np.random.randint(0, side_length, size=2)
        grid[first_trait_x, first_trait_y] = 1  # Initialize the first trait-bearing individual

        generation_states = [grid.copy()]
        for gen in range(1, generations + 1):
            new_grid = np.zeros_like(grid)
            trait_exist = False
            for x in range(side_length):
                for y in range(side_length):
                    if grid[x, y] == 1 and np.random.rand() < survival_rate:
                        trait_exist = True
                        new_grid[x, y] = 1  # The individual survives
                        # Propagate the trait to adjacent individuals
                        for dx in [-1, 0, 1]:
                            for dy in [-1, 0, 1]:
                                nx, ny = x + dx, y + dy
                                if 0 <= nx < side_length and 0 <= ny < side_length:
                                    if np.random.rand() < trait_propagation_probability:
                                        new_grid[nx, ny] = 1
            if not trait_exist:  # All trait-bearing individuals have perished
                break
            grid = new_grid
            generation_states.append(grid.copy())

        trial_results.append((generation_states, (first_trait_x, first_trait_y)))

    return trial_results

import matplotlib.pyplot as plt
import os

def visualize_and_save_generation_process(trial_results, side_length, output_dir="simulation_results"):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    for trial, (generation_states, first_trait_pos) in enumerate(trial_results, start=1):
        for gen, state in enumerate(generation_states):
            plt.figure(figsize=(8, 8))
            display_grid = np.full((side_length, side_length, 3), [0.75, 0.75, 0.75])  # Default color
            for x in range(side_length):
                for y in range(side_length):
                    if state[x, y] == 1:
                        color = [1.0, 0.0, 0.0] if (x, y) == first_trait_pos and gen == 0 else [1.0, 1.0, 0.0]
                        display_grid[x, y] = color
            plt.imshow(display_grid, interpolation='nearest')
            plt.title(f"Trial {trial} - Generation {gen}")
            plt.axis('off')
            filename = f"trial_{trial}_gen_{gen}.png"
            plt.savefig(os.path.join(output_dir, filename))
            plt.close()  # Close the figure to free up memory







import imageio

def create_gif_from_pngs(png_directory, output_gif_path, duration=0.5):
    # ディレクトリ内の全PNGファイルを取得
    png_files = sorted([f for f in os.listdir(png_directory) if f.endswith('.png')],
                       key=lambda x: (int(x.split('_')[1]), int(x.split('_')[3].split('.')[0])))
    images = [imageio.imread(os.path.join(png_directory, f)) for f in png_files]
    # 画像リストをGIFとして保存
    imageio.mimsave(output_gif_path, images, duration=duration)



# Simulation and visualization
population_size = 1000
generations = 30
survival_rate = 0.5
trait_propagation_probability = 0.5
max_trials = 30  # Adjust based on your requirements

trial_results = simulate_trait_spread_with_trials(population_size, generations, survival_rate, trait_propagation_probability, max_trials)
visualize_and_save_generation_process(trial_results, int(np.sqrt(population_size)))

# GIFアニメーションの作成
create_gif_from_pngs("simulation_results", "simulation_animation.gif", duration=0.5)



想定した内容としてはまず1個体が形質を獲得するが、その個体の生存確率は50%としている。

つまり、形質を獲得してもそれが伝播する前に死んでしまうと仮定している。

実際に出来上がったものがこちら。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です