エレファント・ビジュアライザー調査記録

ビジュアルプログラミングで数式の変形を表すことを考えていくブロクです。

人工知能的代数学(3)

置換の分類(2)

ChatGPT で以下のように入力しました。

置換を隣接互換の積に分解するプログラムを書いてください

これは正しいプログラムを得ることができました。

def adjacent_transpositions(perm):
    """
    指定された置換を隣接互換の積に分解します。

    :param perm: 置換リスト
    :return: 隣接互換のリスト
    """
    # 初期の状態として、置換をコピーする
    perm = perm[:]
    n = len(perm)
    transpositions = []

    # シンプルなソートアルゴリズムを使って隣接互換を生成
    for i in range(n):
        # 正しい位置に要素を配置
        for j in range(1, n - i):
            if perm[j - 1] > perm[j]:
                # 隣接する要素を交換する
                perm[j - 1], perm[j] = perm[j], perm[j - 1]
                # その交換を隣接互換として記録
                transpositions.append((j - 1, j))

    return transpositions

# 例として置換 [2, 3, 1] を隣接互換の積に分解
perm = [2, 3, 1]
result = adjacent_transpositions(perm)

print("隣接互換:", result)

続いて以下のように入力しました。

置換を隣接互換の積に分解したときの隣接互換の個数と、その置換の転倒数が等しいかどうかを調べるプログラムを書いてください

すると以下のようになりました。これは隣接互換のリストは作っていないのですがやっていることは上のものと同じです。

def count_inversions(arr):
    """
    配列内の転倒数を計算します。

    :param arr: 入力配列
    :return: 転倒数
    """
    n = len(arr)
    inversions = 0
    # すべてのペアを調べて、逆順にあるものをカウント
    for i in range(n):
        for j in range(i + 1, n):
            if arr[i] > arr[j]:
                inversions += 1
    return inversions

def adjacent_transpositions_count(perm):
    """
    隣接互換によって置換を整列するための操作数を計算します。

    :param perm: 置換リスト
    :return: 隣接互換の個数
    """
    n = len(perm)
    transpositions_count = 0
    # シンプルなバブルソートで隣接互換の数をカウント
    for i in range(n):
        for j in range(1, n - i):
            if perm[j - 1] > perm[j]:
                # 隣接する要素を交換
                perm[j - 1], perm[j] = perm[j], perm[j - 1]
                # 交換が発生したのでカウントを増やす
                transpositions_count += 1
    return transpositions_count

# 例として置換 [3, 1, 2, 4] を考えます
perm = [3, 1, 2, 4]

# 転倒数を計算
inversions = count_inversions(perm)

# 隣接互換の数を計算
transpositions_count = adjacent_transpositions_count(perm[:])  # コピーを渡す

# 結果を表示
print("転倒数:", inversions)
print("隣接互換の数:", transpositions_count)
print("等しいかどうか:", inversions == transpositions_count)

プログラムの改造

これに assert とコメントを入れます。

def adjacent_transpositions_count(perm):
    """
    隣接互換によって置換を整列するための操作数を計算します。

    :param perm: 置換リスト
    :return: 隣接互換の個数
    """
    n = len(perm)
    transpositions_count = 0
    # シンプルなバブルソートで隣接互換の数をカウント
    # (1-開始) 転倒数は元の転倒数
    for i in range(n):
        # (2-開始) perm[n-i] から後の転倒数は 0
        for j in range(1, n - i):
            # (3-開始) perm[0] から perm[j-1] までの中で perm[j-1] が最大
            if perm[j - 1] > perm[j]:
                # (4-開始)
                inversions_before = count_inversions(perm)
                # 隣接する要素を交換
                perm[j - 1], perm[j] = perm[j], perm[j - 1]
                # 交換が発生したのでカウントを増やす
                transpositions_count += 1
                # (4-終了) 交換によって転倒数は 1 減っている
                assert count_inversions(perm) == inversions_before - 1
            # (3-終了) perm[0] から perm[j] までの中で perm[j] が最大
            assert all(x < perm[j] for x in perm[:j])        
        # (2-終了-1) perm[0] から perm[n-i-1] までの中で perm[n-i-1] が最大
        assert all(x < perm[n-i-1] for x in perm[:n-i-1])        
        # (2-終了-2) perm[n-i-1] から後の転倒数は 0
        assert count_inversions(perm[n-i-1:]) == 0       
    # (1-終了) perm[0] から後(全体)の転倒数は 0
    assert count_inversions(perm) == 0
    return transpositions_count

このプログラムは有限回のループなので終了します。コメントに書いたことをたどると、

  • このプログラムで得られる隣接互換の個数は転倒数に等しい
  • このプログラムが終了したときの転倒数は 0

ということがわかります。転倒数が 0 のときは恒等置換なので、元の置換は隣接互換の積で表されます。隣接互換は互換なので、元の置換は互換の積で表されます。

次に、互換にこのプログラムを適用するとどうなるかを考えます。そのためにコメントを書き換えたいと思います。これは次回以降やる予定です。

人工知能的代数学(2)

置換の分類

Visual Studio でデザイナーが開けなくなったので、C# を使うのをやめて、Google Colab というのを使ってみました。これは Python を使うことになります。これにはプログラムを書いてくれる機能があって、「 n を指定して、 n 次の対称群のすべての元を偶置換と奇置換に分類するプログラムを書いてください」と入力すると、正しい結果が得られました。これは「置換のパリティー」などで書いたことで、普通の数学の本に書かれているものです。

Visual StudioPython を使えるようにしていたことがわかったので、こっちでやってみることにしました。これはデザイナーを使わないので大丈夫です。ChatGPT で同様のことをやってみると、こちらも正しい結果が得られました。こちらの方を書いてみます。以下のようなプログラムが得られました。

from itertools import permutations

def is_even_permutation(perm):
    """Check if a permutation is even."""
    inversions = 0
    for i in range(len(perm)):
        for j in range(i+1, len(perm)):
            if perm[i] > perm[j]:
                inversions += 1
    return inversions % 2 == 0

def symmetric_group_elements(n):
    """Generate all elements of the symmetric group of degree n."""
    if n == 1:
        return [[1]]
    else:
        perms = []
        for perm in symmetric_group_elements(n-1):
            for i in range(n):
                new_perm = perm[:i] + [n] + perm[i:]
                perms.append(new_perm)
        return perms

def classify_permutations(n):
    """Classify permutations into even and odd permutations."""
    symmetric_perms = symmetric_group_elements(n)
    even_perms = []
    odd_perms = []
    for perm in symmetric_perms:
        if is_even_permutation(perm):
            even_perms.append(perm)
        else:
            odd_perms.append(perm)
    return even_perms, odd_perms

n = int(input("Enter the value of n: "))
even_perms, odd_perms = classify_permutations(n)
print(f"Even permutations: {even_perms}")
print(f"Odd permutations: {odd_perms}")
結果( n = 3)

Even permutations: [[2, 3, 1], [3, 1, 2], [1, 2, 3]]
Odd permutations: [[3, 2, 1], [2, 1, 3], [1, 3, 2]]

結果( n = 4)

