% Technology example: Hamming(7,4) single-bit error correction.
%
% The received word has one corrupted bit. Syndrome bits identify the bad
% position, then the corrected codeword and decoded payload are derived.

received_bit(packet1, 1, 1).
received_bit(packet1, 2, 0).
received_bit(packet1, 3, 1).
received_bit(packet1, 4, 1).
received_bit(packet1, 5, 1).
received_bit(packet1, 6, 1).
received_bit(packet1, 7, 0).

flip(0, 1).
flip(1, 0).

parity4(A, B, C, D, Parity) :-
  add(A, B, AB),
  add(AB, C, ABC),
  add(ABC, D, Sum),
  mod(Sum, 2, Parity).

syndrome_bit1(Code, S1) :-
  received_bit(Code, 1, B1),
  received_bit(Code, 3, B3),
  received_bit(Code, 5, B5),
  received_bit(Code, 7, B7),
  parity4(B1, B3, B5, B7, S1).

syndrome_bit2(Code, S2) :-
  received_bit(Code, 2, B2),
  received_bit(Code, 3, B3),
  received_bit(Code, 6, B6),
  received_bit(Code, 7, B7),
  parity4(B2, B3, B6, B7, S2).

syndrome_bit4(Code, S4) :-
  received_bit(Code, 4, B4),
  received_bit(Code, 5, B5),
  received_bit(Code, 6, B6),
  received_bit(Code, 7, B7),
  parity4(B4, B5, B6, B7, S4).

syndrome(Code, Syndrome) :-
  syndrome_bit1(Code, S1),
  syndrome_bit2(Code, S2),
  syndrome_bit4(Code, S4),
  mul(S2, 2, WeightedS2),
  mul(S4, 4, WeightedS4),
  add(S1, WeightedS2, Partial),
  add(Partial, WeightedS4, Syndrome).

corrected_bit(Code, Position, Corrected) :-
  syndrome(Code, Position),
  received_bit(Code, Position, Bit),
  flip(Bit, Corrected).

corrected_bit(Code, Position, Bit) :-
  syndrome(Code, ErrorPosition),
  neq(Position, ErrorPosition),
  received_bit(Code, Position, Bit).

corrected_codeword(Code, [B1, B2, B3, B4, B5, B6, B7]) :-
  corrected_bit(Code, 1, B1),
  corrected_bit(Code, 2, B2),
  corrected_bit(Code, 3, B3),
  corrected_bit(Code, 4, B4),
  corrected_bit(Code, 5, B5),
  corrected_bit(Code, 6, B6),
  corrected_bit(Code, 7, B7).

decoded_payload(Code, [D1, D2, D3, D4]) :-
  corrected_bit(Code, 3, D1),
  corrected_bit(Code, 5, D2),
  corrected_bit(Code, 6, D3),
  corrected_bit(Code, 7, D4).

triple(Code, syndrome, Syndrome) :-
  syndrome(Code, Syndrome).

triple(Code, errorBit, Position) :-
  syndrome(Code, Position),
  gt(Position, 0).

triple(Code, correctedCodeword, Codeword) :-
  corrected_codeword(Code, Codeword).

triple(Code, decodedPayload, Payload) :-
  decoded_payload(Code, Payload).

triple(Code, status, single_bit_corrected) :-
  syndrome(Code, Position),
  gt(Position, 0).

triple(Code, reason, "Hamming syndrome identifies the flipped bit position") :-
  syndrome(Code, Position),
  gt(Position, 0).
