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で直積群を実装する:2つの群から新しい群を構成する

0
Last updated at Posted at 2026-07-29

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

前の記事では、正規部分群による剰余群を実装しました。今回は、2つの群から直積群を構成します。

直積群は、群の要素を組として持ち、各成分を別々に演算する構成です。Group[G] を使うと、要素の型が異なる群も組み合わせられます。

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

直積群の定義

群 $G$ と $H$ の直積群 $G \times H$ は、集合としては直積集合を持ち、演算を成分ごとに定義します。

(g_1, h_1)(g_2, h_2) = (g_1g_2, h_1h_2)

単位元と逆元も成分ごとに定まります。

e_{G \times H} = (e_G, e_H),\qquad
(g,h)^{-1} = (g^{-1},h^{-1})

直積群を実装する

direct_product.py
from __future__ import annotations

from group import Group
from homomorphism import GroupHomomorphism


def product_group[G, H](
    left: Group[G],
    right: Group[H],
) -> Group[tuple[G, H]]:
    return Group(
        identity=(left.identity, right.identity),
        inv=lambda value: (
            left.inv(value[0]),
            right.inv(value[1]),
        ),
        op=lambda a, b: (
            left.op(a[0], b[0]),
            right.op(a[1], b[1]),
        ),
    )


def product_homomorphism[K, G, H](
    left: GroupHomomorphism[K, G],
    right: GroupHomomorphism[K, H],
) -> GroupHomomorphism[K, tuple[G, H]]:
    if left.source is not right.source:
        raise ValueError("homomorphisms must have the same source")
    return GroupHomomorphism(
        f=lambda value: (left(value), right(value)),
        source=left.source,
        target=product_group(left.target, right.target),
    )

product_group()Group[G]Group[H] を受け取り、Group[tuple[G, H]] を返します。直積の要素は単なるタプルですが、演算・単位元・逆元は新しい群構造としてまとめられています。

直積群の普遍性

直積群には、単に要素を組にする以上の性質があります。群 $K$ から $G$ と $H$ への群準同型

f : K \to G, \qquad g : K \to H

が与えられると、次の写像が直積群への群準同型になります。

\langle f, g \rangle : K \to G \times H,
\qquad k \mapsto (f(k), g(k))

さらに、直積群から各成分への射影

\pi_G : G \times H \to G, \qquad
\pi_H : G \times H \to H

との合成は、元の準同型に戻ります。

\pi_G \circ \langle f, g \rangle = f,
\qquad
\pi_H \circ \langle f, g \rangle = g

この性質によって $G \times H$ への準同型は特徴づけられます。つまり、同じ2つの合成を持つ準同型は $\langle f, g \rangle$ と一致します。これが直積群の普遍性です。

product_homomorphism() は、2本の群準同型からこの組み合わせ写像を構成します。

有限巡回群の直積

整数を法 $n$ で割った余りの加法群 $\mathbb{Z}/n\mathbb{Z}$を、直積群の具体例として使います。

cyclic.py
from __future__ import annotations

from dataclasses import dataclass, InitVar

from group import Group


@dataclass(frozen=True, slots=True)
class Cyclic:
    modulus: int
    value: InitVar[int]

    def __post_init__(self, value: int) -> None:
        if self.modulus <= 0:
            raise ValueError("modulus must be positive")
        self.value = value % self.modulus

    def _check(self, other: Cyclic) -> None:
        if self.modulus != other.modulus:
            raise ValueError("moduli must be equal")

    def __add__(self, other: Cyclic) -> Cyclic:
        self._check(other)
        return type(self)(self.modulus, self.value + other.value)

    def __neg__(self) -> Cyclic:
        return type(self)(self.modulus, -self.value)


def cyclic_group(modulus: int) -> Group[Cyclic]:
    return Group(
        identity=Cyclic(modulus, 0),
        inv=lambda value: -value,
        op=lambda left, right: left + right,
    )