Even permutations: [[4, 3, 2, 1], [3, 2, 4, 1], [2, 4, 3, 1], [2, 3, 1, 4], [4, 2, 1, 3], [2, 1, 4, 3], [3, 4, 1, 2], [3, 1, 2, 4], [4, 1, 3, 2], [1, 3, 4, 2], [1, 4, 2, 3], [1, 2, 3, 4]]
Odd permutations: [[3, 4, 2, 1], [3, 2, 1, 4], [4, 2, 3, 1], [2, 3, 4, 1], [2, 4, 1, 3], [2, 1, 3, 4], [4, 3, 1, 2], [3, 1, 4, 2], [1, 4, 3, 2], [1, 3, 2, 4], [4, 1, 2, 3], [1, 2, 4, 3]]

結果( n = 5)

Even permutations: [[5, 4, 3, 2, 1], [4, 3, 5, 2, 1], [4, 3, 2, 1, 5], [3, 5, 4, 2, 1], [3, 4, 2, 5, 1], [5, 3, 2, 4, 1], [3, 2, 5, 4, 1], [3, 2, 4, 1, 5], [3, 5, 2, 1, 4], [3, 2, 1, 5, 4], [4, 5, 2, 3, 1], [4, 2, 3, 5, 1], [5, 2, 4, 3, 1], [2, 4, 5, 3, 1], [2, 4, 3, 1, 5], [2, 5, 3, 4, 1], [2, 3, 4, 5, 1], [5, 2, 3, 1, 4], [2, 3, 5, 1, 4], [2, 3, 1, 4, 5], [5, 4, 2, 1, 3], [4, 2, 5, 1, 3], [4, 2, 1, 3, 5], [2, 5, 4, 1, 3], [2, 4, 1, 5, 3], [5, 2, 1, 4, 3], [2, 1, 5, 4, 3], [2, 1, 4, 3, 5], [2, 5, 1, 3, 4], [2, 1, 3, 5, 4], [4, 5, 3, 1, 2], [4, 3, 1, 5, 2], [5, 3, 4, 1, 2], [3, 4, 5, 1, 2], [3, 4, 1, 2, 5], [3, 5, 1, 4, 2], [3, 1, 4, 5, 2], [5, 3, 1, 2, 4], [3, 1, 5, 2, 4], [3, 1, 2, 4, 5], [5, 4, 1, 3, 2], [4, 1, 5, 3, 2], [4, 1, 3, 2, 5], [1, 5, 4, 3, 2], [1, 4, 3, 5, 2], [5, 1, 3, 4, 2], [1, 3, 5, 4, 2], [1, 3, 4, 2, 5], [1, 5, 3, 2, 4], [1, 3, 2, 5, 4], [4, 5, 1, 2, 3], [4, 1, 2, 5, 3], [5, 1, 4, 2, 3], [1, 4, 5, 2, 3], [1, 4, 2, 3, 5], [1, 5, 2, 4, 3], [1, 2, 4, 5, 3], [5, 1, 2, 3, 4], [1, 2, 5, 3, 4], [1, 2, 3, 4, 5]]
Odd permutations: [[4, 5, 3, 2, 1], [4, 3, 2, 5, 1], [5, 3, 4, 2, 1], [3, 4, 5, 2, 1], [3, 4, 2, 1, 5], [3, 5, 2, 4, 1], [3, 2, 4, 5, 1], [5, 3, 2, 1, 4], [3, 2, 5, 1, 4], [3, 2, 1, 4, 5], [5, 4, 2, 3, 1], [4, 2, 5, 3, 1], [4, 2, 3, 1, 5], [2, 5, 4, 3, 1], [2, 4, 3, 5, 1], [5, 2, 3, 4, 1], [2, 3, 5, 4, 1], [2, 3, 4, 1, 5], [2, 5, 3, 1, 4], [2, 3, 1, 5, 4], [4, 5, 2, 1, 3], [4, 2, 1, 5, 3], [5, 2, 4, 1, 3], [2, 4, 5, 1, 3], [2, 4, 1, 3, 5], [2, 5, 1, 4, 3], [2, 1, 4, 5, 3], [5, 2, 1, 3, 4], [2, 1, 5, 3, 4], [2, 1, 3, 4, 5], [5, 4, 3, 1, 2], [4, 3, 5, 1, 2], [4, 3, 1, 2, 5], [3, 5, 4, 1, 2], [3, 4, 1, 5, 2], [5, 3, 1, 4, 2], [3, 1, 5, 4, 2], [3, 1, 4, 2, 5], [3, 5, 1, 2, 4], [3, 1, 2, 5, 4], [4, 5, 1, 3, 2], [4, 1, 3, 5, 2], [5, 1, 4, 3, 2], [1, 4, 5, 3, 2], [1, 4, 3, 2, 5], [1, 5, 3, 4, 2], [1, 3, 4, 5, 2], [5, 1, 3, 2, 4], [1, 3, 5, 2, 4], [1, 3, 2, 4, 5], [5, 4, 1, 2, 3], [4, 1, 5, 2, 3], [4, 1, 2, 3, 5], [1, 5, 4, 2, 3], [1, 4, 2, 5, 3], [5, 1, 2, 4, 3], [1, 2, 5, 4, 3], [1, 2, 4, 3, 5], [1, 5, 2, 3, 4], [1, 2, 3, 5, 4]]

対称群の導来部分群

次に「 n を指定して、 n 次の対称群の 1 次導来部分群と 2 次導来部分群が一致するかどうかを調べるプログラムを書いてください」ということをやってみました。これは計算すればできるのですが、普通の数学の本に簡単な証明が書かれていることもあります。これは ChatGPT でも Google Colab でも正しいプログラムはできなかったのですが、ChatGPT で間違っているところや追加したいところを質問して、得られたプログラムを組み合わせて、間違っているところを直すと動くようになりました。導来部分群は交換子全体で生成される部分群なのですが、このプログラムでは交換子全体を調べているだけなので、一致する場合はこれで良い(生成元が一致するだけで良い)のですが、一致しない場合は本来は部分群であることを確かめる必要があります(ここでやったものは部分群になっています)。これについての説明をwikipediaから引用して後に付け加えておきます。

プログラムと結果は以下のようになります。

from itertools import permutations

def symmetric_group(n):
    return list(permutations(range(1, n + 1)))

def commutator_permutations(perm1, perm2):
    # 逆元を計算
    inv_perm1 = inverse_permutation(perm1)
    inv_perm2 = inverse_permutation(perm2)
    
    # 交換子を計算
    comm = multiply_permutations(inv_perm1, multiply_permutations(inv_perm2, multiply_permutations(perm1, perm2)))
    return comm

# 置換の積を計算する関数
def multiply_permutations(perm1, perm2):
    product = [0] * len(perm1)
    for i in range(len(perm1)):
        product[i] = perm1[perm2[i] - 1]
    return product

# 置換の逆元を計算する関数
def inverse_permutation(perm):
    inverse = [0] * len(perm)
    for i in range(len(perm)):
        inverse[perm[i] - 1] = i + 1
    return inverse

def commutator(a, b):
    return commutator_permutations(a, b)

def derived_subgroup(group):
    derived = set()
    for a in group:
        for b in group:
            comm = commutator(a, b)
            derived.add(tuple(comm))
    return derived

def print_subgroup(subgroup, title):
    print(title)
    if not subgroup:
        print("Empty")
    else:
        print(subgroup)

def is_derived_equal(n):
    sym_group = symmetric_group(n)
    derived_1 = derived_subgroup(sym_group)
    derived_2 = derived_subgroup(derived_1)
    
    print_subgroup(sym_group, "Symmetric Group:")
    print_subgroup(derived_1, "1st Derived Subgroup:")
    print_subgroup(derived_2, "2nd Derived Subgroup:")

    return derived_1 == derived_2

