Skip to content

Commit a9d1989

Browse files
committed
feat: add free distance method to convolutional codes
1 parent b295e65 commit a9d1989

File tree

3 files changed

+41
-9
lines changed

3 files changed

+41
-9
lines changed

src/komm/_error_control_convolutional/ConvolutionalCode.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,43 @@ def feedback_taps(self) -> list[npt.NDArray[np.integer]]:
273273
for nu, q in zip(self.constraint_lengths, self.feedback_polynomials)
274274
]
275275

276+
@cache
277+
def free_distance(self) -> int:
278+
r"""
279+
Returns the *free distance* $d_\mathrm{free}$ of the code. This is equal to the minimum Hamming weight among all non-zero encoded bit sequences
280+
281+
Examples:
282+
>>> code = komm.ConvolutionalCode([[0b111, 0b101]])
283+
>>> code.free_distance()
284+
5
285+
"""
286+
fsm = self.finite_state_machine()
287+
288+
def hamming_weight(y: int, _: int) -> int:
289+
return y.bit_count()
290+
291+
# Start at all-zero state
292+
metrics = np.full(fsm.num_states, np.inf)
293+
metrics[0] = 0.0
294+
295+
_, metrics = fsm.viterbi(
296+
observed=[-1], # dummy
297+
metric_function=hamming_weight,
298+
initial_metrics=metrics,
299+
)
300+
301+
# Block return to all-zero state at the first step
302+
metrics[0] = np.inf
303+
304+
while metrics[0] > np.min(metrics[1:]):
305+
_, metrics = fsm.viterbi(
306+
observed=[-1], # dummy
307+
metric_function=hamming_weight,
308+
initial_metrics=metrics,
309+
)
310+
311+
return int(metrics[0])
312+
276313
@cache
277314
def state_space_representation(
278315
self,

src/komm/_finite_state_machine/MealyMachine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def viterbi(
212212
final_metrics: The final metrics for each state. It is a 1D-array of length $|\mathcal{S}|$.
213213
"""
214214
L, num_states = len(observed), self.num_states
215-
choices = np.empty((L, num_states), dtype=int)
215+
choices = np.zeros((L, num_states), dtype=int)
216216
metrics = np.full((L + 1, num_states), fill_value=np.inf)
217217
if initial_metrics is None:
218218
metrics[0, :] = np.zeros(num_states, dtype=float)

tests/error_control_convolutional/test_convolutional_code.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,6 @@ def test_convolutional_code_free_distance_g(
295295
overall_constraint_length, feedforward_polynomials, free_distance
296296
):
297297
# Lin.Costello.04, p. 539--540
298-
convolutional_code = komm.ConvolutionalCode(feedforward_polynomials)
299-
assert convolutional_code.overall_constraint_length == overall_constraint_length
300-
code = komm.TerminatedConvolutionalCode(
301-
convolutional_code=convolutional_code,
302-
num_blocks=overall_constraint_length,
303-
mode="zero-termination",
304-
)
305-
assert code.minimum_distance() == free_distance
298+
code = komm.ConvolutionalCode(feedforward_polynomials)
299+
assert code.overall_constraint_length == overall_constraint_length
300+
assert code.free_distance() == free_distance

0 commit comments

Comments
 (0)