1use oxilean_kernel::Node;
6use oxilean_kernel::{Declaration, Environment, Expr, Name};
7
8use super::types::{
9 BICMCapacityEstimator, BinaryVector, BurstErrorDetector, CSMeasurementMatrix, ChannelCapacity,
10 ConvolutionalEncoder, FountainCode, GF2m, HammingCode, HammingCode74, LinearCode, PolarCode,
11 PolarCodeBEC, ProductCode, ReedMullerCode, ReedSolomonCode, TurboCode,
12};
13
14pub fn app(f: Expr, a: Expr) -> Expr {
15 Expr::App(Node::new(f), Node::new(a))
16}
17pub fn cst(s: &str) -> Expr {
18 Expr::Const(Name::str(s), vec![])
19}
20pub fn prop() -> Expr {
21 Expr::Sort(oxilean_kernel::Level::zero())
22}
23pub fn type0() -> Expr {
24 Expr::Sort(oxilean_kernel::Level::succ(oxilean_kernel::Level::zero()))
25}
26pub fn nat_ty() -> Expr {
27 cst("Nat")
28}
29pub fn arrow(a: Expr, b: Expr) -> Expr {
30 Expr::Pi(
31 oxilean_kernel::BinderInfo::Default,
32 Name::str("_"),
33 Node::new(a),
34 Node::new(b),
35 )
36}
37pub fn linear_code_ty() -> Expr {
39 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
40}
41pub fn generator_matrix_ty() -> Expr {
43 arrow(nat_ty(), arrow(nat_ty(), type0()))
44}
45pub fn parity_check_matrix_ty() -> Expr {
47 arrow(nat_ty(), arrow(nat_ty(), type0()))
48}
49pub fn hamming_bound_ty() -> Expr {
51 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
52}
53pub fn singleton_bound_ty() -> Expr {
55 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
56}
57pub fn plotkin_bound_ty() -> Expr {
59 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
60}
61pub fn shannon_channel_coding_ty() -> Expr {
64 arrow(cst("Real"), arrow(cst("Real"), prop()))
65}
66pub fn noisy_channel_ty() -> Expr {
69 arrow(cst("Real"), prop())
70}
71pub fn hamming_perfect_ty() -> Expr {
74 arrow(nat_ty(), prop())
75}
76pub fn reed_solomon_mds_ty() -> Expr {
79 arrow(nat_ty(), arrow(nat_ty(), prop()))
80}
81pub fn systematic_code_ty() -> Expr {
83 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
84}
85pub fn dual_code_parity_check_is_generator_ty() -> Expr {
88 arrow(nat_ty(), arrow(nat_ty(), prop()))
89}
90pub fn systematic_encoding_ty() -> Expr {
93 arrow(nat_ty(), arrow(nat_ty(), prop()))
94}
95pub fn hamming_code_optimal_ty() -> Expr {
98 arrow(nat_ty(), prop())
99}
100pub fn extended_hamming_code_ty() -> Expr {
103 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
104}
105pub fn reed_solomon_min_distance_ty() -> Expr {
108 arrow(nat_ty(), arrow(nat_ty(), prop()))
109}
110pub fn reed_solomon_eval_encoding_ty() -> Expr {
113 arrow(nat_ty(), arrow(nat_ty(), type0()))
114}
115pub fn bch_code_ty() -> Expr {
118 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
119}
120pub fn bch_design_distance_ty() -> Expr {
123 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
124}
125pub fn bch_roots_extension_field_ty() -> Expr {
128 arrow(nat_ty(), arrow(nat_ty(), prop()))
129}
130pub fn ldpc_code_ty() -> Expr {
132 arrow(nat_ty(), arrow(nat_ty(), type0()))
133}
134pub fn gallager_ldpc_ty() -> Expr {
137 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
138}
139pub fn belief_propagation_decoding_ty() -> Expr {
142 arrow(nat_ty(), arrow(nat_ty(), prop()))
143}
144pub fn polar_code_ty() -> Expr {
146 arrow(nat_ty(), type0())
147}
148pub fn polar_code_capacity_achieving_ty() -> Expr {
151 arrow(nat_ty(), prop())
152}
153pub fn channel_polarization_ty() -> Expr {
156 arrow(nat_ty(), prop())
157}
158pub fn turbo_code_ty() -> Expr {
160 arrow(nat_ty(), arrow(nat_ty(), type0()))
161}
162pub fn turbo_code_near_capacity_ty() -> Expr {
165 arrow(nat_ty(), arrow(nat_ty(), prop()))
166}
167pub fn convolutional_code_ty() -> Expr {
170 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
171}
172pub fn viterbi_algorithm_ty() -> Expr {
175 arrow(nat_ty(), arrow(nat_ty(), prop()))
176}
177pub fn expander_code_ty() -> Expr {
179 arrow(nat_ty(), arrow(nat_ty(), type0()))
180}
181pub fn expander_code_linear_time_decoding_ty() -> Expr {
184 arrow(nat_ty(), arrow(nat_ty(), prop()))
185}
186pub fn fountain_code_ty() -> Expr {
188 arrow(nat_ty(), type0())
189}
190pub fn luby_transform_code_ty() -> Expr {
192 arrow(nat_ty(), type0())
193}
194pub fn raptor_code_ty() -> Expr {
196 arrow(nat_ty(), type0())
197}
198pub fn network_coding_capacity_ty() -> Expr {
201 arrow(nat_ty(), arrow(nat_ty(), prop()))
202}
203pub fn linear_network_coding_ty() -> Expr {
206 arrow(nat_ty(), arrow(nat_ty(), prop()))
207}
208pub fn space_time_code_ty() -> Expr {
211 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
212}
213pub fn alamouti_scheme_ty() -> Expr {
216 prop()
217}
218pub fn lattice_code_ty() -> Expr {
220 arrow(nat_ty(), type0())
221}
222pub fn minkowski_lattice_theorem_ty() -> Expr {
225 arrow(nat_ty(), prop())
226}
227pub fn list_decoding_ty() -> Expr {
230 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
231}
232pub fn guruswami_sudan_decoding_ty() -> Expr {
235 arrow(nat_ty(), arrow(nat_ty(), prop()))
236}
237pub fn parvaresh_vardy_decoding_ty() -> Expr {
240 arrow(nat_ty(), arrow(nat_ty(), prop()))
241}
242pub fn algebraic_geometry_code_ty() -> Expr {
245 arrow(nat_ty(), arrow(nat_ty(), type0()))
246}
247pub fn goppa_code_min_distance_ty() -> Expr {
250 arrow(nat_ty(), arrow(nat_ty(), prop()))
251}
252pub fn tsfasman_vladut_zink_ty() -> Expr {
255 arrow(nat_ty(), prop())
256}
257pub fn stabilizer_code_ty() -> Expr {
260 arrow(nat_ty(), arrow(nat_ty(), type0()))
261}
262pub fn css_code_ty() -> Expr {
265 arrow(nat_ty(), arrow(nat_ty(), type0()))
266}
267pub fn toric_code_ty() -> Expr {
270 arrow(nat_ty(), type0())
271}
272pub fn quantum_hamming_bound_ty() -> Expr {
275 arrow(nat_ty(), arrow(nat_ty(), prop()))
276}
277pub fn quantum_singleton_ty() -> Expr {
280 arrow(nat_ty(), arrow(nat_ty(), prop()))
281}
282pub fn elias_bassalygo_ty() -> Expr {
285 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
286}
287pub fn mrrw_bound_ty() -> Expr {
290 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
291}
292pub fn gilbert_varshamov_ty() -> Expr {
296 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
297}
298pub fn griesmer_bound_ty() -> Expr {
301 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
302}
303pub fn capacity_achieving_sequence_ty() -> Expr {
306 arrow(nat_ty(), prop())
307}
308pub fn shannon_entropy_ty() -> Expr {
310 arrow(nat_ty(), cst("Real"))
311}
312pub fn mutual_information_ty() -> Expr {
314 arrow(nat_ty(), arrow(nat_ty(), cst("Real")))
315}
316pub fn regenerating_code_ty() -> Expr {
319 arrow(
320 nat_ty(),
321 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0()))),
322 )
323}
324pub fn minimum_storage_regenerating_ty() -> Expr {
327 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
328}
329pub fn minimum_bandwidth_regenerating_ty() -> Expr {
332 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
333}
334pub fn locally_decodable_code_ty() -> Expr {
337 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
338}
339pub fn locally_decodable_code_bound_ty() -> Expr {
342 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
343}
344pub fn trellis_coded_modulation_ty() -> Expr {
347 arrow(nat_ty(), arrow(nat_ty(), type0()))
348}
349pub fn ungerboeck_coded_modulation_ty() -> Expr {
352 arrow(nat_ty(), prop())
353}
354pub fn surface_code_ty() -> Expr {
357 arrow(nat_ty(), type0())
358}
359pub fn surface_code_threshold_ty() -> Expr {
363 prop()
364}
365pub fn color_code_ty() -> Expr {
368 arrow(nat_ty(), type0())
369}
370pub fn color_code_transversal_gates_ty() -> Expr {
373 arrow(nat_ty(), prop())
374}
375pub fn quantum_ldpc_code_ty() -> Expr {
379 arrow(nat_ty(), arrow(nat_ty(), type0()))
380}
381pub fn quantum_ldpc_good_code_ty() -> Expr {
384 arrow(nat_ty(), prop())
385}
386pub fn spatially_coupled_code_ty() -> Expr {
389 arrow(nat_ty(), arrow(nat_ty(), type0()))
390}
391pub fn threshold_saturation_ty() -> Expr {
394 arrow(nat_ty(), prop())
395}
396pub fn reed_muller_code_ty() -> Expr {
399 arrow(nat_ty(), arrow(nat_ty(), type0()))
400}
401pub fn reed_muller_decoding_ty() -> Expr {
405 arrow(nat_ty(), arrow(nat_ty(), prop()))
406}
407pub fn reed_muller_capacity_achieving_ty() -> Expr {
410 prop()
411}
412pub fn universally_decodable_matrix_ty() -> Expr {
415 arrow(nat_ty(), arrow(nat_ty(), type0()))
416}
417pub fn udm_capacity_achieving_ty() -> Expr {
420 arrow(nat_ty(), arrow(nat_ty(), prop()))
421}
422pub fn compressed_sensing_matrix_ty() -> Expr {
425 arrow(nat_ty(), arrow(nat_ty(), type0()))
426}
427pub fn restricted_isometry_property_ty() -> Expr {
430 arrow(nat_ty(), arrow(nat_ty(), prop()))
431}
432pub fn basis_pursuit_recovery_ty() -> Expr {
436 arrow(nat_ty(), arrow(nat_ty(), prop()))
437}
438pub fn mimo_capacity_ty() -> Expr {
442 arrow(nat_ty(), arrow(nat_ty(), prop()))
443}
444pub fn mimo_spacetime_diversity_ty() -> Expr {
447 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
448}
449pub fn product_code_ty() -> Expr {
452 arrow(
453 nat_ty(),
454 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0()))),
455 )
456}
457pub fn concatenated_code_ty() -> Expr {
460 arrow(nat_ty(), arrow(nat_ty(), type0()))
461}
462pub fn concatenated_code_decoding_ty() -> Expr {
466 arrow(nat_ty(), arrow(nat_ty(), prop()))
467}
468pub fn interleaved_code_ty() -> Expr {
471 arrow(nat_ty(), arrow(nat_ty(), type0()))
472}
473pub fn burst_error_correction_interleaving_ty() -> Expr {
476 arrow(nat_ty(), arrow(nat_ty(), prop()))
477}
478pub fn polar_code_bec_capacity_ty() -> Expr {
481 arrow(nat_ty(), prop())
482}
483pub fn ldpc_capacity_bec_ty() -> Expr {
486 arrow(nat_ty(), prop())
487}
488pub fn ldpc_capacity_awgn_ty() -> Expr {
491 arrow(nat_ty(), prop())
492}
493pub fn crc_polar_code_ty() -> Expr {
496 arrow(nat_ty(), arrow(nat_ty(), type0()))
497}
498pub fn polar_code_successive_cancellation_ty() -> Expr {
501 arrow(nat_ty(), prop())
502}
503pub fn polar_code_scl_ty() -> Expr {
506 arrow(nat_ty(), arrow(nat_ty(), prop()))
507}
508pub fn bit_interleaved_coded_modulation_ty() -> Expr {
511 arrow(nat_ty(), arrow(nat_ty(), type0()))
512}
513pub fn bicm_capacity_ty() -> Expr {
516 arrow(nat_ty(), arrow(nat_ty(), prop()))
517}
518pub fn nonbinary_ldpc_ty() -> Expr {
521 arrow(nat_ty(), arrow(nat_ty(), type0()))
522}
523pub fn nonbinary_turbo_code_ty() -> Expr {
526 arrow(nat_ty(), arrow(nat_ty(), type0()))
527}
528pub fn qary_polar_code_ty() -> Expr {
531 arrow(nat_ty(), arrow(nat_ty(), type0()))
532}
533pub fn wozencraft_ensemble_ty() -> Expr {
536 arrow(nat_ty(), arrow(nat_ty(), prop()))
537}
538pub fn random_linear_code_gv_ty() -> Expr {
542 arrow(nat_ty(), arrow(nat_ty(), prop()))
543}
544pub fn mac_williams_transform_ty() -> Expr {
548 arrow(nat_ty(), arrow(nat_ty(), prop()))
549}
550pub fn weight_enumerator_ty() -> Expr {
553 arrow(nat_ty(), arrow(nat_ty(), type0()))
554}
555pub fn blahut_arimoto_ty() -> Expr {
558 arrow(nat_ty(), prop())
559}
560pub fn rate_distortion_function_ty() -> Expr {
563 arrow(nat_ty(), arrow(nat_ty(), prop()))
564}
565pub fn channel_capacity_converse_ty() -> Expr {
568 arrow(nat_ty(), prop())
569}
570pub fn build_coding_theory_env(env: &mut Environment) {
572 let axioms: &[(&str, Expr)] = &[
573 ("LinearCode", linear_code_ty()),
574 ("GeneratorMatrix", generator_matrix_ty()),
575 ("ParityCheckMatrix", parity_check_matrix_ty()),
576 ("HammingBound", hamming_bound_ty()),
577 ("SingletonBound", singleton_bound_ty()),
578 ("PlotkinBound", plotkin_bound_ty()),
579 ("shannon_channel_coding", shannon_channel_coding_ty()),
580 ("noisy_channel", noisy_channel_ty()),
581 ("hamming_perfect", hamming_perfect_ty()),
582 ("reed_solomon_mds", reed_solomon_mds_ty()),
583 ("BinaryEntropy", arrow(cst("Real"), cst("Real"))),
584 ("BSCCapacity", arrow(cst("Real"), cst("Real"))),
585 ("BECCapacity", arrow(cst("Real"), cst("Real"))),
586 ("AWGNCapacity", arrow(cst("Real"), cst("Real"))),
587 ("HammingCode", arrow(nat_ty(), type0())),
588 ("ReedSolomon", arrow(nat_ty(), arrow(nat_ty(), type0()))),
589 ("PerfectCode", arrow(type0(), prop())),
590 ("MDS", arrow(type0(), prop())),
591 ("ReliableComm", arrow(cst("Real"), prop())),
592 ("SystematicCode", systematic_code_ty()),
593 (
594 "dual_code_parity_check_is_generator",
595 dual_code_parity_check_is_generator_ty(),
596 ),
597 ("systematic_encoding", systematic_encoding_ty()),
598 ("HammingCodeOptimal", hamming_code_optimal_ty()),
599 ("ExtendedHammingCode", extended_hamming_code_ty()),
600 ("ReedSolomonMinDistance", reed_solomon_min_distance_ty()),
601 ("ReedSolomonEvalEncoding", reed_solomon_eval_encoding_ty()),
602 ("BCHCode", bch_code_ty()),
603 ("BCHDesignDistance", bch_design_distance_ty()),
604 ("BCHRootsExtensionField", bch_roots_extension_field_ty()),
605 ("LDPCCode", ldpc_code_ty()),
606 ("GallagerLDPC", gallager_ldpc_ty()),
607 (
608 "BeliefPropagationDecoding",
609 belief_propagation_decoding_ty(),
610 ),
611 ("PolarCode", polar_code_ty()),
612 (
613 "PolarCodeCapacityAchieving",
614 polar_code_capacity_achieving_ty(),
615 ),
616 ("ChannelPolarization", channel_polarization_ty()),
617 ("TurboCode", turbo_code_ty()),
618 ("TurboCodeNearCapacity", turbo_code_near_capacity_ty()),
619 ("ConvolutionalCode", convolutional_code_ty()),
620 ("ViterbiAlgorithm", viterbi_algorithm_ty()),
621 ("ExpanderCode", expander_code_ty()),
622 (
623 "ExpanderCodeLinearTimeDecoding",
624 expander_code_linear_time_decoding_ty(),
625 ),
626 ("FountainCode", fountain_code_ty()),
627 ("LubyTransformCode", luby_transform_code_ty()),
628 ("RaptorCode", raptor_code_ty()),
629 ("NetworkCodingCapacity", network_coding_capacity_ty()),
630 ("LinearNetworkCoding", linear_network_coding_ty()),
631 ("SpaceTimeCode", space_time_code_ty()),
632 ("AlamoutiScheme", alamouti_scheme_ty()),
633 ("LatticeCode", lattice_code_ty()),
634 ("MinkowskiLatticeTheorem", minkowski_lattice_theorem_ty()),
635 ("ListDecoding", list_decoding_ty()),
636 ("GuruswamiSudanDecoding", guruswami_sudan_decoding_ty()),
637 ("ParvareshVardyDecoding", parvaresh_vardy_decoding_ty()),
638 ("AlgebraicGeometryCode", algebraic_geometry_code_ty()),
639 ("GoppaCodeMinDistance", goppa_code_min_distance_ty()),
640 ("TsfasmanVladutZink", tsfasman_vladut_zink_ty()),
641 ("StabilizerCode", stabilizer_code_ty()),
642 ("CSSCode", css_code_ty()),
643 ("ToricCode", toric_code_ty()),
644 ("QuantumHammingBound", quantum_hamming_bound_ty()),
645 ("QuantumSingleton", quantum_singleton_ty()),
646 ("EliasBassalygo", elias_bassalygo_ty()),
647 ("MRRWBound", mrrw_bound_ty()),
648 ("GilbertVarshamov", gilbert_varshamov_ty()),
649 ("GreismerBound", griesmer_bound_ty()),
650 (
651 "CapacityAchievingSequence",
652 capacity_achieving_sequence_ty(),
653 ),
654 ("ShannonEntropy", shannon_entropy_ty()),
655 ("MutualInformation", mutual_information_ty()),
656 ("RegeneratingCode", regenerating_code_ty()),
657 (
658 "MinimumStorageRegenerating",
659 minimum_storage_regenerating_ty(),
660 ),
661 (
662 "MinimumBandwidthRegenerating",
663 minimum_bandwidth_regenerating_ty(),
664 ),
665 ("LocallyDecodableCode", locally_decodable_code_ty()),
666 (
667 "LocallyDecodableCodeBound",
668 locally_decodable_code_bound_ty(),
669 ),
670 ("TrellisCodedModulation", trellis_coded_modulation_ty()),
671 (
672 "UngerboeckCodedModulation",
673 ungerboeck_coded_modulation_ty(),
674 ),
675 ("SurfaceCode", surface_code_ty()),
676 ("SurfaceCodeThreshold", surface_code_threshold_ty()),
677 ("ColorCode", color_code_ty()),
678 (
679 "ColorCodeTransversalGates",
680 color_code_transversal_gates_ty(),
681 ),
682 ("QuantumLDPCCode", quantum_ldpc_code_ty()),
683 ("QuantumLDPCGoodCode", quantum_ldpc_good_code_ty()),
684 ("SpatiallyCoupledCode", spatially_coupled_code_ty()),
685 ("ThresholdSaturation", threshold_saturation_ty()),
686 ("ReedMullerCode", reed_muller_code_ty()),
687 ("ReedMullerDecoding", reed_muller_decoding_ty()),
688 (
689 "ReedMullerCapacityAchieving",
690 reed_muller_capacity_achieving_ty(),
691 ),
692 (
693 "UniversallyDecodableMatrix",
694 universally_decodable_matrix_ty(),
695 ),
696 ("UDMCapacityAchieving", udm_capacity_achieving_ty()),
697 ("CompressedSensingMatrix", compressed_sensing_matrix_ty()),
698 (
699 "RestrictedIsometryProperty",
700 restricted_isometry_property_ty(),
701 ),
702 ("BasisPursuitRecovery", basis_pursuit_recovery_ty()),
703 ("MIMOCapacity", mimo_capacity_ty()),
704 ("MIMOSpacetimeDiversity", mimo_spacetime_diversity_ty()),
705 ("ProductCode", product_code_ty()),
706 ("ConcatenatedCode", concatenated_code_ty()),
707 ("ConcatenatedCodeDecoding", concatenated_code_decoding_ty()),
708 ("InterleavedCode", interleaved_code_ty()),
709 (
710 "BurstErrorCorrectionInterleaving",
711 burst_error_correction_interleaving_ty(),
712 ),
713 ("PolarCodeBECCapacity", polar_code_bec_capacity_ty()),
714 ("LDPCCapacityBEC", ldpc_capacity_bec_ty()),
715 ("LDPCCapacityAWGN", ldpc_capacity_awgn_ty()),
716 ("CRCPolarCode", crc_polar_code_ty()),
717 (
718 "PolarCodeSuccessiveCancellation",
719 polar_code_successive_cancellation_ty(),
720 ),
721 ("PolarCodeSCL", polar_code_scl_ty()),
722 (
723 "BitInterleavedCodedModulation",
724 bit_interleaved_coded_modulation_ty(),
725 ),
726 ("BICMCapacity", bicm_capacity_ty()),
727 ("NonbinaryLDPC", nonbinary_ldpc_ty()),
728 ("NonbinaryTurboCode", nonbinary_turbo_code_ty()),
729 ("QaryPolarCode", qary_polar_code_ty()),
730 ("WozencraftEnsemble", wozencraft_ensemble_ty()),
731 ("RandomLinearCodeGV", random_linear_code_gv_ty()),
732 ("MacWilliamsTransform", mac_williams_transform_ty()),
733 ("WeightEnumerator", weight_enumerator_ty()),
734 ("BlahutArimoto", blahut_arimoto_ty()),
735 ("RateDistortionFunction", rate_distortion_function_ty()),
736 ("ChannelCapacityConverse", channel_capacity_converse_ty()),
737 ];
738 for (name, ty) in axioms {
739 env.add(Declaration::Axiom {
740 name: Name::str(*name),
741 univ_params: vec![],
742 ty: ty.clone(),
743 })
744 .ok();
745 }
746}
747pub fn hamming_ball_volume(n: usize, t: usize) -> usize {
749 let mut vol = 0usize;
750 let mut binom = 1usize;
751 for i in 0..=t {
752 vol = vol.saturating_add(binom);
753 if i < t {
754 binom = binom.saturating_mul(n - i) / (i + 1);
755 }
756 }
757 vol
758}
759pub fn erfc_approx(x: f64) -> f64 {
764 if x < 0.0 {
765 return 2.0 - erfc_approx(-x);
766 }
767 let t = 1.0 / (1.0 + 0.3275911 * x);
768 let poly = t
769 * (0.254829592
770 + t * (-0.284496736 + t * (1.421413741 + t * (-1.453152027 + t * 1.061405429))));
771 poly * (-x * x).exp()
772}
773#[cfg(test)]
774mod tests {
775 use super::*;
776 #[test]
777 fn test_binary_vector_hamming_weight() {
778 let v = BinaryVector::from_bits(vec![true, false, true, true, false]);
779 assert_eq!(v.hamming_weight(), 3);
780 let z = BinaryVector::new(4);
781 assert_eq!(z.hamming_weight(), 0);
782 }
783 #[test]
784 fn test_binary_vector_xor_dot() {
785 let a = BinaryVector::from_bits(vec![true, false, true]);
786 let b = BinaryVector::from_bits(vec![true, true, false]);
787 let c = a.xor(&b);
788 assert_eq!(c.bits, vec![false, true, true]);
789 assert!(a.dot(&b));
790 let x = BinaryVector::from_bits(vec![true, false, false]);
791 let y = BinaryVector::from_bits(vec![false, true, false]);
792 assert!(!x.dot(&y));
793 }
794 #[test]
795 fn test_binary_vector_hamming_distance() {
796 let a = BinaryVector::from_bits(vec![true, false, true, false]);
797 let b = BinaryVector::from_bits(vec![false, false, true, true]);
798 assert_eq!(a.hamming_distance(&b), 2);
799 }
800 #[test]
801 fn test_linear_code_rate_redundancy() {
802 let code = LinearCode::new(7, 4, 3);
803 assert!((code.rate() - 4.0 / 7.0).abs() < 1e-10);
804 assert_eq!(code.redundancy(), 3);
805 assert_eq!(code.corrects_errors(), 1);
806 assert_eq!(code.detects_errors(), 2);
807 }
808 #[test]
809 fn test_singleton_bound_mds() {
810 let mds = LinearCode::new(7, 4, 4);
811 assert!(mds.meets_singleton_bound());
812 let not_mds = LinearCode::new(7, 4, 3);
813 assert!(!not_mds.meets_singleton_bound());
814 }
815 #[test]
816 fn test_hamming_code_parameters() {
817 let ham = HammingCode::new(3);
818 let lc = ham.to_linear_code();
819 assert_eq!(lc.n, 7);
820 assert_eq!(lc.k, 4);
821 assert_eq!(lc.d_min, 3);
822 assert_eq!(lc.corrects_errors(), 1);
823 }
824 #[test]
825 fn test_hamming_code_is_perfect() {
826 let ham = HammingCode::new(3);
827 let lc = ham.to_linear_code();
828 assert!(lc.meets_hamming_bound());
829 }
830 #[test]
831 fn test_hamming_74_encode_is_codeword() {
832 let ham = HammingCode74::new();
833 let msg = BinaryVector::from_bits(vec![true, false, true, true]);
834 let cw = ham.encode(&msg);
835 assert_eq!(cw.bits.len(), 7);
836 assert!(ham.inner.is_codeword(&cw));
837 }
838 #[test]
839 fn test_hamming_74_single_error_correction() {
840 let ham = HammingCode74::new();
841 let msg = BinaryVector::from_bits(vec![true, false, true, false]);
842 let cw = ham.encode(&msg);
843 let mut received = cw.clone();
844 received.bits[2] ^= true;
845 let corrected = ham.correct(&received);
846 assert_eq!(corrected.bits, cw.bits);
847 }
848 #[test]
849 fn test_linear_code_matrix_encode_syndrome() {
850 let ham = HammingCode74::new();
851 let msg = BinaryVector::from_bits(vec![false, true, false, true]);
852 let cw = ham.encode(&msg);
853 let syn = ham.syndrome(&cw);
854 assert_eq!(syn.hamming_weight(), 0);
855 }
856 #[test]
857 fn test_reed_solomon_encode() {
858 let rs = ReedSolomonCode::new(7, 3, 11);
859 let cw = rs.encode(&[1, 2, 3]);
860 assert_eq!(cw.len(), 7);
861 assert!(cw.iter().all(|&v| v < 11));
862 assert_eq!(rs.min_distance(), 5);
863 assert_eq!(rs.error_correction_capability(), 2);
864 }
865 #[test]
866 fn test_reed_solomon_zero_message() {
867 let rs = ReedSolomonCode::new(5, 3, 7);
868 let cw = rs.encode(&[0, 0, 0]);
869 assert!(cw.iter().all(|&v| v == 0));
870 }
871 #[test]
872 fn test_convolutional_encoder_basic() {
873 let mut enc = ConvolutionalEncoder::new(1, 2, 3, vec![0b111, 0b101]);
874 enc.reset();
875 let out = enc.encode_bit(true);
876 assert_eq!(out.len(), 2);
877 assert_eq!(out, vec![true, true]);
878 }
879 #[test]
880 fn test_convolutional_encoder_flush() {
881 let mut enc = ConvolutionalEncoder::new(1, 2, 3, vec![0b111, 0b101]);
882 enc.reset();
883 let _ = enc.encode(&[true, false, true]);
884 let tail = enc.flush();
885 assert_eq!(tail.len(), 4);
886 }
887 #[test]
888 fn test_channel_capacity_bsc() {
889 assert!((ChannelCapacity::bsc_capacity(0.0) - 1.0).abs() < 1e-10);
890 assert!(ChannelCapacity::bsc_capacity(0.5).abs() < 1e-10);
891 assert!((ChannelCapacity::bsc_capacity(1.0) - 1.0).abs() < 1e-10);
892 }
893 #[test]
894 fn test_channel_capacity_bec_awgn() {
895 assert!((ChannelCapacity::bec_capacity(0.5) - 0.5).abs() < 1e-10);
896 assert!(ChannelCapacity::awgn_capacity(0.0).abs() < 1e-10);
897 assert!((ChannelCapacity::awgn_capacity(1.0) - 0.5).abs() < 1e-10);
898 }
899 #[test]
900 fn test_q_ary_entropy() {
901 assert!(ChannelCapacity::q_ary_entropy(0.0, 4).abs() < 1e-10);
902 assert!(ChannelCapacity::q_ary_entropy(1.0, 4).abs() < 1e-10);
903 let p = 0.3;
904 let bh = ChannelCapacity::binary_entropy(p);
905 let qh = ChannelCapacity::q_ary_entropy(p, 2);
906 assert!((bh - qh).abs() < 1e-8, "bh={bh} qh={qh}");
907 }
908 #[test]
909 fn test_gf2m_arithmetic() {
910 let gf = GF2m::new(3, 11);
911 assert_eq!(gf.size, 8);
912 assert_eq!(gf.pow(0), 1);
913 assert_eq!(gf.pow(1), 2);
914 assert_eq!(gf.pow(2), 4);
915 assert_eq!(gf.pow(7), gf.pow(0));
916 assert_eq!(gf.mul(1, 1), 1);
917 assert_eq!(gf.add(3, 5), 6);
918 assert_eq!(gf.mul(gf.inv(2), 2), 1);
919 }
920 #[test]
921 fn test_burst_error_detector() {
922 let det = BurstErrorDetector::new(7, 2, vec![true, true, true]);
923 let zero_cw = BinaryVector::new(7);
924 assert!(det.is_valid(&zero_cw));
925 let mut errored = BinaryVector::new(7);
926 errored.bits[3] = true;
927 let syn = det.compute_syndrome(&errored);
928 assert_ne!(syn.hamming_weight(), 0);
929 }
930 #[test]
931 fn test_build_coding_theory_env() {
932 let mut env = Environment::new();
933 build_coding_theory_env(&mut env);
934 assert!(env.get(&Name::str("LinearCode")).is_some());
935 assert!(env.get(&Name::str("shannon_channel_coding")).is_some());
936 assert!(env.get(&Name::str("hamming_perfect")).is_some());
937 assert!(env.get(&Name::str("reed_solomon_mds")).is_some());
938 assert!(env.get(&Name::str("BCHCode")).is_some());
939 assert!(env.get(&Name::str("PolarCode")).is_some());
940 assert!(env.get(&Name::str("TurboCode")).is_some());
941 assert!(env.get(&Name::str("LDPCCode")).is_some());
942 assert!(env.get(&Name::str("StabilizerCode")).is_some());
943 assert!(env.get(&Name::str("CSSCode")).is_some());
944 assert!(env.get(&Name::str("ToricCode")).is_some());
945 assert!(env.get(&Name::str("EliasBassalygo")).is_some());
946 assert!(env.get(&Name::str("MRRWBound")).is_some());
947 assert!(env.get(&Name::str("GilbertVarshamov")).is_some());
948 assert!(env.get(&Name::str("GuruswamiSudanDecoding")).is_some());
949 assert!(env.get(&Name::str("RegeneratingCode")).is_some());
950 assert!(env.get(&Name::str("LocallyDecodableCode")).is_some());
951 assert!(env.get(&Name::str("AlamoutiScheme")).is_some());
952 assert!(env.get(&Name::str("TrellisCodedModulation")).is_some());
953 assert!(env.get(&Name::str("SurfaceCode")).is_some());
954 assert!(env.get(&Name::str("ColorCode")).is_some());
955 assert!(env.get(&Name::str("QuantumLDPCCode")).is_some());
956 assert!(env.get(&Name::str("ReedMullerCode")).is_some());
957 assert!(env.get(&Name::str("CompressedSensingMatrix")).is_some());
958 assert!(env.get(&Name::str("RestrictedIsometryProperty")).is_some());
959 assert!(env.get(&Name::str("MIMOCapacity")).is_some());
960 assert!(env.get(&Name::str("ProductCode")).is_some());
961 assert!(env.get(&Name::str("WeightEnumerator")).is_some());
962 assert!(env.get(&Name::str("BlahutArimoto")).is_some());
963 assert!(env.get(&Name::str("RateDistortionFunction")).is_some());
964 assert!(env.get(&Name::str("ChannelCapacityConverse")).is_some());
965 }
966 #[test]
967 fn test_reed_muller_code_parameters() {
968 let rm = ReedMullerCode::new(1, 3);
969 assert_eq!(rm.block_length(), 8);
970 assert_eq!(rm.min_distance(), 4);
971 assert_eq!(rm.dimension(), 4);
972 assert!(rm.is_first_order());
973 assert_eq!(rm.error_correction_capability(), 1);
974 let rm2 = ReedMullerCode::new(2, 4);
975 assert_eq!(rm2.block_length(), 16);
976 assert_eq!(rm2.min_distance(), 4);
977 assert_eq!(rm2.dimension(), 11);
978 assert!(!rm2.is_first_order());
979 }
980 #[test]
981 fn test_product_code_parameters() {
982 let c1 = LinearCode::new(7, 4, 3);
983 let c2 = LinearCode::new(5, 3, 3);
984 let pc = ProductCode::new(c1, c2);
985 assert_eq!(pc.block_length(), 35);
986 assert_eq!(pc.dimension(), 12);
987 assert_eq!(pc.min_distance(), 9);
988 let rate = pc.rate();
989 assert!((rate - 12.0 / 35.0).abs() < 1e-10);
990 }
991 #[test]
992 fn test_polar_code_bec_construction() {
993 let polar = PolarCodeBEC::new(4, 8, 0.5);
994 assert_eq!(polar.block_length(), 16);
995 assert_eq!(polar.dimension(), 8);
996 let rate = polar.rate();
997 assert!((rate - 0.5).abs() < 1e-10);
998 for &z in &polar.erasure_probs {
999 assert!(z >= 0.0 && z <= 1.0 + 1e-12);
1000 }
1001 let frac = polar.fraction_good(0.01);
1002 assert!(frac >= 0.0 && frac <= 1.0);
1003 }
1004 #[test]
1005 fn test_cs_measurement_matrix() {
1006 let data = vec![1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0];
1007 let phi = CSMeasurementMatrix::from_data(3, 3, data);
1008 assert!(phi.mutual_coherence() < 1e-10);
1009 let y = phi.apply(&[1.0, 2.0, 3.0]);
1010 assert!((y[0] - 1.0).abs() < 1e-10);
1011 assert!((y[1] - 2.0).abs() < 1e-10);
1012 assert!((y[2] - 3.0).abs() < 1e-10);
1013 }
1014 #[test]
1015 fn test_bicm_capacity_bpsk() {
1016 let bpsk = BICMCapacityEstimator::new(2);
1017 assert_eq!(bpsk.bits_per_symbol, 1);
1018 assert_eq!(bpsk.spectral_efficiency_upper_bound(), 1.0);
1019 let cap = bpsk.approximate_capacity_db(30.0);
1020 assert!(cap > 0.99 && cap <= 1.0);
1021 let cap_low = bpsk.approximate_capacity_db(-10.0);
1022 assert!(cap_low >= 0.0 && cap_low < 0.5);
1023 }
1024 #[test]
1025 fn test_bicm_capacity_qam() {
1026 let qam16 = BICMCapacityEstimator::new(16);
1027 assert_eq!(qam16.bits_per_symbol, 4);
1028 assert_eq!(qam16.spectral_efficiency_upper_bound(), 4.0);
1029 let cap = qam16.approximate_capacity_db(20.0);
1030 assert!(cap > 0.0 && cap <= 4.0);
1031 }
1032}
1033#[allow(dead_code)]
1034pub fn binomial(n: usize, k: usize) -> usize {
1035 if k > n {
1036 return 0;
1037 }
1038 let mut result = 1usize;
1039 for i in 0..k.min(n - k) {
1040 result = result.saturating_mul(n - i);
1041 result /= i + 1;
1042 }
1043 result
1044}
1045#[cfg(test)]
1046mod tests_coding_extra {
1047 use super::*;
1048 #[test]
1049 fn test_reed_solomon() {
1050 let rs = ReedSolomonCode::new(7, 4, 8);
1051 assert_eq!(rs.distance(), 4);
1052 assert!(rs.is_mds());
1053 assert_eq!(rs.error_correction_capacity(), 1);
1054 assert_eq!(rs.erasure_correction_capacity(), 3);
1055 assert!((rs.rate() - 4.0 / 7.0).abs() < 1e-9);
1056 }
1057 #[test]
1058 fn test_turbo_code() {
1059 let tc = TurboCode::standard_3gpp(1024);
1060 assert!(tc.overall_rate() > 0.0 && tc.overall_rate() < 1.0);
1061 }
1062 #[test]
1063 fn test_polar_code() {
1064 let pc = PolarCode::new(1024, 512);
1065 assert!((pc.rate() - 0.5).abs() < 1e-9);
1066 assert!(pc.is_capacity_achieving());
1067 assert!(pc.successive_cancellation_complexity() > 0);
1068 }
1069 #[test]
1070 fn test_fountain_code() {
1071 let lt = FountainCode::lt_code(1000);
1072 assert!(lt.is_rateless());
1073 let needed = lt.n_symbols_to_decode();
1074 assert!(needed > 1000);
1075 let raptor = FountainCode::raptor_code(1000);
1076 assert!(raptor.decoding_complexity() < lt.decoding_complexity());
1077 }
1078 #[test]
1079 fn test_linear_code() {
1080 let hamming = LinearCode::new(7, 4, 3);
1081 assert!(hamming.satisfies_singleton_bound());
1082 assert!(hamming.satisfies_hamming_bound());
1083 assert!(hamming.is_perfect());
1084 }
1085}