n = int(input("Enter the value of n: "))
if is_derived_equal(n):
    print("1st and 2nd derived subgroups are equal.")
else:
    print("1st and 2nd derived subgroups are not equal.")
結果( n = 3)

Enter the value of n: Symmetric Group:
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
1st Derived Subgroup:
{(2, 3, 1), (1, 2, 3), (3, 1, 2)}
2nd Derived Subgroup:
{(1, 2, 3)}
1st and 2nd derived subgroups are not equal.

結果( n = 4)

Enter the value of n: Symmetric Group:
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
1st Derived Subgroup:
{(1, 4, 2, 3), (4, 2, 1, 3), (1, 3, 4, 2), (2, 3, 1, 4), (1, 2, 3, 4), (3, 1, 2, 4), (3, 2, 4, 1), (2, 1, 4, 3), (2, 4, 3, 1), (4, 3, 2, 1), (4, 1, 3, 2), (3, 4, 1, 2)}
2nd Derived Subgroup:
{(1, 2, 3, 4), (2, 1, 4, 3), (4, 3, 2, 1), (3, 4, 1, 2)}
1st and 2nd derived subgroups are not equal.

結果( n = 5)

Enter the value of n: Symmetric Group:
[(1, 2, 3, 4, 5), (1, 2, 3, 5, 4), (1, 2, 4, 3, 5), (1, 2, 4, 5, 3), (1, 2, 5, 3, 4), (1, 2, 5, 4, 3), (1, 3, 2, 4, 5), (1, 3, 2, 5, 4), (1, 3, 4, 2, 5), (1, 3, 4, 5, 2), (1, 3, 5, 2, 4), (1, 3, 5, 4, 2), (1, 4, 2, 3, 5), (1, 4, 2, 5, 3), (1, 4, 3, 2, 5), (1, 4, 3, 5, 2), (1, 4, 5, 2, 3), (1, 4, 5, 3, 2), (1, 5, 2, 3, 4), (1, 5, 2, 4, 3), (1, 5, 3, 2, 4), (1, 5, 3, 4, 2), (1, 5, 4, 2, 3), (1, 5, 4, 3, 2), (2, 1, 3, 4, 5), (2, 1, 3, 5, 4), (2, 1, 4, 3, 5), (2, 1, 4, 5, 3), (2, 1, 5, 3, 4), (2, 1, 5, 4, 3), (2, 3, 1, 4, 5), (2, 3, 1, 5, 4), (2, 3, 4, 1, 5), (2, 3, 4, 5, 1), (2, 3, 5, 1, 4), (2, 3, 5, 4, 1), (2, 4, 1, 3, 5), (2, 4, 1, 5, 3), (2, 4, 3, 1, 5), (2, 4, 3, 5, 1), (2, 4, 5, 1, 3), (2, 4, 5, 3, 1), (2, 5, 1, 3, 4), (2, 5, 1, 4, 3), (2, 5, 3, 1, 4), (2, 5, 3, 4, 1), (2, 5, 4, 1, 3), (2, 5, 4, 3, 1), (3, 1, 2, 4, 5), (3, 1, 2, 5, 4), (3, 1, 4, 2, 5), (3, 1, 4, 5, 2), (3, 1, 5, 2, 4), (3, 1, 5, 4, 2), (3, 2, 1, 4, 5), (3, 2, 1, 5, 4), (3, 2, 4, 1, 5), (3, 2, 4, 5, 1), (3, 2, 5, 1, 4), (3, 2, 5, 4, 1), (3, 4, 1, 2, 5), (3, 4, 1, 5, 2), (3, 4, 2, 1, 5), (3, 4, 2, 5, 1), (3, 4, 5, 1, 2), (3, 4, 5, 2, 1), (3, 5, 1, 2, 4), (3, 5, 1, 4, 2), (3, 5, 2, 1, 4), (3, 5, 2, 4, 1), (3, 5, 4, 1, 2), (3, 5, 4, 2, 1), (4, 1, 2, 3, 5), (4, 1, 2, 5, 3), (4, 1, 3, 2, 5), (4, 1, 3, 5, 2), (4, 1, 5, 2, 3), (4, 1, 5, 3, 2), (4, 2, 1, 3, 5), (4, 2, 1, 5, 3), (4, 2, 3, 1, 5), (4, 2, 3, 5, 1), (4, 2, 5, 1, 3), (4, 2, 5, 3, 1), (4, 3, 1, 2, 5), (4, 3, 1, 5, 2), (4, 3, 2, 1, 5), (4, 3, 2, 5, 1), (4, 3, 5, 1, 2), (4, 3, 5, 2, 1), (4, 5, 1, 2, 3), (4, 5, 1, 3, 2), (4, 5, 2, 1, 3), (4, 5, 2, 3, 1), (4, 5, 3, 1, 2), (4, 5, 3, 2, 1), (5, 1, 2, 3, 4), (5, 1, 2, 4, 3), (5, 1, 3, 2, 4), (5, 1, 3, 4, 2), (5, 1, 4, 2, 3), (5, 1, 4, 3, 2), (5, 2, 1, 3, 4), (5, 2, 1, 4, 3), (5, 2, 3, 1, 4), (5, 2, 3, 4, 1), (5, 2, 4, 1, 3), (5, 2, 4, 3, 1), (5, 3, 1, 2, 4), (5, 3, 1, 4, 2), (5, 3, 2, 1, 4), (5, 3, 2, 4, 1), (5, 3, 4, 1, 2), (5, 3, 4, 2, 1), (5, 4, 1, 2, 3), (5, 4, 1, 3, 2), (5, 4, 2, 1, 3), (5, 4, 2, 3, 1), (5, 4, 3, 1, 2), (5, 4, 3, 2, 1)]
1st Derived Subgroup:
{(5, 4, 1, 3, 2), (3, 1, 4, 5, 2), (1, 4, 3, 5, 2), (4, 3, 1, 5, 2), (5, 1, 2, 3, 4), (2, 3, 4, 5, 1), (2, 3, 1, 4, 5), (2, 5, 3, 4, 1), (5, 3, 1, 2, 4), (3, 4, 1, 2, 5), (2, 1, 4, 3, 5), (5, 3, 2, 4, 1), (1, 5, 3, 2, 4), (3, 5, 2, 1, 4), (5, 4, 2, 1, 3), (4, 3, 5, 2, 1), (5, 4, 3, 2, 1), (4, 2, 5, 1, 3), (2, 5, 1, 3, 4), (5, 1, 3, 4, 2), (3, 5, 1, 4, 2), (2, 4, 3, 1, 5), (3, 5, 4, 2, 1), (4, 1, 5, 3, 2), (4, 1, 2, 5, 3), (3, 1, 5, 2, 4), (1, 2, 3, 4, 5), (2, 3, 5, 1, 4), (4, 2, 3, 5, 1), (1, 3, 5, 4, 2), (2, 5, 4, 1, 3), (4, 5, 1, 2, 3), (5, 1, 4, 2, 3), (2, 1, 3, 5, 4), (5, 2, 1, 4, 3), (5, 2, 4, 3, 1), (2, 4, 1, 5, 3), (3, 4, 2, 5, 1), (3, 2, 4, 1, 5), (4, 5, 2, 3, 1), (1, 3, 2, 5, 4), (4, 3, 2, 1, 5), (3, 2, 5, 4, 1), (1, 2, 4, 5, 3), (1, 3, 4, 2, 5), (3, 4, 5, 1, 2), (4, 1, 3, 2, 5), (5, 2, 3, 1, 4), (4, 5, 3, 1, 2), (3, 1, 2, 4, 5), (2, 4, 5, 3, 1), (3, 2, 1, 5, 4), (1, 5, 4, 3, 2), (1, 4, 2, 3, 5), (1, 4, 5, 2, 3), (4, 2, 1, 3, 5), (1, 5, 2, 4, 3), (2, 1, 5, 4, 3), (1, 2, 5, 3, 4), (5, 3, 4, 1, 2)}
2nd Derived Subgroup:
{(5, 4, 1, 3, 2), (3, 1, 4, 5, 2), (1, 4, 3, 5, 2), (4, 3, 1, 5, 2), (5, 1, 2, 3, 4), (2, 3, 1, 4, 5), (5, 3, 1, 2, 4), (2, 5, 3, 4, 1), (2, 3, 4, 5, 1), (3, 4, 1, 2, 5), (2, 1, 4, 3, 5), (5, 3, 2, 4, 1), (1, 5, 3, 2, 4), (3, 5, 2, 1, 4), (5, 4, 2, 1, 3), (4, 3, 5, 2, 1), (5, 4, 3, 2, 1), (4, 2, 5, 1, 3), (2, 5, 1, 3, 4), (5, 1, 3, 4, 2), (3, 5, 1, 4, 2), (2, 4, 3, 1, 5), (3, 5, 4, 2, 1), (4, 1, 5, 3, 2), (4, 1, 2, 5, 3), (3, 1, 5, 2, 4), (1, 2, 3, 4, 5), (2, 3, 5, 1, 4), (4, 2, 3, 5, 1), (1, 3, 5, 4, 2), (4, 5, 1, 2, 3), (2, 5, 4, 1, 3), (5, 1, 4, 2, 3), (2, 1, 3, 5, 4), (5, 2, 1, 4, 3), (5, 2, 4, 3, 1), (2, 4, 1, 5, 3), (3, 4, 2, 5, 1), (3, 2, 4, 1, 5), (4, 5, 2, 3, 1), (1, 3, 2, 5, 4), (4, 3, 2, 1, 5), (3, 2, 5, 4, 1), (1, 2, 4, 5, 3), (1, 3, 4, 2, 5), (3, 4, 5, 1, 2), (4, 1, 3, 2, 5), (5, 2, 3, 1, 4), (4, 5, 3, 1, 2), (3, 1, 2, 4, 5), (2, 4, 5, 3, 1), (1, 5, 4, 3, 2), (1, 5, 2, 4, 3), (1, 4, 5, 2, 3), (2, 1, 5, 4, 3), (4, 2, 1, 3, 5), (1, 4, 2, 3, 5), (3, 2, 1, 5, 4), (1, 2, 5, 3, 4), (5, 3, 4, 1, 2)}
1st and 2nd derived subgroups are equal.

