2025年3月16日日曜日

三輪眞弘について生成AIに聞いてみた(5):「またりさま」のプログラムの作成(Claudeの場合)

 「またりさま」の状態遷移規則をプロンプトとして説明し、ChatGPTおよびGeminiにプログラムを生成させることに成功したことについては既に報告済ですが、この記事では、Claudeに対して同じ指示をしてプログラムを生成させた結果を報告します。Claudeも意図した動きをするプログラムの生成には成功しました。

 のみならず、ClaudeもまたGemini同様、一回では「x1とx2の計算結果でx2を更新してからx2とx3の計算をするというように順番に計算」という指示がプログラムに反映されず、配列全体のコピーを作って、全ての変数に対して同時に一気に排他的論理和の計算結果で更新をかける仕様のプログラムを生成したため、Geminiの時と同様、その点についての指示を再度プロンプトとして与え、最後に初期状態に戻ったら停止する処理を追加するプロンプトを与えることになりました。以下、プロンプトと回答を順次示し、実行結果は割愛します。

 なお、線形フィードバックシフトレジスタに言及したのはClaudeのみでした。

(2025.3.16)

*     *     *

プロンプト:

「8個の[0,1]変数x1~x8について、x1とx2、x2とx3,...x8とx1というように隣り合った変数間で排他的論理和を計算します。 x1とx2の計算結果でx2を更新してからx2とx3の計算をするというように順番に計算をします。変数の値の変化を表示するプログラムを作って下さい。計算は63回繰り返します。初期値は[0,0,0,1,0,1,0,1]とします。」

Claude (2025.3.13)

8つの変数の排他的論理和を順番に計算し、値の変化を表示するプログラムを作ります。

def xor_simulation(initial_values, iterations):

    # 値の変化を保存するリスト

    history = [list(initial_values)]

    

    # 現在の値

    current = list(initial_values)

    

    # 指定された回数だけ計算を繰り返す

    for i in range(iterations):

        new_values = list(current)

        

        # 各変数について隣り合った変数との排他的論理和を計算して更新

        for j in range(8):

            next_idx = (j + 1) % 8  # 隣の変数のインデックス(x8の次はx1)

            

            # 排他的論理和を計算

            xor_result = current[j] ^ current[next_idx]

            

            # 次の変数を更新

            new_values[next_idx] = xor_result

            

        # 更新された値を現在の値として設定

        current = new_values

        

        # 履歴に追加

        history.append(list(current))

    

    return history


# 初期値の設定

initial_values = [0, 0, 0, 1, 0, 1, 0, 1]


# 63回の計算を実行

results = xor_simulation(initial_values, 63)


# 結果の表示

print("Iteration | x1 x2 x3 x4 x5 x6 x7 x8")

print("-" * 32)


for i, values in enumerate(results):

    values_str = " ".join(str(v) for v in values)

    print(f"{i:9d} | {values_str}")

 

このプログラムは、8つの変数x1~x8について排他的論理和(XOR)を計算し、各イテレーションごとの変数の値を表示します。

プログラムの動作:

  1. 初期値 [0,0,0,1,0,1,0,1] から開始します
  2. 各ステップで、各変数xjとその隣の変数x(j+1)の排他的論理和を計算し、x(j+1)を更新します
  3. x8とx1の計算結果はx1を更新します(環状になっています)
  4. これを63回繰り返します

結果は表形式で出力され、各行が1回のイテレーション後の8つの変数の状態を示します。初期状態(Iteration 0)から始まり、63回の更新後の最終状態まで表示されます。

このプログラムを実行すると、変数の値がどのように変化していくかを確認できます。


*     *     *

プロンプト:

「x1とx2の排他的論理和でx2を更新してから、x2とx3の計算をします。これを63回繰り返します。」

Claude (2025.3.13)

おっしゃる通り、私の解釈が間違っていました。各ステップでは前の変数との排他的論理和で変数を更新し、その更新した値を使って次の計算を行う必要があります。修正したプログラムを作成します。

