OpenAIの最新モデル


先日,OpenAIの最新のモデルとしてo3 の完全版が発表された.今回はその性能を試してみたい.そこで以前投稿したWeasel Programをo3で試してみる.

プロンプトと出力結果は下記.

Weasel Program を可能な限りリッチな表現を用いたコードで書いて.
その過程をアニメーションとして出力できるようにして.
"""
Rich Weasel Program with animated evolution preview
Author: OpenAI o3  (Apr 18 2025, JST)

Requirements:
    pip install matplotlib imageio tqdm
    # (tqdm は進捗バー用・無くても動作します)
"""

import random, string, time, itertools, textwrap, sys, os
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter, FFMpegWriter
import imageio.v2 as imageio
from tqdm import tqdm

# ──────────────────────────────────────────────────────────────────
#  1. 進化パラメータ
# ──────────────────────────────────────────────────────────────────
TARGET          = "METHINKS IT IS LIKE A WEASEL"
POP_SIZE        = 100               # 1 世代あたり作る子供の数
MUT_RATE        = 0.05              # 1 文字当たりの突然変異率
LINEAR_SELECT   = True              # True: 線形ランキング選択, False: トーナメント
SAVE_EVERY_N    = 1                 # 何世代ごとにフレームを保存するか
MAX_GENERATIONS = 5000              # 安全装置(通常は数百で収束)
SEED            = 42
random.seed(SEED)

ALPHABET = string.ascii_uppercase + " "
L        = len(TARGET)

# ──────────────────────────────────────────────────────────────────
#  2. 遺伝的オペレータ
# ──────────────────────────────────────────────────────────────────
def random_string():
    return "".join(random.choice(ALPHABET) for _ in range(L))

def mutate(parent):
    chars = list(parent)
    for i, ch in enumerate(chars):
        if random.random() < MUT_RATE:
            chars[i] = random.choice(ALPHABET)
    return "".join(chars)

def fitness(candidate):
    return sum(c==t for c,t in zip(candidate, TARGET))

def breed(parent, k=POP_SIZE):
    return [mutate(parent) for _ in range(k)]

def select(pop):
    """return best individual; optionally weighted/linear selection"""
    ranked = sorted(pop, key=fitness, reverse=True)
    if LINEAR_SELECT:
        # 線形ランキング:上位ほど採択確率が高い
        weights = list(reversed(range(1, len(pop)+1)))
        return random.choices(ranked, weights=weights, k=1)[0]
    return ranked[0]

# ──────────────────────────────────────────────────────────────────
#  3. 進化ループ(各世代のベスト個体・スコアを記録)
# ──────────────────────────────────────────────────────────────────
history_strings, history_scores = [], []
parent = random_string()

for gen in tqdm(range(MAX_GENERATIONS), desc="Evolving"):
    # 子孫生成 → 最良選択
    children   = breed(parent)
    candidate  = max(children, key=fitness)
    # 記録
    if gen % SAVE_EVERY_N == 0:
        history_strings.append(candidate)
        history_scores .append(fitness(candidate))
    # 目標一致なら終了
    if candidate == TARGET:
        print(f"\n>>> Finished at generation {gen}")
        break
    parent = candidate
else:
    print("Reached MAX_GENERATIONS without perfect match :(")

# ──────────────────────────────────────────────────────────────────
#  4. アニメーション作成
# ──────────────────────────────────────────────────────────────────
def make_animation(strings, scores, interval=120, dpi=120,
                   save_gif=True, save_mp4=False, fname="weasel_evolution"):
    gens = list(range(0, len(strings)*SAVE_EVERY_N, SAVE_EVERY_N))

    # Figure レイアウト
    fig, (ax_txt, ax_score) = plt.subplots(2, 1, figsize=(10,4.8),
                                           gridspec_kw=dict(height_ratios=[2,1]))
    plt.tight_layout()

    # ① テキスト部
    txt_obj = ax_txt.text(0.5, 0.5, "", fontsize=26, ha='center', va='center',
                          family="monospace")
    ax_txt.axis("off")

    # ② スコア推移
    ax_score.set_xlim(0, gens[-1] if gens else 1)
    ax_score.set_ylim(0, L)
    ax_score.set_xlabel("Generation")
    ax_score.set_ylabel("Fitness")
    line, = ax_score.plot([], [], lw=2)
    ax_score.grid(alpha=.3)

    # 更新関数
    def update(i):
        txt_obj.set_text(strings[i])
        line.set_data(gens[:i+1], scores[:i+1])
        return txt_obj, line

    anim = FuncAnimation(fig, update, frames=len(strings),
                         interval=interval, blit=True)

    # 保存
    if save_gif:
        anim.save(f"{fname}.gif", writer=PillowWriter(fps=1000/interval), dpi=dpi)
    if save_mp4:
        anim.save(f"{fname}.mp4", writer=FFMpegWriter(fps=1000/interval), dpi=dpi)
    plt.close(fig)
    return anim

animation = make_animation(history_strings, history_scores,
                           interval=120, dpi=120,
                           save_gif=True, save_mp4=False)

# ──────────────────────────────────────────────────────────────────
#  5. Jupyter 表示用(.gif を自動表示)
# ──────────────────────────────────────────────────────────────────
try:
    from IPython.display import HTML, Image
    display(HTML(animation.to_jshtml()))  # JS 形式(ブラウザキャッシュが効く)
except Exception:
    pass

print("\nAnimated evolution saved as 'weasel_evolution.gif'")

コメントを残す

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