交換子

wikipedia:交換子 から必要な部分を引用します。

 G の二つの元  x, y の交換子を  [x, y] = x^{-1}y^{-1}xy と定義します。 x^y = y^{-1}xy と定義します。
 x^{y}=x[x,y]
 [y,x]=[x,y]^{-1}
 [xy,z]=[x,z]^{y}[y,z]
 [x,yz]=[x,z][x,y]^{z}
 [x,y^{-1}]=[y,x]^{y^{-1}}
 [x^{-1},y]=[y,x]^{x^{-1}}
 [[x,y^{-1}],z]^{y}[[y,z^{-1}],x]^{z}[[z,x^{-1}],y]^{x}=1
 [[x,y],z^{x}][[z,x],y^{z}][[y,z],x^{y}]=1
が成り立ちます。

交換子部分群

wikipedia:交換子部分群 から必要な部分を引用します。

 G の交換子全体が生成する部分群
 [G,G]={\big \langle }\left\{\,[x,y]\mid x,y\in G\,\right\}{\big \rangle }
 G の交換子部分群または導来部分群と呼びます。交換子部分群は
 G', \ G^{(1)}, \ \gamma_{2}(G), \ D(G)
と表すこともあります。

交換子の逆元も交換子なので、交換子部分群  [G, G] の任意の元は有限個の交換子の積
 [x_{1},y_{1}][x_{2},y_{2}]\cdots [x_{n},y_{n}]
の形に書くことができます。

 [x, y]^z = [x^z, y^z] であることから
 \displaystyle ([x_{1},y_{1}]\cdots [x_{n},y_{n}])^{z}=[x_{1}^{z},y_{1}^{z}]\cdots [x_{n}^{z},y_{n}^{z}]
が成り立ち、交換子部分群は  G正規部分群になります。

導来群を作る操作を繰り返して
 G^{(0)}:=G
 G^{(n)}:=[G^{(n-1)},G^{(n-1)}] \ (n \in \mathbb{N})
と定義します。このとき部分群  G^{(n)} n 次導来部分群、降正規列
 G=G^{(0)} \triangleright G^{(1)} \triangleright G^{(2)} \triangleright \cdots
を導来列と呼びます。

人工知能的論理プログラミング(8)

理想的な並行論理プログラミング言語

「論理プログラミング」、「論理計算と随伴関手」、「半環上のフラクタル代数」、「フラクタル代数言語 Fractal」、「一階述語論理」などの内容です。以下のようなことを考察します。

  • Prolog のプログラムを「プログラムを変換するもの」と考える
  • 変換されたものを  P^1, P^2, \cdots (再帰の深さ  n のものを  P^n)
  • ある  P^n の結果が真ならば証明できるか?
  • これを使って無限に実行できるか?

これを考えるために Prolog のプログラムを多項式に対応させることができるかどうかを考えます。多項式については答えてくれるようなので ChatGPT で質問してみます。以下は入力とそれに対する答えです。間違っているけど考える助けにはなります。「あなたは数学の専門家です」と入力すると良いということですが、効果があるかどうかは不明です。

あなたは数学の専門家です。多項式と形式的べき級数の関係について説明してください

多項式と形式的べき級数は、数学の分野で重要な役割を果たす概念です。まず、それぞれの定義から始めて、その関係について説明します。

  1. 多項式多項式は、1つ以上の変数に対する有限個の項の和で表される関数です。各項は変数のべき乗と定数の積で構成されます。例えば、 f(x) = 3x^2 + 2x - 1多項式の例です。ここで、 x は変数であり、2乗項、1次項、定数項がそれぞれ含まれています。
  2. 形式的べき級数:形式的べき級数は、次数が無限に広がる可能性のある項の和で表される数列です。この数列は、通常の数学的な意味での収束性や収束先を持たず、単に形式的な操作においてのみ意味を持ちます。例えば、 f(x) = 1 + x + x^2 + x^3 + \ldots という形式的べき級数は、無限の次数を持つ数列として表されます。

これらの概念の関係は、形式的べき級数多項式を一般化したものと見ることができます。多項式は有限個の項の和で表されますが、形式的べき級数は無限個の項の和で表されます。そのため、多項式は形式的べき級数の特別な場合と考えることができます。

また、多項式は形式的べき級数の1つの特殊な形であるとも言えます。多項式は次数が有限であるため、その級数展開を有限項で打ち切ることができます。つまり、多項式は次数が無限でない形式的べき級数と見なすことができます。

簡単に言えば、多項式は形式的べき級数の特殊なケースであり、形式的べき級数多項式を一般化したものであるという関係があります。

