0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで部分群・正規部分群・交換子部分群を扱う

0
Last updated at Posted at 2026-07-28

前の記事:Pythonで群準同型を表す:写像・核・像

前の記事では、群準同型を GroupHomomorphism[G, H] として表しました。今回は、群の中にある部分構造を扱います。

数学的には、部分群 $H \leq G$ は、台集合 $H$ とその群構造、および $G$ への包含写像の組として捉えられます。Pythonでもこの対応を保つため、要素集合だけでなく、入力側・出力側の群と包含写像を明示します。

コード例は Python 3.12 以降を前提にしています。

部分群の定義

群 $G$ の部分群 $H$ は、包含写像 $i : H \to G$ が群準同型となるような群です。有限モデルでは、検証対象の要素を別途列挙して確認します。

subgroup.py
from __future__ import annotations

from collections.abc import Iterable
from dataclasses import dataclass

from group import Group
from homomorphism import InjectiveGroupHomomorphism


@dataclass(frozen=True, slots=True)
class Subgroup[G, H]:
    inclusion: InjectiveGroupHomomorphism[H, G]

    def assert_inclusion(self, samples: Iterable[H]) -> None:
        samples = tuple(samples)
        assert self.inclusion.source.identity in samples
        self.inclusion.assert_injective(samples)
        self.inclusion.assert_preserves_identity()
        for element in samples:
            self.inclusion.assert_preserves_inverse(element)
        for left in samples:
            for right in samples:
                self.inclusion.assert_preserves_operation(left, right)

    def assert_normal(
        self,
        ambient_samples: Iterable[G],
        subgroup_samples: Iterable[H],
    ) -> None:
        subgroup_samples = tuple(subgroup_samples)
        self.assert_inclusion(subgroup_samples)
        image = {self.inclusion(element) for element in subgroup_samples}
        assert all(
            self.inclusion.target.op(
                self.inclusion.target.op(ambient_element, self.inclusion(element)),
                self.inclusion.target.inv(ambient_element),
            )
            in image
            for ambient_element in ambient_samples
            for element in subgroup_samples
        )

Subgroup[G, H] は、HG のPythonサブクラスであることを要求していません。包含写像を明示することで、異なるPython型で表された台集合の間にも部分群関係を表現できます。包含写像の型を InjectiveGroupHomomorphism[H, G] とすることで、部分群の包含に必要な単射性も構造に反映しています。有限集合をフィールドに持たせていないため、無限群にも同じ構造を使えます。

assert_inclusion()assert_normal() は、有限モデルの全要素、または検証対象のサンプルを引数として受け取ります。渡された要素について、包含写像が群準同型であることや正規性を確認します。

部分群の具体例

置換群 $S_3$ の偶置換全体 $A_3$ を考えます。A3Element を用意し、包含写像で Permutation へ埋め込みます。

subgroup_example.py
from dataclasses import dataclass

from group import Group
from homomorphism import InjectiveGroupHomomorphism
from permutation import Permutation, symmetric_group
from subgroup import Subgroup


S3 = frozenset(
    Permutation(values)
    for values in (
        (0, 1, 2),
        (0, 2, 1),
        (1, 0, 2),
        (1, 2, 0),
        (2, 0, 1),
        (2, 1, 0),
    )
)


def sign(permutation: Permutation) -> int:
    inversions = sum(
        permutation.values[i] > permutation.values[j]
        for i in range(len(permutation.values))
        for j in range(i + 1, len(permutation.values))
    )
    return -1 if inversions % 2 else 1


S3_group = symmetric_group(3)


@dataclass(frozen=True, slots=True)
class A3Element:
    value: Permutation


A3_group = Group[A3Element](
    identity=A3Element(S3_group.identity),
    inv=lambda element: A3Element(S3_group.inv(element.value)),
    op=lambda left, right: A3Element(
        S3_group.op(left.value, right.value)
    ),
)
A3_elements = frozenset(
    A3Element(permutation)
    for permutation in S3
    if sign(permutation) == 1
)
A3 = Subgroup(
    inclusion=InjectiveGroupHomomorphism(
        f=lambda element: element.value,
        source=A3_group,
        target=S3_group,
    ),
)
A3.assert_inclusion(A3_elements)
assert len(A3_elements) == 3

A3_groupA3Element 上の群構造であり、inclusionA3ElementPermutation へ埋め込みます。有限モデルの要素は A3_elements として、検証時に渡しています。Subgroup の対象群と部分群は、包含写像の targetsource から取得できます。

正規部分群

部分群 $N \leq G$ が正規部分群であるとは、任意の $g \in G$ と $n \in N$ に対して、共役元 $gng^{-1}$ が再び $N$ に含まれることです。

gng^{-1} \in N

A3S3 の正規部分群なので、次のように確認できます。

A3.assert_normal(S3, A3_elements)

assert_normal() は、有限モデルとして与えた ambient_samples 全体について共役を計算します。無限群の正規性を、この方法で一般に証明するものではありません。

交換子部分群

群の交換子を、ここでは次の規約で定義します。

[a,b] = a^{-1}b^{-1}ab

交換子部分群 $[G,G]$ は、すべての交換子で生成される部分群です。

commutator_subgroup.py
from collections.abc import Iterable

from group import Group


def commutator[G](group: Group[G], a: G, b: G) -> G:
    return group.op(
        group.op(group.inv(a), group.inv(b)),
        group.op(a, b),
    )


def generated_subgroup[G](
    group: Group[G],
    ambient_elements: frozenset[G],
    generators: Iterable[G],
) -> frozenset[G]:
    elements = {group.identity, *generators}

    while True:
        expanded = elements | {group.inv(element) for element in elements}
        expanded |= {
            group.op(left, right)
            for left in elements
            for right in elements
        }
        if expanded == elements:
            return frozenset(elements)
        if not expanded <= ambient_elements:
            raise ValueError("the finite carrier is not closed")
        elements = expanded


def commutator_subgroup[G](
    group: Group[G],
    ambient_elements: frozenset[G],
) -> frozenset[G]:
    commutators = {
        commutator(group, left, right)
        for left in ambient_elements
        for right in ambient_elements
    }
    return generated_subgroup(group, ambient_elements, commutators)

generated_subgroup() は、有限群で閉包が安定するまで元を追加します。無限群では停止するとは限らないため、有限モデルを対象とした実装です。

S_3 の交換子部分群を計算する

commutator_example.py
from subgroup_example import A3_elements, S3, S3_group
from commutator_subgroup import commutator_subgroup


derived_elements = commutator_subgroup(S3_group, S3)

assert derived_elements == {
    element.value for element in A3_elements
}

この計算から、具体的な有限群 $S_3$ では

[S_3,S_3] = A_3

となることを確認できます。交換子部分群を含む剰余群 $G/[G,G]$ は可換群になります。この構成は、次の記事で扱う剰余群と第一同型定理につながります。

まとめ

  • 部分群を台集合・群構造・包含写像の組として表した
  • 包含写像が群準同型であることを具体例について検証した
  • 正規性を共役によって判定した
  • $S_3$ の交換子部分群が $A_3$ になることを観察した

次の記事では、正規部分群による剰余群を実装し、第一同型定理を具体例で確認します。

次の記事:Pythonで剰余群と第一同型定理を検証する

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?