def sequential_xor_simulation(initial_values, iterations):

    # 値の変化を保存するリスト

    history = [list(initial_values)]

    

    # 現在の値

    values = list(initial_values)

    

    # 指定された回数だけ計算を繰り返す

    for i in range(iterations):

        # 1回のイテレーションで、順番に更新

        for j in range(8):

            current_idx = j

            next_idx = (j + 1) % 8  # 隣の変数のインデックス(x8の次はx1)

            

            # 排他的論理和を計算して、次の変数を即時更新

            values[next_idx] = values[current_idx] ^ values[next_idx]

        

        # 1回のイテレーション終了後の状態を記録

        history.append(list(values))

    

    return history


# 初期値の設定

initial_values = [0, 0, 0, 1, 0, 1, 0, 1]


# 63回の計算を実行

results = sequential_xor_simulation(initial_values, 63)


# 結果の表示

print("Iteration | x1 x2 x3 x4 x5 x6 x7 x8")

print("-" * 32)


for i, values in enumerate(results):

    values_str = " ".join(str(v) for v in values)

    print(f"{i:9d} | {values_str}")

 

この修正版プログラムでは、次のように処理を行います:

  1. 初期値 [0,0,0,1,0,1,0,1] から開始します
  2. 各イテレーションで:
    • x1とx2の排他的論理和を計算し、x2を更新します
    • 更新後のx2とx3の排他的論理和を計算し、x3を更新します
    • 同様に続けて、x7と更新後のx8の排他的論理和を計算し、x8を更新します
    • 最後に更新後のx8とx1の排他的論理和を計算し、x1を更新します
  3. これを63回繰り返します

各イテレーションごとに8つの変数の状態が記録され、表示されます。これで、変数の値が連続的にどのように変化していくかを確認できます。

*     *     *

プロンプト:

「全ての変数が初期状態に戻ったら停止する処理を加えてください。」

Claude (2025.3.13)

全ての変数が初期状態に戻ったら停止する機能を追加します。

def sequential_xor_simulation_with_stop(initial_values):

    # 値の変化を保存するリスト

    history = [list(initial_values)]

    

    # 現在の値

    values = list(initial_values)

    

    # 繰り返し回数のカウンター

    iterations = 0

    

    while True:

        iterations += 1

        

        # 1回のイテレーションで、順番に更新

        for j in range(8):

            current_idx = j

            next_idx = (j + 1) % 8  # 隣の変数のインデックス(x8の次はx1)

            

            # 排他的論理和を計算して、次の変数を即時更新

            values[next_idx] = values[current_idx] ^ values[next_idx]

        

        # 1回のイテレーション終了後の状態を記録

        history.append(list(values))

        

        # 初期状態に戻ったかチェック

        if values == initial_values:

            print(f"初期状態に戻りました!繰り返し回数: {iterations}")

            break

            

        # 無限ループ防止(オプション)

        if iterations > 1000:

            print("1000回の繰り返しで初期状態に戻りませんでした。")

            break

    

    return history, iterations


# 初期値の設定

initial_values = [0, 0, 0, 1, 0, 1, 0, 1]


# 計算を実行(初期状態に戻るまで)

results, total_iterations = sequential_xor_simulation_with_stop(initial_values)


# 結果の表示

print(f"\n全繰り返し回数: {total_iterations}")

print("\nIteration | x1 x2 x3 x4 x5 x6 x7 x8")

print("-" * 32)


for i, values in enumerate(results):

    values_str = " ".join(str(v) for v in values)

    print(f"{i:9d} | {values_str}")


このプログラムでは、次の機能を追加しました:

  1. 各イテレーション後に、現在の値が初期値と完全に一致するかをチェックします
  2. 初期値に戻った場合は、メッセージを表示して繰り返しを停止します
  3. 安全策として、1000回以上繰り返しても初期状態に戻らない場合は停止するようにしました(無限ループ防止)

このプログラムは、以下のように動作します:

  • 初期値から始め、前述の方法で変数を更新していきます
  • 各イテレーション後に初期状態に戻ったかチェックします
  • 戻った場合は停止し、何回のイテレーションで初期状態に戻ったかを表示します
  • 全ての結果(各イテレーションでの変数の状態)を表形式で出力します

8ビットの線形フィードバックシフトレジスタ(LFSR)のような動作をするため、必ず有限回の繰り返しで初期状態に戻ります。このプログラムではその周期を検出できます。


0 件のコメント:

コメントを投稿