環上の多項式を環と不定元で自由生成された環の元と考えます。同じような考え方で形式的べき級数を説明してください

形式的べき級数を説明するためには、まず環上の多項式の概念を振り返ります。

環上の多項式:環  R 上の多項式は、  R[x] と書かれ、  x不定元として、  R の元から構成される形式的な式の集合です。これらの式は、  R の元を係数として持つ有限個の  x のべき乗の和で表されます。例えば、実数の環  \mathbb{R} 上の多項式は、実数係数を持つ形式的な式の集合です。

形式的べき級数:環  R 上の形式的べき級数は、 R[[x]] と書かれ、  x不定元として、  R の元から構成される形式的な式の集合です。これらの式は、  R の元を係数として持つ無限個の  x のべき乗の和で表されます。例えば、実数の環  \mathbb{R} 上の形式的べき級数は、実数係数を持つ形式的な式の集合ですが、この級数は収束性を持ちません。

環上の多項式 R x から生成される自由な環の元であると考えると、形式的べき級数も同様に  R x から生成される自由な環の元と見なすことができます。ただし、形式的べき級数は無限個の  x のべき乗の和で表されるため、その生成される自由な環の元は無限個の基底要素を持ちます。

したがって、環上の多項式が有限個の  x のべき乗の和で構成されるのに対し、形式的べき級数は無限個の  x のべき乗の和で構成されるという点で異なります。しかし、両者とも環  R 上で係数を持ち、  x不定元として構成される形式的な式の集合であるという共通点があります。

形式的べき級数多項式の極限として説明してください

形式的べき級数多項式の極限として説明することは、非常に重要であり直感的な理解を提供します。

多項式は有限個の項の和で構成される関数ですが、形式的べき級数は無限個の項の和で構成される数列です。これにより、形式的べき級数多項式の極限と見なすことができます。

具体的には、 x のべき級数として表される関数が多項式として表される関数の極限となります。例えば、 f(x) = 1 + x + x^2 + x^3 + \ldots という形式的べき級数は、 n が大きくなるにつれて次数が増えていきます。この級数は、  n \to \infty の極限として考えると、 1 + x + x^2 + x^3 + \ldots \frac{1}{1-x} という形式的な表現に収束します。

このように、形式的べき級数多項式の極限として考えることができます。多項式が有限個の項の和で表されるのに対し、形式的べき級数は無限個の項の和で表されるため、その和を取る際には収束性を考える必要があります。しかし、形式的べき級数多項式の極限として捉えることで、より広い範囲の関数を扱うことができるようになります。

形式的べき級数多項式の射影的極限として説明してください

形式的べき級数多項式の射影的極限として説明することは、抽象的な数学的概念に基づいて行われる説明です。射影的極限は、ある構造(例えば、多項式環)の部分構造(例えば、次数に制限された多項式の集合)に対する極限を取る操作です。

形式的べき級数多項式の射影的極限として説明するには、次のステップが必要です。

  1. 有限次数の多項式の集合を考える:まず、有限次数の多項式の集合  R[x]_n を考えます。これは次数が  n 以下の全ての多項式からなる集合です。
  2. 部分集合の包含関係を考える:集合  R[x]_0 から始めて、次数が  n 以下の多項式の集合を順に考えます。各集合は、その次数の多項式を持ち、次数が増えるにつれて集合の要素数も増えます。また、この各集合  R[x]_n R[x]_{n+1} の部分集合として考えることができます。
  3. 部分集合間の関係を考える:各集合  R[x]_n から  R[x]_{n+1} への包含写像があります。これは、次数  n多項式を次数  n+1多項式として埋め込む写像です。
  4. 射影的極限を取る:次数が無限に増加するとき、各次数  n における多項式の集合  R[x]_n の極限を考えます。この極限を取る操作が射影的極限です。
  5. 形式的べき級数の定義:射影的極限により得られた集合が、形式的べき級数の集合  R[[x]] です。これは、無限次数の多項式の和で構成される集合であり、各要素は  x のべき乗の係数を持ちます。

このようにして、形式的べき級数は、次数が無限に増加する多項式の集合として、多項式の射影的極限として定義されます。これにより、形式的べき級数は無限の次数を持ち、収束性を持たない数列として捉えることができます。

 R[x]_n が環ではないのでちょっと変ですが、流れは合っています。

多項式の代入について説明してください

多項式の代入とは、与えられた多項式の変数に具体的な値を代入して、新しい式を得る操作です。多項式の代入は、多項式の値を計算したり、式を変形したりするために広く使用されます。

多項式の代入をより具体的に説明するために、例を挙げてみましょう。

例えば、多項式  f(x) = 3x^2 + 2x - 1 x = 4 を代入する場合、次のようになります:

 f(4) = 3(4)^2 + 2(4) - 1
 = 3 \times 16 + 2 \times 4 - 1
 = 48 + 8 - 1
 = 55

このようにして、 x = 4 f(x) に代入すると、値  55 を得ます。

多項式の代入は、一般的に次の手順に従います。

  1. 代入したい値を多項式の変数に代入します。これにより、各項の中の変数が具体的な値に置き換えられます。
  2. 代入された式を計算し、新しい値を得ます。

多項式の代入は、多項式の値を計算したり、式を簡略化したりするのに非常に便利です。また、多項式の代入は、数値計算や数学的な証明においても広く使用されます。

多項式多項式を代入するとします。これを無限に繰り返したものを形式的べき級数で表すことはできますか

はい、多項式多項式を代入してそれを無限に繰り返すことを形式的べき級数で表すことができます。この操作は、形式的べき級数の概念を用いて次のように記述することができます。

多項式  f(x) を考えます。そして、  f(f(x)) f(x) に代入したものとします。つまり、 f(f(x)) は次のようになります。

 f(f(x)) = f(a_0 + a_1x + a_2x^2 + \ldots)

ここで、 a_0, a_1, a_2, \ldots f(x) の係数です。

この操作を再帰的に繰り返すと、以下のような形式的べき級数が得られます。

 f(f(f(\ldots f(x) \ldots)))

このようにして、多項式多項式を代入して繰り返す操作を形式的に表すことができます。これが形式的べき級数の一例であり、多項式による無限の繰り返しを表現しています。

無限の  f(f(f(\ldots f(x) \ldots))) が形式的べき級数で表せるかどうか(たぶんできない)を聞いているのですがそれには答えてくれません。

人工知能的写像の理論(1)

写像と同値類

ChatGPTでブログの記事を分析したものを書いてもらうというのはなかなか難しそうなので、ChatGPTでいろいろやりとりしながら、それを参考に記事の内容をまとめてみることにします。

まず写像と同値類の関係についてまとめてみます。

群論の計算」の「写像による分類」(さらにその後の「写像の計算」)
群論の計算(2) - エレファント・ビジュアライザー調査記録
群論の計算(3) - エレファント・ビジュアライザー調査記録
の項目では何をやっているのかというと、「準同型定理」のようなものを「写像の理論を使って書く」ための準備をやっています。「準同型定理」はもともと写像で書かれているので、「写像の理論を使って書く」というのは変ですが、普通の数学の本では写像の理論がそれほど使われているわけではないという印象なので、写像を中心とした書き方をしようとしています。普通の数学の本に書かれていることをわざわざ書くのは意味がないのでそのようにしています。