$\mathbb{Z}/4\mathbb{Z}$ と $\mathbb{Z}/3\mathbb{Z}$ の直積を作ります。

product_example.py
from cyclic import cyclic_group
from direct_product import product_group


z4 = cyclic_group(4)
z3 = cyclic_group(3)
product = product_group(z4, z3)

zero = product.identity
element = (z4.identity, z3.identity)
assert element == zero
assert product.op(element, zero) == element
assert product.inv(element) == zero

直積の要素は (Cyclic(4, ...), Cyclic(3, ...)) のような組になります。左右の群は同じ要素型である必要がなく、各成分の群構造を別々に渡せます。

普遍性を具体例で観察する

$\mathbb{Z}/6\mathbb{Z}$ から $\mathbb{Z}/4\mathbb{Z}$ と $\mathbb{Z}/3\mathbb{Z}$ への準同型を用意し、直積群への組み合わせ写像を作ります。

product_universal_property.py
from cyclic import Cyclic, cyclic_group
from direct_product import product_homomorphism
from homomorphism import GroupHomomorphism


z6 = cyclic_group(6)
z4 = cyclic_group(4)
z3 = cyclic_group(3)

to_z4 = GroupHomomorphism(
    f=lambda value: Cyclic(4, 2 * value.value),
    source=z6,
    target=z4,
)
to_z3 = GroupHomomorphism(
    f=lambda value: Cyclic(3, value.value),
    source=z6,
    target=z3,
)
pairing = product_homomorphism(to_z4, to_z3)
product = pairing.target

z6_elements = frozenset(Cyclic(6, value) for value in range(6))
for value in z6_elements:
    assert pairing(value) == (to_z4(value), to_z3(value))

projection_z4 = GroupHomomorphism(
    f=lambda value: value[0],
    source=product,
    target=z4,
)
projection_z3 = GroupHomomorphism(
    f=lambda value: value[1],
    source=product,
    target=z3,
)

for value in z6_elements:
    assert projection_z4(pairing(value)) == to_z4(value)
    assert projection_z3(pairing(value)) == to_z3(value)

pairing.assert_preserves_identity()
for left in z6_elements:
    for right in z6_elements:
        pairing.assert_preserves_operation(left, right)

この例では、pairing の各成分が to_z4to_z3 に一致することを確認しています。したがって、直積群への写像を各射影との合成で特徴づける普遍性を、有限モデル上で観察できます。任意の群についての一意性をPythonの実行だけで証明しているわけではありません。

直積群の公理を検証する

直積群の公理は、各成分の公理から成り立ちます。有限群の具体例では、Hypothesisで要素の組を生成して確認できます。

test_direct_product.py
from hypothesis import given, strategies as st

from cyclic import Cyclic, cyclic_group
from direct_product import product_group


z4 = cyclic_group(4)
z3 = cyclic_group(3)
product = product_group(z4, z3)
elements = st.tuples(
    st.integers(min_value=0, max_value=3).map(lambda value: Cyclic(4, value)),
    st.integers(min_value=0, max_value=2).map(lambda value: Cyclic(3, value)),
)


@given(elements, elements, elements)
def test_associativity(left, middle, right) -> None:
    product.assert_associative(left, middle, right)


@given(elements)
def test_identity(value) -> None:
    product.assert_left_identity(value)
    product.assert_right_identity(value)


@given(elements)
def test_inverse(value) -> None:
    product.assert_inverse(value)

直積群の実装では、左右の群の演算を組み合わせて新しい演算を作っています。Group の公理検証メソッドを再利用できるため、構成した群も同じテストの枠組みで確認できます。

まとめ

  • 直積群の要素は2つの群の要素の組である
  • 演算・単位元・逆元を成分ごとに定義できる
  • 異なる要素型の群も直積にできる
  • 直積群の公理を Group の検証メソッドとHypothesisで確認した
  • 2本の準同型から直積群への準同型を構成し、普遍性を観察した

次の記事では、生成元から自由群を構成し、その普遍性をPythonで観察します。

次の記事: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?