77from pydantic import Field , model_validator
88
99from jacobian ._models import StrictModel
10+ from jacobian .math ._labels import OpaqueLabel
1011
1112MAX_ELEMENTS = 50
12- MAX_LABEL_LENGTH = 64
1313
1414
1515class FiniteSemigroup (StrictModel ):
1616 """A finite semigroup: a finite set with an associative binary operation."""
1717
18- elements : tuple [str , ...] = Field (min_length = 1 , max_length = MAX_ELEMENTS )
19- multiplication : tuple [tuple [str , ...], ...]
18+ elements : tuple [OpaqueLabel , ...] = Field (min_length = 1 , max_length = MAX_ELEMENTS )
19+ multiplication : tuple [tuple [OpaqueLabel , ...], ...]
2020
2121 @model_validator (mode = "after" )
2222 def require_valid_semigroup (self ) -> Self :
2323 labels = set (self .elements )
2424 if len (labels ) != len (self .elements ):
2525 raise ValueError ("element labels must be distinct" )
26- for label in self .elements :
27- if len (label ) > MAX_LABEL_LENGTH :
28- raise ValueError ("element label exceeds the bounded length budget" )
2926 if len (self .multiplication ) != len (self .elements ):
3027 raise ValueError ("multiplication table must have one row per element" )
3128 for row in self .multiplication :
@@ -59,7 +56,7 @@ class PowerProfileRequest(StrictModel):
5956 """Request the power profile of one element in a finite semigroup."""
6057
6158 semigroup : FiniteSemigroup
62- element : str
59+ element : OpaqueLabel
6360
6461 @model_validator (mode = "after" )
6562 def require_element_exists (self ) -> Self :
@@ -79,12 +76,12 @@ class PowerProfileResult(StrictModel):
7976 """
8077
8178 semigroup : FiniteSemigroup
82- element : str
83- powers : tuple [str , ...]
79+ element : OpaqueLabel
80+ powers : tuple [OpaqueLabel , ...]
8481 index : int = Field (ge = 1 )
8582 period : int = Field (ge = 1 )
86- idempotent : str
87- cyclic_subsemigroup : tuple [str , ...]
83+ idempotent : OpaqueLabel
84+ cyclic_subsemigroup : tuple [OpaqueLabel , ...]
8885
8986 @model_validator (mode = "after" )
9087 def bind_power_profile (self ) -> Self :
@@ -114,7 +111,7 @@ class GeneratedSubsemigroupRequest(StrictModel):
114111 """Request the subsemigroup generated by a set of elements."""
115112
116113 semigroup : FiniteSemigroup
117- generators : tuple [str , ...] = Field (min_length = 1 )
114+ generators : tuple [OpaqueLabel , ...] = Field (min_length = 1 )
118115
119116 @model_validator (mode = "after" )
120117 def require_generators_exist (self ) -> Self :
@@ -128,15 +125,15 @@ def require_generators_exist(self) -> Self:
128125class GeneratedSubsemigroupResult (StrictModel ):
129126 """The subsemigroup generated by a set of elements."""
130127
131- generators : tuple [str , ...]
132- elements : tuple [str , ...]
128+ generators : tuple [OpaqueLabel , ...]
129+ elements : tuple [OpaqueLabel , ...]
133130
134131
135132class ElementPowerRequest (StrictModel ):
136133 """Request the exact power ``element^exponent`` in a finite semigroup."""
137134
138135 semigroup : FiniteSemigroup
139- element : str
136+ element : OpaqueLabel
140137 exponent : int = Field (ge = 1 )
141138
142139 @model_validator (mode = "after" )
@@ -150,9 +147,9 @@ class ElementPowerResult(StrictModel):
150147 """The exact power ``element^exponent`` in a finite semigroup."""
151148
152149 semigroup : FiniteSemigroup
153- element : str
150+ element : OpaqueLabel
154151 exponent : int = Field (ge = 1 )
155- power : str
152+ power : OpaqueLabel
156153
157154 @model_validator (mode = "after" )
158155 def bind_power (self ) -> Self :
@@ -179,7 +176,7 @@ class IdempotentsResult(StrictModel):
179176 """All idempotent elements of a finite semigroup."""
180177
181178 semigroup : FiniteSemigroup
182- idempotents : tuple [str , ...]
179+ idempotents : tuple [OpaqueLabel , ...]
183180
184181 @model_validator (mode = "after" )
185182 def bind_idempotents (self ) -> Self :
@@ -197,7 +194,7 @@ class PrincipalIdealsRequest(StrictModel):
197194 """Request the principal ideal of each listed element."""
198195
199196 semigroup : FiniteSemigroup
200- elements : tuple [str , ...] = Field (min_length = 1 , max_length = MAX_ELEMENTS )
197+ elements : tuple [OpaqueLabel , ...] = Field (min_length = 1 , max_length = MAX_ELEMENTS )
201198
202199 @model_validator (mode = "after" )
203200 def require_elements_exist (self ) -> Self :
@@ -222,8 +219,8 @@ class PrincipalIdealsResult(StrictModel):
222219 """
223220
224221 semigroup : FiniteSemigroup
225- elements : tuple [str , ...]
226- ideals : tuple [tuple [str , ...], ...]
222+ elements : tuple [OpaqueLabel , ...]
223+ ideals : tuple [tuple [OpaqueLabel , ...], ...]
227224
228225 @model_validator (mode = "after" )
229226 def bind_ideals (self ) -> Self :
0 commit comments