この話題は、このブログで「群論の計算」の後でもやったので探してみると、「集合の計算」
集合の計算(1) - エレファント・ビジュアライザー調査記録
集合の計算(2) - エレファント・ビジュアライザー調査記録
集合の計算(3) - エレファント・ビジュアライザー調査記録
集合の計算(4) - エレファント・ビジュアライザー調査記録
集合の計算(5) - エレファント・ビジュアライザー調査記録
集合の計算(6) - エレファント・ビジュアライザー調査記録
集合の計算(7) - エレファント・ビジュアライザー調査記録
集合の計算(8) - エレファント・ビジュアライザー調査記録
集合の計算(9) - エレファント・ビジュアライザー調査記録
でやっていました。その前の「エレファントな整数論」の(20)から(23)
エレファントな整数論(20) - エレファント・ビジュアライザー調査記録
エレファントな整数論(21) - エレファント・ビジュアライザー調査記録
エレファントな整数論(22) - エレファント・ビジュアライザー調査記録
エレファントな整数論(23) - エレファント・ビジュアライザー調査記録
でもやっています。他にもやっているかもしれません。何をやっているかまとめてみます。普通の数学の本に書かれていることも準備のために書いています。

まず「集合の計算」の内容をまとめます。ここはまだ準備なのでブログの内容をまとめただけとします。これは普通の数学の本に書かれている内容です。

集合の計算(1)

 f: X \to Y g: Y \to Z に対して

集合の計算(2)

  • (1)  f(A \cap B) \subseteq f(A) \cap f(B)
  • (2)  f(A \cup B) = f(A) \cup f(B)
  • (3)  f^{-1}(U \cap V) = f^{-1}(U) \cap f^{-1}(V)
  • (4)  f^{-1}(U \cup V) = f^{-1}(U) \cup f^{-1}(V)
  • (5)  \displaystyle f(\bigcap_{\lambda \in \Lambda} A_\lambda) \subseteq \bigcap_{\lambda \in \Lambda} f(A_\lambda)
  • (6)  \displaystyle f(\bigcup_{\lambda \in \Lambda} A_\lambda) = \bigcup_{\lambda \in \Lambda} f(A_\lambda)
  • (7)  \displaystyle f^{-1}(\bigcap_{\mu \in M} U_\mu) = \bigcap_{\mu \in M} f^{-1}(U_\mu)
  • (8)  \displaystyle f^{-1}(\bigcup_{\mu \in M} U_\mu) = \bigcup_{\mu \in M} f^{-1}(U_\mu)

集合の計算(3)

  • (*)  f(A) \subseteq U \iff A \subseteq f^{-1}(U)
  • (9)  A \subseteq f^{-1}(f(A))
  • (10)  f(f^{-1}(U)) \subseteq U
  • (11)  f(A) \setminus f(B) \subseteq f(A \setminus B)
  • (12)  f^{-1}(U) \setminus f^{-1}(V) = f^{-1}(U \setminus V)

集合の計算(4)

  • (1)  f(A \cap B) \subseteq f(A) \cap f(B)
  • (2)  f(A \cup B) = f(A) \cup f(B)
  • (3)  f^{-1}(U \cap V) = f^{-1}(U) \cap f^{-1}(V)
  • (4)  f^{-1}(U \cup V) = f^{-1}(U) \cup f^{-1}(V)
  • (5)  \displaystyle f(\bigcap_{\lambda \in \Lambda} A_\lambda) \subseteq \bigcap_{\lambda \in \Lambda} f(A_\lambda)
  • (6)  \displaystyle f(\bigcup_{\lambda \in \Lambda} A_\lambda) = \bigcup_{\lambda \in \Lambda} f(A_\lambda)
  • (7)  \displaystyle f^{-1}(\bigcap_{\mu \in M} U_\mu) = \bigcap_{\mu \in M} f^{-1}(U_\mu)
  • (8)  \displaystyle f^{-1}(\bigcup_{\mu \in M} U_\mu) = \bigcup_{\mu \in M} f^{-1}(U_\mu)

集合の計算(5)

「集合の計算(4)」の議論を  f \in \mathfrak{P}(X \times Y) の場合について考えます。(写像の代わりに  X \times Y の部分集合を考えます。写像全体を  \mathcal{M}(X, Y) で表します。)

  • (1)  \overline{f}(A \cap B) \subseteq \overline{f}(A) \cap \overline{f}(B)
  • (2)  \overline{f}(A \cup B) = \overline{f}(A) \cup \overline{f}(B)
  • (3)  f \in \mathcal{M}(X, Y) \implies \overline{f^{-1}}(U \cap V) = \overline{f^{-1}}(U) \cap \overline{f^{-1}}(V)
  • (4)  \overline{f^{-1}}(U \cup V) = \overline{f^{-1}}(U) \cup \overline{f^{-1}}(V)
  • (5)  \displaystyle \overline{f}(\bigcap_{\lambda \in \Lambda} A_\lambda) \subseteq \bigcap_{\lambda \in \Lambda} \overline{f}(A_\lambda)
  • (6)  \displaystyle \overline{f}(\bigcup_{\lambda \in \Lambda} A_\lambda) = \bigcup_{\lambda \in \Lambda} \overline{f}(A_\lambda)
  • (7)  \displaystyle f \in \mathcal{M}(X, Y) \implies \overline{f^{-1}}(\bigcap_{\mu \in M} U_\mu) = \bigcap_{\mu \in M} \overline{f^{-1}}(U_\mu)
  • (8)  \displaystyle \overline{f^{-1}}(\bigcup_{\mu \in M} U_\mu) = \bigcup_{\mu \in M} \overline{f^{-1}}(U_\mu)

人工知能的代数学(1)

目標

ここでは「群論の計算」などで扱っている問題をChatGPTを使って書いていきます。

まず、これは何のためにやっているのかを書きます。これはChatGPTではなかなかちゃんとした答えが返ってくるように書くのは難しいようなので、大まかなことは自分で書きます。以下のようなことをやろうとしています。

  • 数学の問題を表す適切な用語がないものについて考える
  • 帰納法を数式の変形またはビジュアルプログラミングで表す
  • 多項式の計算でできることを考える
  • プログラムの代数的構造を考える

細かい個別のテーマを書いておきます。これらについては何か答えが得られるかもしれません。

まず一般的な代数的構造についてChatGPTに聞いてみます。これらは一般的な本に書かれているものなので聞かなくてもいいのですが、どうなるか確認のためやってみます。以下は質問とその答えです。

群の定義を教えてください

「群(ぐん)」とは、数学の分野における代数構造の一つであり、以下の条件を満たす集合と演算の組である。

  1. 集合には、演算が定義されている。この演算は、通常は加法(+)や乗法(×)などで表されるが、その他の演算も考えることができる。
  2. その演算は、閉じている。つまり、集合の任意の2つの元を取って演算を行っても、結果は集合の中に含まれる。
  3. その演算は、結合法則を満たす。つまり、任意の元  a, b, c に対して、 (a ・ b) ・ c = a ・ (b ・ c) のように、演算を行う順序を変えても結果が変わらない。
  4. 集合には、恒等元が存在する。つまり、集合の中のどの元とも演算を行っても変化がないような元が存在する。
  5. 任意の元に対して、その逆元が存在する。つまり、ある元  a が与えられたとき、演算によって恒等元を得るために必要な元  b が存在する。

群は、数学的な対象や構造の理解や分類において重要な役割を果たしており、多くの数学分野で利用されている。

環の定義を教えてください

「環(かん)」は、数学の代数学における基本的な概念の一つであり、以下の条件を満たす代数構造を指します。

