use oxilean_kernel::{Declaration, Environment, Expr, Name};
use super::types::{
BICMCapacityEstimator, BinaryVector, BurstErrorDetector, CSMeasurementMatrix, ChannelCapacity,
ConvolutionalEncoder, FountainCode, GF2m, HammingCode, HammingCode74, LinearCode, PolarCode,
PolarCodeBEC, ProductCode, ReedMullerCode, ReedSolomonCode, TurboCode,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(oxilean_kernel::Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(oxilean_kernel::Level::succ(oxilean_kernel::Level::zero()))
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
Expr::Pi(
oxilean_kernel::BinderInfo::Default,
Name::str("_"),
Box::new(a),
Box::new(b),
)
}
pub fn linear_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn generator_matrix_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn parity_check_matrix_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn hamming_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn singleton_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn plotkin_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn shannon_channel_coding_ty() -> Expr {
arrow(cst("Real"), arrow(cst("Real"), prop()))
}
pub fn noisy_channel_ty() -> Expr {
arrow(cst("Real"), prop())
}
pub fn hamming_perfect_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn reed_solomon_mds_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn systematic_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn dual_code_parity_check_is_generator_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn systematic_encoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn hamming_code_optimal_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn extended_hamming_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn reed_solomon_min_distance_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn reed_solomon_eval_encoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn bch_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn bch_design_distance_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn bch_roots_extension_field_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn ldpc_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn gallager_ldpc_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn belief_propagation_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn polar_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn polar_code_capacity_achieving_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn channel_polarization_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn turbo_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn turbo_code_near_capacity_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn convolutional_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn viterbi_algorithm_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn expander_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn expander_code_linear_time_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn fountain_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn luby_transform_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn raptor_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn network_coding_capacity_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn linear_network_coding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn space_time_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn alamouti_scheme_ty() -> Expr {
prop()
}
pub fn lattice_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn minkowski_lattice_theorem_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn list_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn guruswami_sudan_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn parvaresh_vardy_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn algebraic_geometry_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn goppa_code_min_distance_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn tsfasman_vladut_zink_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn stabilizer_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn css_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn toric_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn quantum_hamming_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn quantum_singleton_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn elias_bassalygo_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn mrrw_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn gilbert_varshamov_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn griesmer_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn capacity_achieving_sequence_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn shannon_entropy_ty() -> Expr {
arrow(nat_ty(), cst("Real"))
}
pub fn mutual_information_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), cst("Real")))
}
pub fn regenerating_code_ty() -> Expr {
arrow(
nat_ty(),
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0()))),
)
}
pub fn minimum_storage_regenerating_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn minimum_bandwidth_regenerating_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn locally_decodable_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn locally_decodable_code_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn trellis_coded_modulation_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn ungerboeck_coded_modulation_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn surface_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn surface_code_threshold_ty() -> Expr {
prop()
}
pub fn color_code_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn color_code_transversal_gates_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn quantum_ldpc_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn quantum_ldpc_good_code_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn spatially_coupled_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn threshold_saturation_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn reed_muller_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn reed_muller_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn reed_muller_capacity_achieving_ty() -> Expr {
prop()
}
pub fn universally_decodable_matrix_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn udm_capacity_achieving_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn compressed_sensing_matrix_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn restricted_isometry_property_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn basis_pursuit_recovery_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn mimo_capacity_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn mimo_spacetime_diversity_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn product_code_ty() -> Expr {
arrow(
nat_ty(),
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0()))),
)
}
pub fn concatenated_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn concatenated_code_decoding_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn interleaved_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn burst_error_correction_interleaving_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn polar_code_bec_capacity_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn ldpc_capacity_bec_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn ldpc_capacity_awgn_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn crc_polar_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn polar_code_successive_cancellation_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn polar_code_scl_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn bit_interleaved_coded_modulation_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn bicm_capacity_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn nonbinary_ldpc_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn nonbinary_turbo_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn qary_polar_code_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn wozencraft_ensemble_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn random_linear_code_gv_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn mac_williams_transform_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn weight_enumerator_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn blahut_arimoto_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn rate_distortion_function_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn channel_capacity_converse_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn build_coding_theory_env(env: &mut Environment) {
let axioms: &[(&str, Expr)] = &[
("LinearCode", linear_code_ty()),
("GeneratorMatrix", generator_matrix_ty()),
("ParityCheckMatrix", parity_check_matrix_ty()),
("HammingBound", hamming_bound_ty()),
("SingletonBound", singleton_bound_ty()),
("PlotkinBound", plotkin_bound_ty()),
("shannon_channel_coding", shannon_channel_coding_ty()),
("noisy_channel", noisy_channel_ty()),
("hamming_perfect", hamming_perfect_ty()),
("reed_solomon_mds", reed_solomon_mds_ty()),
("BinaryEntropy", arrow(cst("Real"), cst("Real"))),
("BSCCapacity", arrow(cst("Real"), cst("Real"))),
("BECCapacity", arrow(cst("Real"), cst("Real"))),
("AWGNCapacity", arrow(cst("Real"), cst("Real"))),
("HammingCode", arrow(nat_ty(), type0())),
("ReedSolomon", arrow(nat_ty(), arrow(nat_ty(), type0()))),
("PerfectCode", arrow(type0(), prop())),
("MDS", arrow(type0(), prop())),
("ReliableComm", arrow(cst("Real"), prop())),
("SystematicCode", systematic_code_ty()),
(
"dual_code_parity_check_is_generator",
dual_code_parity_check_is_generator_ty(),
),
("systematic_encoding", systematic_encoding_ty()),
("HammingCodeOptimal", hamming_code_optimal_ty()),
("ExtendedHammingCode", extended_hamming_code_ty()),
("ReedSolomonMinDistance", reed_solomon_min_distance_ty()),
("ReedSolomonEvalEncoding", reed_solomon_eval_encoding_ty()),
("BCHCode", bch_code_ty()),
("BCHDesignDistance", bch_design_distance_ty()),
("BCHRootsExtensionField", bch_roots_extension_field_ty()),
("LDPCCode", ldpc_code_ty()),
("GallagerLDPC", gallager_ldpc_ty()),
(
"BeliefPropagationDecoding",
belief_propagation_decoding_ty(),
),
("PolarCode", polar_code_ty()),
(
"PolarCodeCapacityAchieving",
polar_code_capacity_achieving_ty(),
),
("ChannelPolarization", channel_polarization_ty()),
("TurboCode", turbo_code_ty()),
("TurboCodeNearCapacity", turbo_code_near_capacity_ty()),
("ConvolutionalCode", convolutional_code_ty()),
("ViterbiAlgorithm", viterbi_algorithm_ty()),
("ExpanderCode", expander_code_ty()),
(
"ExpanderCodeLinearTimeDecoding",
expander_code_linear_time_decoding_ty(),
),
("FountainCode", fountain_code_ty()),
("LubyTransformCode", luby_transform_code_ty()),
("RaptorCode", raptor_code_ty()),
("NetworkCodingCapacity", network_coding_capacity_ty()),
("LinearNetworkCoding", linear_network_coding_ty()),
("SpaceTimeCode", space_time_code_ty()),
("AlamoutiScheme", alamouti_scheme_ty()),
("LatticeCode", lattice_code_ty()),
("MinkowskiLatticeTheorem", minkowski_lattice_theorem_ty()),
("ListDecoding", list_decoding_ty()),
("GuruswamiSudanDecoding", guruswami_sudan_decoding_ty()),
("ParvareshVardyDecoding", parvaresh_vardy_decoding_ty()),
("AlgebraicGeometryCode", algebraic_geometry_code_ty()),
("GoppaCodeMinDistance", goppa_code_min_distance_ty()),
("TsfasmanVladutZink", tsfasman_vladut_zink_ty()),
("StabilizerCode", stabilizer_code_ty()),
("CSSCode", css_code_ty()),
("ToricCode", toric_code_ty()),
("QuantumHammingBound", quantum_hamming_bound_ty()),
("QuantumSingleton", quantum_singleton_ty()),
("EliasBassalygo", elias_bassalygo_ty()),
("MRRWBound", mrrw_bound_ty()),
("GilbertVarshamov", gilbert_varshamov_ty()),
("GreismerBound", griesmer_bound_ty()),
(
"CapacityAchievingSequence",
capacity_achieving_sequence_ty(),
),
("ShannonEntropy", shannon_entropy_ty()),
("MutualInformation", mutual_information_ty()),
("RegeneratingCode", regenerating_code_ty()),
(
"MinimumStorageRegenerating",
minimum_storage_regenerating_ty(),
),
(
"MinimumBandwidthRegenerating",
minimum_bandwidth_regenerating_ty(),
),
("LocallyDecodableCode", locally_decodable_code_ty()),
(
"LocallyDecodableCodeBound",
locally_decodable_code_bound_ty(),
),
("TrellisCodedModulation", trellis_coded_modulation_ty()),
(
"UngerboeckCodedModulation",
ungerboeck_coded_modulation_ty(),
),
("SurfaceCode", surface_code_ty()),
("SurfaceCodeThreshold", surface_code_threshold_ty()),
("ColorCode", color_code_ty()),
(
"ColorCodeTransversalGates",
color_code_transversal_gates_ty(),
),
("QuantumLDPCCode", quantum_ldpc_code_ty()),
("QuantumLDPCGoodCode", quantum_ldpc_good_code_ty()),
("SpatiallyCoupledCode", spatially_coupled_code_ty()),
("ThresholdSaturation", threshold_saturation_ty()),
("ReedMullerCode", reed_muller_code_ty()),
("ReedMullerDecoding", reed_muller_decoding_ty()),
(
"ReedMullerCapacityAchieving",
reed_muller_capacity_achieving_ty(),
),
(
"UniversallyDecodableMatrix",
universally_decodable_matrix_ty(),
),
("UDMCapacityAchieving", udm_capacity_achieving_ty()),
("CompressedSensingMatrix", compressed_sensing_matrix_ty()),
(
"RestrictedIsometryProperty",
restricted_isometry_property_ty(),
),
("BasisPursuitRecovery", basis_pursuit_recovery_ty()),
("MIMOCapacity", mimo_capacity_ty()),
("MIMOSpacetimeDiversity", mimo_spacetime_diversity_ty()),
("ProductCode", product_code_ty()),
("ConcatenatedCode", concatenated_code_ty()),
("ConcatenatedCodeDecoding", concatenated_code_decoding_ty()),
("InterleavedCode", interleaved_code_ty()),
(
"BurstErrorCorrectionInterleaving",
burst_error_correction_interleaving_ty(),
),
("PolarCodeBECCapacity", polar_code_bec_capacity_ty()),
("LDPCCapacityBEC", ldpc_capacity_bec_ty()),
("LDPCCapacityAWGN", ldpc_capacity_awgn_ty()),
("CRCPolarCode", crc_polar_code_ty()),
(
"PolarCodeSuccessiveCancellation",
polar_code_successive_cancellation_ty(),
),
("PolarCodeSCL", polar_code_scl_ty()),
(
"BitInterleavedCodedModulation",
bit_interleaved_coded_modulation_ty(),
),
("BICMCapacity", bicm_capacity_ty()),
("NonbinaryLDPC", nonbinary_ldpc_ty()),
("NonbinaryTurboCode", nonbinary_turbo_code_ty()),
("QaryPolarCode", qary_polar_code_ty()),
("WozencraftEnsemble", wozencraft_ensemble_ty()),
("RandomLinearCodeGV", random_linear_code_gv_ty()),
("MacWilliamsTransform", mac_williams_transform_ty()),
("WeightEnumerator", weight_enumerator_ty()),
("BlahutArimoto", blahut_arimoto_ty()),
("RateDistortionFunction", rate_distortion_function_ty()),
("ChannelCapacityConverse", channel_capacity_converse_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
}
pub fn hamming_ball_volume(n: usize, t: usize) -> usize {
let mut vol = 0usize;
let mut binom = 1usize;
for i in 0..=t {
vol = vol.saturating_add(binom);
if i < t {
binom = binom.saturating_mul(n - i) / (i + 1);
}
}
vol
}
pub fn erfc_approx(x: f64) -> f64 {
if x < 0.0 {
return 2.0 - erfc_approx(-x);
}
let t = 1.0 / (1.0 + 0.3275911 * x);
let poly = t
* (0.254829592
+ t * (-0.284496736 + t * (1.421413741 + t * (-1.453152027 + t * 1.061405429))));
poly * (-x * x).exp()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_binary_vector_hamming_weight() {
let v = BinaryVector::from_bits(vec![true, false, true, true, false]);
assert_eq!(v.hamming_weight(), 3);
let z = BinaryVector::new(4);
assert_eq!(z.hamming_weight(), 0);
}
#[test]
fn test_binary_vector_xor_dot() {
let a = BinaryVector::from_bits(vec![true, false, true]);
let b = BinaryVector::from_bits(vec![true, true, false]);
let c = a.xor(&b);
assert_eq!(c.bits, vec![false, true, true]);
assert!(a.dot(&b));
let x = BinaryVector::from_bits(vec![true, false, false]);
let y = BinaryVector::from_bits(vec![false, true, false]);
assert!(!x.dot(&y));
}
#[test]
fn test_binary_vector_hamming_distance() {
let a = BinaryVector::from_bits(vec![true, false, true, false]);
let b = BinaryVector::from_bits(vec![false, false, true, true]);
assert_eq!(a.hamming_distance(&b), 2);
}
#[test]
fn test_linear_code_rate_redundancy() {
let code = LinearCode::new(7, 4, 3);
assert!((code.rate() - 4.0 / 7.0).abs() < 1e-10);
assert_eq!(code.redundancy(), 3);
assert_eq!(code.corrects_errors(), 1);
assert_eq!(code.detects_errors(), 2);
}
#[test]
fn test_singleton_bound_mds() {
let mds = LinearCode::new(7, 4, 4);
assert!(mds.meets_singleton_bound());
let not_mds = LinearCode::new(7, 4, 3);
assert!(!not_mds.meets_singleton_bound());
}
#[test]
fn test_hamming_code_parameters() {
let ham = HammingCode::new(3);
let lc = ham.to_linear_code();
assert_eq!(lc.n, 7);
assert_eq!(lc.k, 4);
assert_eq!(lc.d_min, 3);
assert_eq!(lc.corrects_errors(), 1);
}
#[test]
fn test_hamming_code_is_perfect() {
let ham = HammingCode::new(3);
let lc = ham.to_linear_code();
assert!(lc.meets_hamming_bound());
}
#[test]
fn test_hamming_74_encode_is_codeword() {
let ham = HammingCode74::new();
let msg = BinaryVector::from_bits(vec![true, false, true, true]);
let cw = ham.encode(&msg);
assert_eq!(cw.bits.len(), 7);
assert!(ham.inner.is_codeword(&cw));
}
#[test]
fn test_hamming_74_single_error_correction() {
let ham = HammingCode74::new();
let msg = BinaryVector::from_bits(vec![true, false, true, false]);
let cw = ham.encode(&msg);
let mut received = cw.clone();
received.bits[2] ^= true;
let corrected = ham.correct(&received);
assert_eq!(corrected.bits, cw.bits);
}
#[test]
fn test_linear_code_matrix_encode_syndrome() {
let ham = HammingCode74::new();
let msg = BinaryVector::from_bits(vec![false, true, false, true]);
let cw = ham.encode(&msg);
let syn = ham.syndrome(&cw);
assert_eq!(syn.hamming_weight(), 0);
}
#[test]
fn test_reed_solomon_encode() {
let rs = ReedSolomonCode::new(7, 3, 11);
let cw = rs.encode(&[1, 2, 3]);
assert_eq!(cw.len(), 7);
assert!(cw.iter().all(|&v| v < 11));
assert_eq!(rs.min_distance(), 5);
assert_eq!(rs.error_correction_capability(), 2);
}
#[test]
fn test_reed_solomon_zero_message() {
let rs = ReedSolomonCode::new(5, 3, 7);
let cw = rs.encode(&[0, 0, 0]);
assert!(cw.iter().all(|&v| v == 0));
}
#[test]
fn test_convolutional_encoder_basic() {
let mut enc = ConvolutionalEncoder::new(1, 2, 3, vec![0b111, 0b101]);
enc.reset();
let out = enc.encode_bit(true);
assert_eq!(out.len(), 2);
assert_eq!(out, vec![true, true]);
}
#[test]
fn test_convolutional_encoder_flush() {
let mut enc = ConvolutionalEncoder::new(1, 2, 3, vec![0b111, 0b101]);
enc.reset();
let _ = enc.encode(&[true, false, true]);
let tail = enc.flush();
assert_eq!(tail.len(), 4);
}
#[test]
fn test_channel_capacity_bsc() {
assert!((ChannelCapacity::bsc_capacity(0.0) - 1.0).abs() < 1e-10);
assert!(ChannelCapacity::bsc_capacity(0.5).abs() < 1e-10);
assert!((ChannelCapacity::bsc_capacity(1.0) - 1.0).abs() < 1e-10);
}
#[test]
fn test_channel_capacity_bec_awgn() {
assert!((ChannelCapacity::bec_capacity(0.5) - 0.5).abs() < 1e-10);
assert!(ChannelCapacity::awgn_capacity(0.0).abs() < 1e-10);
assert!((ChannelCapacity::awgn_capacity(1.0) - 0.5).abs() < 1e-10);
}
#[test]
fn test_q_ary_entropy() {
assert!(ChannelCapacity::q_ary_entropy(0.0, 4).abs() < 1e-10);
assert!(ChannelCapacity::q_ary_entropy(1.0, 4).abs() < 1e-10);
let p = 0.3;
let bh = ChannelCapacity::binary_entropy(p);
let qh = ChannelCapacity::q_ary_entropy(p, 2);
assert!((bh - qh).abs() < 1e-8, "bh={bh} qh={qh}");
}
#[test]
fn test_gf2m_arithmetic() {
let gf = GF2m::new(3, 11);
assert_eq!(gf.size, 8);
assert_eq!(gf.pow(0), 1);
assert_eq!(gf.pow(1), 2);
assert_eq!(gf.pow(2), 4);
assert_eq!(gf.pow(7), gf.pow(0));
assert_eq!(gf.mul(1, 1), 1);
assert_eq!(gf.add(3, 5), 6);
assert_eq!(gf.mul(gf.inv(2), 2), 1);
}
#[test]
fn test_burst_error_detector() {
let det = BurstErrorDetector::new(7, 2, vec![true, true, true]);
let zero_cw = BinaryVector::new(7);
assert!(det.is_valid(&zero_cw));
let mut errored = BinaryVector::new(7);
errored.bits[3] = true;
let syn = det.compute_syndrome(&errored);
assert_ne!(syn.hamming_weight(), 0);
}
#[test]
fn test_build_coding_theory_env() {
let mut env = Environment::new();
build_coding_theory_env(&mut env);
assert!(env.get(&Name::str("LinearCode")).is_some());
assert!(env.get(&Name::str("shannon_channel_coding")).is_some());
assert!(env.get(&Name::str("hamming_perfect")).is_some());
assert!(env.get(&Name::str("reed_solomon_mds")).is_some());
assert!(env.get(&Name::str("BCHCode")).is_some());
assert!(env.get(&Name::str("PolarCode")).is_some());
assert!(env.get(&Name::str("TurboCode")).is_some());
assert!(env.get(&Name::str("LDPCCode")).is_some());
assert!(env.get(&Name::str("StabilizerCode")).is_some());
assert!(env.get(&Name::str("CSSCode")).is_some());
assert!(env.get(&Name::str("ToricCode")).is_some());
assert!(env.get(&Name::str("EliasBassalygo")).is_some());
assert!(env.get(&Name::str("MRRWBound")).is_some());
assert!(env.get(&Name::str("GilbertVarshamov")).is_some());
assert!(env.get(&Name::str("GuruswamiSudanDecoding")).is_some());
assert!(env.get(&Name::str("RegeneratingCode")).is_some());
assert!(env.get(&Name::str("LocallyDecodableCode")).is_some());
assert!(env.get(&Name::str("AlamoutiScheme")).is_some());
assert!(env.get(&Name::str("TrellisCodedModulation")).is_some());
assert!(env.get(&Name::str("SurfaceCode")).is_some());
assert!(env.get(&Name::str("ColorCode")).is_some());
assert!(env.get(&Name::str("QuantumLDPCCode")).is_some());
assert!(env.get(&Name::str("ReedMullerCode")).is_some());
assert!(env.get(&Name::str("CompressedSensingMatrix")).is_some());
assert!(env.get(&Name::str("RestrictedIsometryProperty")).is_some());
assert!(env.get(&Name::str("MIMOCapacity")).is_some());
assert!(env.get(&Name::str("ProductCode")).is_some());
assert!(env.get(&Name::str("WeightEnumerator")).is_some());
assert!(env.get(&Name::str("BlahutArimoto")).is_some());
assert!(env.get(&Name::str("RateDistortionFunction")).is_some());
assert!(env.get(&Name::str("ChannelCapacityConverse")).is_some());
}
#[test]
fn test_reed_muller_code_parameters() {
let rm = ReedMullerCode::new(1, 3);
assert_eq!(rm.block_length(), 8);
assert_eq!(rm.min_distance(), 4);
assert_eq!(rm.dimension(), 4);
assert!(rm.is_first_order());
assert_eq!(rm.error_correction_capability(), 1);
let rm2 = ReedMullerCode::new(2, 4);
assert_eq!(rm2.block_length(), 16);
assert_eq!(rm2.min_distance(), 4);
assert_eq!(rm2.dimension(), 11);
assert!(!rm2.is_first_order());
}
#[test]
fn test_product_code_parameters() {
let c1 = LinearCode::new(7, 4, 3);
let c2 = LinearCode::new(5, 3, 3);
let pc = ProductCode::new(c1, c2);
assert_eq!(pc.block_length(), 35);
assert_eq!(pc.dimension(), 12);
assert_eq!(pc.min_distance(), 9);
let rate = pc.rate();
assert!((rate - 12.0 / 35.0).abs() < 1e-10);
}
#[test]
fn test_polar_code_bec_construction() {
let polar = PolarCodeBEC::new(4, 8, 0.5);
assert_eq!(polar.block_length(), 16);
assert_eq!(polar.dimension(), 8);
let rate = polar.rate();
assert!((rate - 0.5).abs() < 1e-10);
for &z in &polar.erasure_probs {
assert!(z >= 0.0 && z <= 1.0 + 1e-12);
}
let frac = polar.fraction_good(0.01);
assert!(frac >= 0.0 && frac <= 1.0);
}
#[test]
fn test_cs_measurement_matrix() {
let data = vec![1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
let phi = CSMeasurementMatrix::from_data(3, 3, data);
assert!(phi.mutual_coherence() < 1e-10);
let y = phi.apply(&[1.0, 2.0, 3.0]);
assert!((y[0] - 1.0).abs() < 1e-10);
assert!((y[1] - 2.0).abs() < 1e-10);
assert!((y[2] - 3.0).abs() < 1e-10);
}
#[test]
fn test_bicm_capacity_bpsk() {
let bpsk = BICMCapacityEstimator::new(2);
assert_eq!(bpsk.bits_per_symbol, 1);
assert_eq!(bpsk.spectral_efficiency_upper_bound(), 1.0);
let cap = bpsk.approximate_capacity_db(30.0);
assert!(cap > 0.99 && cap <= 1.0);
let cap_low = bpsk.approximate_capacity_db(-10.0);
assert!(cap_low >= 0.0 && cap_low < 0.5);
}
#[test]
fn test_bicm_capacity_qam() {
let qam16 = BICMCapacityEstimator::new(16);
assert_eq!(qam16.bits_per_symbol, 4);
assert_eq!(qam16.spectral_efficiency_upper_bound(), 4.0);
let cap = qam16.approximate_capacity_db(20.0);
assert!(cap > 0.0 && cap <= 4.0);
}
}
#[allow(dead_code)]
pub fn binomial(n: usize, k: usize) -> usize {
if k > n {
return 0;
}
let mut result = 1usize;
for i in 0..k.min(n - k) {
result = result.saturating_mul(n - i);
result /= i + 1;
}
result
}
#[cfg(test)]
mod tests_coding_extra {
use super::*;
#[test]
fn test_reed_solomon() {
let rs = ReedSolomonCode::new(7, 4, 8);
assert_eq!(rs.distance(), 4);
assert!(rs.is_mds());
assert_eq!(rs.error_correction_capacity(), 1);
assert_eq!(rs.erasure_correction_capacity(), 3);
assert!((rs.rate() - 4.0 / 7.0).abs() < 1e-9);
}
#[test]
fn test_turbo_code() {
let tc = TurboCode::standard_3gpp(1024);
assert!(tc.overall_rate() > 0.0 && tc.overall_rate() < 1.0);
}
#[test]
fn test_polar_code() {
let pc = PolarCode::new(1024, 512);
assert!((pc.rate() - 0.5).abs() < 1e-9);
assert!(pc.is_capacity_achieving());
assert!(pc.successive_cancellation_complexity() > 0);
}
#[test]
fn test_fountain_code() {
let lt = FountainCode::lt_code(1000);
assert!(lt.is_rateless());
let needed = lt.n_symbols_to_decode();
assert!(needed > 1000);
let raptor = FountainCode::raptor_code(1000);
assert!(raptor.decoding_complexity() < lt.decoding_complexity());
}
#[test]
fn test_linear_code() {
let hamming = LinearCode::new(7, 4, 3);
assert!(hamming.satisfies_singleton_bound());
assert!(hamming.satisfies_hamming_bound());
assert!(hamming.is_perfect());
}
}