-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy path_models.py
More file actions
198 lines (156 loc) · 6.88 KB
/
Copy path_models.py
File metadata and controls
198 lines (156 loc) · 6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
"""Typed wire contracts for coding theory operations."""
from __future__ import annotations
from typing import Literal, Self
from pydantic import Field, model_validator
from jacobian._models import StrictModel
MAX_EXACT_CODEWORDS = 65_536
MAX_COVERING_RADIUS_STATES = 65_536
MAX_COVERING_RADIUS_TRANSITIONS = 2_000_000
def _validate_prime_field_matrix(
field_order: int,
generator_matrix: tuple[tuple[int, ...], ...],
) -> int:
from sympy import isprime
if not isprime(field_order):
raise ValueError("field_order must be prime for this prime-field operation")
width = len(generator_matrix[0])
if width == 0 or width > 256:
raise ValueError("generator rows must have between one and 256 entries")
if any(len(row) != width for row in generator_matrix):
raise ValueError("generator matrix rows must have equal length")
if any(not 0 <= entry < field_order for row in generator_matrix for entry in row):
raise ValueError("generator entries must be canonical field residues")
return width
def _matrix_rank_mod_prime(
matrix: tuple[tuple[int, ...], ...],
field_order: int,
) -> int:
rows = [list(row) for row in matrix]
row_count = len(rows)
column_count = len(rows[0])
pivot_row = 0
for column in range(column_count):
pivot = next(
(
index
for index in range(pivot_row, row_count)
if rows[index][column] % field_order != 0
),
None,
)
if pivot is None:
continue
rows[pivot_row], rows[pivot] = rows[pivot], rows[pivot_row]
inverse = pow(rows[pivot_row][column] % field_order, -1, field_order)
rows[pivot_row] = [value * inverse % field_order for value in rows[pivot_row]]
for index, row in enumerate(rows):
if index == pivot_row:
continue
factor = row[column] % field_order
if factor == 0:
continue
rows[index] = [
(left - factor * right) % field_order
for left, right in zip(row, rows[pivot_row], strict=True)
]
pivot_row += 1
if pivot_row == row_count:
break
return pivot_row
class LinearCodeRequest(StrictModel):
"""A linear code given by its generator matrix over one bounded prime field."""
field_order: int = Field(ge=2, le=251)
generator_matrix: tuple[tuple[int, ...], ...] = Field(min_length=1, max_length=8)
@model_validator(mode="after")
def require_bounded_prime_field_matrix(self) -> Self:
_validate_prime_field_matrix(self.field_order, self.generator_matrix)
if self.field_order ** len(self.generator_matrix) > MAX_EXACT_CODEWORDS:
raise ValueError("generator matrix exceeds the exact enumeration bound")
return self
class MinimumDistanceResult(StrictModel):
minimum_distance: int = Field(ge=0, le=10000)
method: Literal["EXACT_ENUMERATION"] = "EXACT_ENUMERATION"
class WeightDistributionResult(StrictModel):
weights: tuple[tuple[int, int], ...] = Field(max_length=10000)
method: Literal["EXACT_ENUMERATION"] = "EXACT_ENUMERATION"
class CoveringRadiusRequest(StrictModel):
"""A linear code whose syndrome graph fits declared exact-work bounds."""
field_order: int = Field(ge=2, le=251)
generator_matrix: tuple[tuple[int, ...], ...] = Field(min_length=1, max_length=8)
@model_validator(mode="after")
def require_bounded_syndrome_graph(self) -> Self:
width = _validate_prime_field_matrix(
self.field_order,
self.generator_matrix,
)
rank = _matrix_rank_mod_prime(self.generator_matrix, self.field_order)
syndrome_dimension = width - rank
state_count = self.field_order**syndrome_dimension
if state_count > MAX_COVERING_RADIUS_STATES:
raise ValueError("syndrome space exceeds the exact state bound")
move_count_bound = min(
width * (self.field_order - 1),
max(state_count - 1, 0),
)
if state_count * move_count_bound > MAX_COVERING_RADIUS_TRANSITIONS:
raise ValueError("syndrome graph exceeds the exact transition bound")
return self
class CoveringRadiusResult(StrictModel):
covering_radius: int = Field(ge=0, le=256)
method: Literal["SYNDROME_BFS"] = "SYNDROME_BFS"
# ---------------------------------------------------------------------------
# Dual code operations
# ---------------------------------------------------------------------------
class DualCodeRequest(StrictModel):
"""Compute the dual code (parity check matrix) from a generator matrix."""
field_order: int = Field(ge=2, le=251)
generator_matrix: tuple[tuple[int, ...], ...] = Field(min_length=1)
@model_validator(mode="after")
def require_valid_prime_field(self) -> Self:
from sympy import isprime
if not isprime(self.field_order):
raise ValueError("field_order must be prime")
width = len(self.generator_matrix[0])
if width == 0:
raise ValueError("generator rows must be nonempty")
if any(len(row) != width for row in self.generator_matrix):
raise ValueError("generator rows must have equal length")
if any(
not 0 <= entry < self.field_order
for row in self.generator_matrix
for entry in row
):
raise ValueError("entries must be canonical field residues")
return self
class DualCodeResult(StrictModel):
"""The dual code: parity check matrix (rows span the null space)."""
field_order: int
parity_check_matrix: tuple[tuple[int, ...], ...]
code_dimension: int
code_length: int
dual_dimension: int
class SyndromeRequest(StrictModel):
"""Compute the syndrome of a received word under a parity check matrix."""
field_order: int = Field(ge=2, le=251)
parity_check_matrix: tuple[tuple[int, ...], ...] = Field(min_length=1)
received_word: tuple[int, ...] = Field(min_length=1)
@model_validator(mode="after")
def require_valid_request(self) -> Self:
from sympy import isprime
if not isprime(self.field_order):
raise ValueError("field_order must be prime")
cols = len(self.parity_check_matrix[0])
if any(len(row) != cols for row in self.parity_check_matrix):
raise ValueError("parity check rows must have equal length")
if len(self.received_word) != cols:
raise ValueError("received word length must match parity check columns")
for entry in self.received_word:
if not 0 <= entry < self.field_order:
raise ValueError(
"received word entries must be canonical field residues"
)
return self
class SyndromeResult(StrictModel):
"""The syndrome vector H * r^T mod p."""
field_order: int
syndrome: tuple[int, ...]