環は、集合  R とその上で定義された2つの二項演算(通常は加法  + と乗法  \cdot)の組  (R, +, \cdot) であり、次の性質を満たします:

  1. 集合  R は加法に関して可換群をなす。
    • 任意の  a, b, c \in R について、加法に関して結合法則が成り立つ: (a + b) + c = a + (b + c)
    • 集合  R の元  a, b について、加法に関して交換法則が成り立つ: a + b = b + a
    • 集合  R の中に、加法の単位元  0 が存在する:任意の  a \in R に対して、 a + 0 = a = 0 + a を満たす。
  2. 集合  R は乗法に関して結合法則を満たす。
    • 任意の  a, b, c \in R について、乗法に関して結合法則が成り立つ: (a \cdot b) \cdot c = a \cdot (b \cdot c)
  3. 乗法に関して分配法則が成り立つ。
    • 任意の  a, b, c \in R について、左分配法則が成り立つ: a \cdot (b + c) = (a \cdot b) + (a \cdot c)
    • 任意の  a, b, c \in R について、右分配法則が成り立つ: (a + b) \cdot c = (a \cdot c) + (b \cdot c)

環は、整数環、多項式環、行列環など、数学や物理学、工学などのさまざまな分野で広く応用されています。

体の定義を教えてください

体(たい)は、数学の代数学における基本的な構造の一つであり、以下の性質を満たす代数的構造です。

体は、集合  F とその上で定義された2つの二項演算(通常は加法  + と乗法  \cdot)の組  (F, +, \cdot) であり、次の性質を満たします:

  1.  F は加法に関して可換群をなす。
    • 任意の  a, b, c \in F について、加法に関して結合法則が成り立つ: (a + b) + c = a + (b + c)
    •  F の元  a, b について、加法に関して交換法則が成り立つ: a + b = b + a
    •  F の中に、加法の単位元  0 が存在する:任意の  a \in F に対して、 a + 0 = a = 0 + a を満たす。
    • 任意の  a \in F に対して、加法の逆元  -a が存在する: a + (-a) = 0
  2.  F の非零元全体は乗法に関して可換群をなす。
    • 任意の  a, b, c \in F について、乗法に関して結合法則が成り立つ: (a \cdot b) \cdot c = a \cdot (b \cdot c)
    •  F の非零元  a, b について、乗法に関して交換法則が成り立つ: a \cdot b = b \cdot a
    •  F の非零元  a に対して、乗法の単位元  1 が存在する:任意の  a に対して、 a \cdot 1 = a = 1 \cdot a を満たす。
    • 任意の  a \in F で、 a \neq 0 ならば、 F の中に  a の乗法の逆元  a^{-1} が存在する: a \cdot a^{-1} = 1

体は、有理数の集合、実数の集合、複素数の集合などがその例です。体は、線型代数や数論などの分野で幅広く応用されています。

群の定義は表現が変な感じです。

人工知能的論理プログラミング(7)

並行論理プログラミングと半環

「論理プログラミング」では PLP と PLP+ というプログラミング言語を考えています。PLP は「Prolog について」のところで書いたような理想的な並行 Prolog です。PLP+ はこれの無限に実行できるバージョンなのですが、PLP が定義されていないので PLP+ も定義されていません。PLP+ はいったい何なのかというと、「素数を登録するプログラム」のようなものが書けるように Prolog を拡張したプログラミング言語を目指したものです。

以下のような問題を考えます。

  1. PLP は定義できるか
  2. PLP で論理式が証明できるかどうかを調べることができるか

2は「不完全性定理」で調べた「チューリング機械の停止問題」の問題があるので、(まだ PLP を定義していないのですが)できないと考えられます。その代わりに

  • PLP が有限回で終了して結果が真  \iff 論理式が証明できる

という問題を考えることができます。

まず、PLP のプログラムを単純化して考えます。

Prolog のプログラムを単純化して
 \begin{matrix}
h_1 & :- & t_{11}, & \cdots, & t_{1n}. \\
\vdots & & \vdots & & \vdots \\
h_m & :- & t_{m1}, & \cdots, & t_{mn}. \\
\end{matrix}
とします。これを項  x に論理式
 \begin{matrix}
h_1=x & \land & t_{11} & \land & \cdots & \land & t_{1n} & \lor \\
\vdots & & \vdots & & & & \vdots & \\
h_m=x & \land & t_{m1} & \land & \cdots & \land & t_{mn} \\
\end{matrix}
を対応させる写像
 \begin{matrix}
x & \mapsto & h_1=x & \land & t_{11} & \land & \cdots & \land & t_{1n} & \lor \\
& & \vdots & & \vdots & & & & \vdots & \\
& & h_m=x & \land & t_{m1} & \land & \cdots & \land & t_{mn} \\
\end{matrix}
とみなします。これを
 \begin{pmatrix}
h_1 & t_{11} & \cdots & t_{1n} \\
\vdots & \vdots & \ddots & \vdots \\
h_m & t_{m1} & \cdots & t_{mn} \\
\end{pmatrix}
と書くことにします。項  u が写る先
 \begin{matrix}
h_1=u & \land & t_{11} & \land & \cdots & \land & t_{1n} & \lor \\
\vdots & & \vdots & & & & \vdots & \\
h_m=u & \land & t_{m1} & \land & \cdots & \land & t_{mn} \\
\end{matrix}

 u * \begin{pmatrix}
h_1 & t_{11} & \cdots & t_{1n} \\
\vdots & \vdots & \ddots & \vdots \\
h_m & t_{m1} & \cdots & t_{mn} \\
\end{pmatrix}
と書くことにします。
 P' = \begin{pmatrix}
h'_1 & t'_{11} & \cdots & t'_{1n} \\
\vdots & \vdots & \ddots & \vdots \\
h'_m & t'_{m1} & \cdots & t'_{mn} \\
\end{pmatrix} P = \begin{pmatrix}
h_1 & t_{11} & \cdots & t_{1n} \\
\vdots & \vdots & \ddots & \vdots \\
h_m & t_{m1} & \cdots & t_{mn} \\
\end{pmatrix}
に対して  P' * P を項  x に論理式
 \begin{matrix}
h'_1=x & \land & t'_{11} * P & \land & \cdots & \land & t'_{1n} * P & \lor \\
\vdots & & \vdots & & & & \vdots & \\
h'_m=x & \land & t'_{m1} * P & \land & \cdots & \land & t'_{mn} * P \\
\end{matrix}
を展開して選言標準形にしたものを対応させる写像とします。これを展開と呼ぶことにします。展開をChatGPTでやってもらおうとしましたが、うまくできませんでした。展開を有限回繰り返したものの各「連言」を順に実行する(「選言」については並行に実行)とどうなるのか、ということを考えます。これで論理式の証明ができるのかということをChatGPTで聞いてみましたが、あまり良い答えは返ってきませんでした。これは無限ループになる可能性があると考えられますが、よくわかりません。今後考えていきます。

人工知能的論理プログラミング(6)

半環について

Prolog のプログラムは論理式と解釈できます。論理式の全体は分配束となります。分配束は(単位元の存在などを無視すると)半環となります。このブログでは Prolog のプログラムを半環を使って調べています。分配束を使って調べても良いのですが、半環は環と同様のことが成り立つことがあって考えやすいので半環を使っています。

いくつかの入力とそれに対する答えです。

半環の定義を教えてください

半環(Semiring)は、代数構造の一種であり、加法と乗法を持ち、それぞれに対して加法単位元と乗法単位元を持つ非常に基本的な構造です。以下に、半環の定義を示します。

半環は、以下の条件を満たす二項演算(加法と乗法)とそれに関連する単位元からなる代数構造です。

  1. 加法と乗法が閉じている:半環の任意の要素に対して、その加法と乗法による演算の結果は再び半環の要素である。
  2. 加法と乗法は結合法則を満たす:任意の要素  a, b, c に対して、 (a + b) + c = a + (b + c) および  (a \cdot b) \cdot c = a \cdot (b \cdot c)
  3. 加法に関して可換性が成り立つ:任意の要素  a, b に対して、 a + b = b + a
  4. 加法と乗法に関して分配法則が成り立つ:任意の要素  a, b, c に対して、 a \cdot (b + c) = (a \cdot b) + (a \cdot c) および  (a + b) \cdot c = (a \cdot c) + (b \cdot c)
  5. 加法単位元の存在:半環には、加法の単位元  0 が存在し、任意の要素  a に対して、 a + 0 = 0 + a = a を満たす。
  6. 乗法単位元の存在:半環には、乗法の単位元  1 が存在し、任意の要素  a に対して、 a \cdot 1 = 1 \cdot a = a を満たす。

半環は、組み合わせ最適化グラフ理論、符号理論などの数学や計算機科学の分野で広く用いられます。

分配束の定義を教えてください

分配束(Distributive lattice)は、部分順序集合において、二項演算である合併(join)と交叉(meet)に対して分配法則を満たす代数的構造です。具体的には以下の性質を持ちます。

  1. 部分順序集合である:集合  L が部分順序集合である。
  2. 合併と交叉に関する分配法則を満たす:任意の  a, b, c \in L について、以下の分配法則が成り立つ。
    •  a \vee (b \wedge c) = (a \vee b) \wedge (a \vee c)
    •  a \wedge (b \vee c) = (a \wedge b) \vee (a \wedge c)
  3. 合併と交叉に関しての最小と最大の元が存在する: L の任意の部分集合に対して、その合併と交叉が存在し、それぞれの操作によって得られる元が  L の元である。

このような性質を持つ代数構造は、数学やコンピュータサイエンスの様々な分野で応用されます。例えば、論理学、集合論、データ構造、情報理論などの分野で用いられます。

最大元と最小元をもつ分配束で、合併を加法、交叉を乗法と決めたものは半環になりますか

はい、最大元と最小元を持つ分配束で、合併を加法、交叉を乗法とする操作を定義した場合、それは半環と呼ばれる代数的構造になります。

半環は、2つの二項演算(加法と乗法)を持つ代数的構造であり、以下の条件を満たす必要があります:

  1. 加法に関する閉包性:任意の要素に対して、その加法に関する逆元が存在すること。
  2. 加法に関する結合法則:任意の要素  a、b、c について、 (a+b)+c = a+(b+c) となること。
  3. 加法に関する交換法則:任意の要素  a、b について、 a+b = b+a となること。
  4. 乗法に関する閉包性:任意の要素に対して、その乗法に関する単位元が存在すること。
  5. 乗法に関する結合法則:任意の要素  a、b、c について、 (a×b)×c = a×(b×c) となること。
  6. 加法に関する分配法則:任意の要素  a、b、c について、 a×(b+c) = (a×b)+(a×c) となること。
  7. 乗法に関する分配法則:任意の要素  a、b、c について、 (a+b)×c = (a×c)+(b×c) となること。

最大元と最小元を持つ分配束に対して、合併を加法、交叉を乗法とする操作を定義すると、これらの条件が満たされるので、それは半環となります。

命題論理の論理式の全体に、論理積を交叉、論理和を合併と決めると分配束になりますか

命題論理の論理式の全体に、論理積を交叉、論理和を合併として定義すると、それは分配束となります。

分配束とは、集合とその上の2つの二項演算が定義され、それらの演算が分配法則を満たす代数的構造です。論理積論理和は、分配法則を満たすので、これらを交叉と合併として定義すれば、命題論理の論理式の全体は分配束になります。

具体的には、以下のような分配法則が成立します:

  1. 交叉(論理積)に関する分配法則:任意の論理式  A B C について、 A \land (B \lor C) = (A \land B) \lor (A \land C)
  2. 合併(論理和)に関する分配法則:任意の論理式  A B C について、 A \lor (B \land C) = (A \lor B) \land (A \lor C)

したがって、命題論理の論理式の全体に対してこのような操作を定義すると、それは分配束となります。

半環を使って以下のようなことをやります。

Prolog のリストの逆順を求める述語

reverse_list([], []).
reverse_list([X|Xs], Reverse) :-
    reverse_list(Xs, Rest),
    append(Rest, [X], Reverse).

について、reverse_list と同じ動作をする reverse_list_2 を作り、reverse_list からの再帰的な reverse_list の呼び出しを reverse_list_2 の呼び出しで置き換えます。

reverse_list([], []).
reverse_list([X|Xs], Reverse) :-
    reverse_list_2(Xs, Rest),
    append(Rest, [X], Reverse).
reverse_list_2([], []).
reverse_list_2([X|Xs], Reverse) :-
    reverse_list_2(Xs, Rest),
    append(Rest, [X], Reverse).

ここで(後で置き換えやすいように) reverse_list_2 の変数名を変更しておきます。

reverse_list([], []).
reverse_list([X|Xs], Reverse) :-
    reverse_list_2(Xs, Rest),
    append(Rest, [X], Reverse).
reverse_list_2([], []).
reverse_list_2([X_2|Xs_2], Reverse_2) :-
    reverse_list_2(Xs_2, Rest_2),
    append(Rest_2, [X_2], Reverse_2).

次に reverse_list からの reverse_list_2 の呼び出しを reverse_list_2 の本体で置き換えます。

reverse_list([], []).
reverse_list([X|Xs], Reverse) :-
    Xs=[], Rest=[], 
    append(Rest, [X], Reverse).
reverse_list([X|Xs], Reverse) :-
    Xs=[X_2|Xs_2], Rest=Reverse_2, 
    reverse_list_2(Xs_2, Rest_2),
    append(Rest_2, [X_2], Reverse_2),
    append(Rest, [X], Reverse).
reverse_list_2([], []).
reverse_list_2([X_2|Xs_2], Reverse_2) :-
    reverse_list_2(Xs_2, Rest_2),
    append(Rest_2, [X_2], Reverse_2).

こうすると reverse_list の再帰を一段階減らすことができます。

これをもう一段階減らしてください

と入力したところ、以下のような答えでした。

次に再帰を一段階減らすために、`reverse_list_2` の再帰呼び出しを `reverse_list` の本体で行います。

reverse_list([], []).
reverse_list([X|Xs], Reverse) :-
    Xs=[], Rest=[], 
    append(Rest, [X], Reverse).
reverse_list([X|Xs], Reverse) :-
    Xs=[X_2|Xs_2], Rest=Reverse_2, 
    reverse_list(Xs_2, Rest_2),
    append(Rest_2, [X_2], Reverse_2),
    append(Rest, [X], Reverse).
reverse_list_2([], []).
reverse_list_2([X_2|Xs_2], Reverse_2) :-
    append(Rest_2, [X_2], Reverse_2),
    reverse_list_2(Xs_2, Rest_2).

こうすることで、`reverse_list` と `reverse_list_2` の両方で再帰呼び出しを一段階減らすことができます。

これはやってくれませんでした。このようなことを半環を使ってやろうとしています。