1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 ApproximationVerifier, CacheObliviousMatrix, CertBFSExt, CertHashMapExt, CertifiedHashMap,
9 CertifiedUnionFind, CertifyingUnionFind, KMPMatcher, OnlineScheduler,
10 StreamingFrequencyEstimator, SuffixArray,
11};
12
13pub fn sorting_lower_bound_theorem() -> &'static str {
17 "Theorem (Comparison Sort Lower Bound): Any algorithm that sorts n elements \
18 using only comparisons must perform Omega(n log n) comparisons in the worst case. \
19 Proof sketch: The decision tree for any comparison sort has n! leaves (one per \
20 permutation). A binary tree of height h has at most 2^h leaves, so h >= log2(n!). \
21 By Stirling's approximation, log2(n!) = Theta(n log n). QED."
22}
23pub fn mod_pow(mut base: u64, mut exp: u64, modulus: u64) -> u64 {
24 let mut result = 1u64;
25 base %= modulus;
26 while exp > 0 {
27 if exp % 2 == 1 {
28 result = ((result as u128 * base as u128) % modulus as u128) as u64;
29 }
30 exp /= 2;
31 base = ((base as u128 * base as u128) % modulus as u128) as u64;
32 }
33 result
34}
35pub fn ackermann_function_terminates() -> bool {
40 true
41}
42pub fn app(f: Expr, x: Expr) -> Expr {
43 Expr::App(Box::new(f), Box::new(x))
44}
45pub fn app2(f: Expr, x: Expr, y: Expr) -> Expr {
46 app(app(f, x), y)
47}
48pub fn app3(f: Expr, x: Expr, y: Expr, z: Expr) -> Expr {
49 app(app2(f, x, y), z)
50}
51pub fn cst(name: &str) -> Expr {
52 Expr::Const(Name::str(name), vec![])
53}
54pub fn prop() -> Expr {
55 Expr::Sort(Level::zero())
56}
57pub fn type0() -> Expr {
58 Expr::Sort(Level::succ(Level::zero()))
59}
60pub fn pi(name: &str, domain: Expr, body: Expr) -> Expr {
61 Expr::Pi(
62 BinderInfo::Default,
63 Name::str(name),
64 Box::new(domain),
65 Box::new(body),
66 )
67}
68pub fn arrow(a: Expr, b: Expr) -> Expr {
69 pi("_", a, b)
70}
71pub fn bvar(i: u32) -> Expr {
72 Expr::BVar(i)
73}
74pub fn nat_ty() -> Expr {
75 cst("Nat")
76}
77pub fn real_ty() -> Expr {
78 cst("Real")
79}
80pub fn bool_ty() -> Expr {
81 cst("Bool")
82}
83pub fn list_ty(elem: Expr) -> Expr {
84 app(cst("List"), elem)
85}
86pub fn pair_ty(a: Expr, b: Expr) -> Expr {
87 app2(cst("Prod"), a, b)
88}
89pub fn option_ty(a: Expr) -> Expr {
90 app(cst("Option"), a)
91}
92pub fn potential_function_ty() -> Expr {
94 arrow(type0(), type0())
95}
96pub fn amortized_cost_ty() -> Expr {
99 arrow(
100 arrow(type0(), real_ty()),
101 arrow(cst("Operation"), real_ty()),
102 )
103}
104pub fn aggregate_cost_ty() -> Expr {
107 arrow(list_ty(cst("Operation")), arrow(real_ty(), prop()))
108}
109pub fn accounting_method_ty() -> Expr {
112 arrow(cst("Operation"), arrow(real_ty(), prop()))
113}
114pub fn amortized_correct_ty() -> Expr {
117 arrow(potential_function_ty(), arrow(cst("Algorithm"), prop()))
118}
119pub fn ideal_cache_model_ty() -> Expr {
122 arrow(nat_ty(), arrow(nat_ty(), type0()))
123}
124pub fn cache_transfer_ty() -> Expr {
127 arrow(cst("Algorithm"), arrow(nat_ty(), arrow(nat_ty(), prop())))
128}
129pub fn cache_oblivious_optimal_ty() -> Expr {
132 arrow(cst("Algorithm"), prop())
133}
134pub fn recursive_matrix_layout_ty() -> Expr {
137 arrow(nat_ty(), type0())
138}
139pub fn funnel_sort_ty() -> Expr {
142 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop()))
143}
144pub fn frequency_moment_ty() -> Expr {
147 arrow(nat_ty(), arrow(list_ty(nat_ty()), real_ty()))
148}
149pub fn heavy_hitter_ty() -> Expr {
152 arrow(
153 list_ty(nat_ty()),
154 arrow(real_ty(), arrow(list_ty(nat_ty()), prop())),
155 )
156}
157pub fn reservoir_sample_ty() -> Expr {
160 arrow(
161 list_ty(nat_ty()),
162 arrow(nat_ty(), arrow(list_ty(nat_ty()), prop())),
163 )
164}
165pub fn count_min_sketch_ty() -> Expr {
168 arrow(nat_ty(), arrow(nat_ty(), type0()))
169}
170pub fn count_min_correct_ty() -> Expr {
173 arrow(cst("CountMinSketch"), arrow(cst("Stream"), prop()))
174}
175pub fn ams_sketch_ty() -> Expr {
178 arrow(nat_ty(), type0())
179}
180pub fn io_model_ty() -> Expr {
183 arrow(nat_ty(), arrow(nat_ty(), type0()))
184}
185pub fn external_sort_ty() -> Expr {
188 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop()))
189}
190pub fn buffer_tree_ty() -> Expr {
193 type0()
194}
195pub fn external_bfs_ty() -> Expr {
198 arrow(
199 cst("Graph"),
200 arrow(cst("Vertex"), arrow(cst("Dist"), prop())),
201 )
202}
203pub fn pram_model_ty() -> Expr {
206 type0()
207}
208pub fn work_span_ty() -> Expr {
211 arrow(cst("Algorithm"), arrow(nat_ty(), arrow(nat_ty(), prop())))
212}
213pub fn brent_lemma_ty() -> Expr {
216 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop())))
217}
218pub fn list_ranking_ty() -> Expr {
221 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop()))
222}
223pub fn parallel_prefix_sum_ty() -> Expr {
226 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop()))
227}
228pub fn message_complexity_ty() -> Expr {
231 arrow(cst("Algorithm"), arrow(nat_ty(), prop()))
232}
233pub fn synchronizer_ty() -> Expr {
236 type0()
237}
238pub fn alpha_synchronizer_ty() -> Expr {
241 arrow(nat_ty(), arrow(nat_ty(), type0()))
242}
243pub fn consensus_protocol_ty() -> Expr {
246 arrow(nat_ty(), arrow(nat_ty(), type0()))
247}
248pub fn flp_impossibility_ty() -> Expr {
251 prop()
252}
253pub fn competitive_ratio_ty() -> Expr {
256 arrow(cst("Algorithm"), arrow(real_ty(), prop()))
257}
258pub fn ski_rental_ty() -> Expr {
261 arrow(nat_ty(), arrow(real_ty(), prop()))
262}
263pub fn k_server_ty() -> Expr {
266 arrow(nat_ty(), arrow(cst("Graph"), type0()))
267}
268pub fn k_server_conjecture_ty() -> Expr {
271 arrow(nat_ty(), prop())
272}
273pub fn online_bin_packing_ty() -> Expr {
276 arrow(list_ty(real_ty()), arrow(nat_ty(), prop()))
277}
278pub fn markov_chain_ty() -> Expr {
281 type0()
282}
283pub fn mixing_time_ty() -> Expr {
286 arrow(cst("MarkovChain"), arrow(real_ty(), prop()))
287}
288pub fn rapidly_mixing_ty() -> Expr {
291 arrow(cst("MarkovChain"), prop())
292}
293pub fn coupling_from_past_ty() -> Expr {
296 arrow(cst("MarkovChain"), arrow(cst("Algorithm"), prop()))
297}
298pub fn spectral_gap_ty() -> Expr {
301 arrow(cst("MarkovChain"), real_ty())
302}
303pub fn cell_probe_model_ty() -> Expr {
306 arrow(nat_ty(), arrow(nat_ty(), type0()))
307}
308pub fn query_complexity_ty() -> Expr {
311 arrow(
312 cst("DataStructure"),
313 arrow(cst("Operation"), arrow(nat_ty(), prop())),
314 )
315}
316pub fn pointer_machine_ty() -> Expr {
319 type0()
320}
321pub fn static_lower_bound_ty() -> Expr {
324 arrow(cst("Problem"), arrow(nat_ty(), prop()))
325}
326pub fn witness_ty() -> Expr {
329 arrow(cst("Input"), arrow(cst("Output"), type0()))
330}
331pub fn checker_correct_ty() -> Expr {
334 arrow(
335 cst("Witness"),
336 arrow(cst("Input"), arrow(cst("Output"), prop())),
337 )
338}
339pub fn certifying_algorithm_ty() -> Expr {
342 arrow(cst("Algorithm"), prop())
343}
344pub fn linearity_test_ty() -> Expr {
347 arrow(arrow(nat_ty(), nat_ty()), prop())
348}
349pub fn dijkstra_correct_ty() -> Expr {
352 arrow(
353 cst("Graph"),
354 arrow(cst("Vertex"), arrow(cst("Dist"), prop())),
355 )
356}
357pub fn bellman_ford_correct_ty() -> Expr {
360 arrow(
361 cst("Graph"),
362 arrow(cst("Vertex"), arrow(cst("Dist"), prop())),
363 )
364}
365pub fn floyd_warshall_correct_ty() -> Expr {
368 arrow(cst("Graph"), arrow(cst("Matrix"), prop()))
369}
370pub fn prim_correct_ty() -> Expr {
373 arrow(cst("Graph"), arrow(cst("SpanningTree"), prop()))
374}
375pub fn kruskal_correct_ty() -> Expr {
378 arrow(cst("Graph"), arrow(cst("SpanningTree"), prop()))
379}
380pub fn kmp_correct_ty() -> Expr {
383 arrow(
384 list_ty(nat_ty()),
385 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop())),
386 )
387}
388pub fn aho_corasick_correct_ty() -> Expr {
391 arrow(
392 list_ty(list_ty(nat_ty())),
393 arrow(cst("String"), arrow(list_ty(nat_ty()), prop())),
394 )
395}
396pub fn suffix_array_correct_ty() -> Expr {
399 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop()))
400}
401pub fn burrows_wheeler_correct_ty() -> Expr {
404 arrow(list_ty(nat_ty()), arrow(list_ty(nat_ty()), prop()))
405}
406pub fn convex_hull_correct_ty() -> Expr {
409 arrow(list_ty(cst("Point")), arrow(list_ty(cst("Point")), prop()))
410}
411pub fn voronoi_correct_ty() -> Expr {
414 arrow(list_ty(cst("Point")), arrow(cst("Diagram"), prop()))
415}
416pub fn delaunay_correct_ty() -> Expr {
419 arrow(list_ty(cst("Point")), arrow(cst("Triangulation"), prop()))
420}
421pub fn closest_pair_correct_ty() -> Expr {
424 arrow(
425 list_ty(cst("Point")),
426 arrow(pair_ty(cst("Point"), cst("Point")), prop()),
427 )
428}
429pub fn build_env(env: &mut Environment) -> Result<(), String> {
431 build_certified_algorithms_env(env)
432}
433pub fn build_certified_algorithms_env(env: &mut Environment) -> Result<(), String> {
435 for (name, ty) in &[
436 ("PotentialFunction", potential_function_ty()),
437 ("AmortizedCost", amortized_cost_ty()),
438 ("AggregateCost", aggregate_cost_ty()),
439 ("AccountingMethod", accounting_method_ty()),
440 ("AmortizedCorrect", amortized_correct_ty()),
441 ("IdealCacheModel", ideal_cache_model_ty()),
442 ("CacheTransfer", cache_transfer_ty()),
443 ("CacheObliviousOptimal", cache_oblivious_optimal_ty()),
444 ("RecursiveMatrixLayout", recursive_matrix_layout_ty()),
445 ("FunnelSort", funnel_sort_ty()),
446 ("FrequencyMoment", frequency_moment_ty()),
447 ("HeavyHitter", heavy_hitter_ty()),
448 ("ReservoirSample", reservoir_sample_ty()),
449 ("CountMinSketch", count_min_sketch_ty()),
450 ("CountMinCorrect", count_min_correct_ty()),
451 ("AMS_Sketch", ams_sketch_ty()),
452 ("IOModel", io_model_ty()),
453 ("ExternalSort", external_sort_ty()),
454 ("BufferTree", buffer_tree_ty()),
455 ("ExternalBFS", external_bfs_ty()),
456 ("PRAMModel", pram_model_ty()),
457 ("WorkSpan", work_span_ty()),
458 ("Brent_Lemma", brent_lemma_ty()),
459 ("ListRanking", list_ranking_ty()),
460 ("ParallelPrefixSum", parallel_prefix_sum_ty()),
461 ("MessageComplexity", message_complexity_ty()),
462 ("Synchronizer", synchronizer_ty()),
463 ("AlphaSynchronizer", alpha_synchronizer_ty()),
464 ("ConsensusProtocol", consensus_protocol_ty()),
465 ("FLPImpossibility", flp_impossibility_ty()),
466 ("CompetitiveRatio", competitive_ratio_ty()),
467 ("SkiRental", ski_rental_ty()),
468 ("KServer", k_server_ty()),
469 ("KServerConjecture", k_server_conjecture_ty()),
470 ("OnlineBinPacking", online_bin_packing_ty()),
471 ("MarkovChain", markov_chain_ty()),
472 ("MixingTime", mixing_time_ty()),
473 ("RapidlyMixing", rapidly_mixing_ty()),
474 ("CouplingFromPast", coupling_from_past_ty()),
475 ("SpectralGap", spectral_gap_ty()),
476 ("CellProbeModel", cell_probe_model_ty()),
477 ("QueryComplexity", query_complexity_ty()),
478 ("PointerMachine", pointer_machine_ty()),
479 ("StaticLowerBound", static_lower_bound_ty()),
480 ("Witness", witness_ty()),
481 ("CheckerCorrect", checker_correct_ty()),
482 ("CertifyingAlgorithm", certifying_algorithm_ty()),
483 ("LinearityTest", linearity_test_ty()),
484 ("DijkstraCorrect", dijkstra_correct_ty()),
485 ("BellmanFordCorrect", bellman_ford_correct_ty()),
486 ("FloydWarshallCorrect", floyd_warshall_correct_ty()),
487 ("PrimCorrect", prim_correct_ty()),
488 ("KruskalCorrect", kruskal_correct_ty()),
489 ("KMPCorrect", kmp_correct_ty()),
490 ("AhoCorasickCorrect", aho_corasick_correct_ty()),
491 ("SuffixArrayCorrect", suffix_array_correct_ty()),
492 ("BurrowsWheelerCorrect", burrows_wheeler_correct_ty()),
493 ("ConvexHullCorrect", convex_hull_correct_ty()),
494 ("VoronoiCorrect", voronoi_correct_ty()),
495 ("DelaunayCorrect", delaunay_correct_ty()),
496 ("ClosestPairCorrect", closest_pair_correct_ty()),
497 ] {
498 env.add(Declaration::Axiom {
499 name: Name::str(*name),
500 univ_params: vec![],
501 ty: ty.clone(),
502 })
503 .ok();
504 }
505 Ok(())
506}
507#[cfg(test)]
508mod tests {
509 use super::*;
510 #[test]
511 fn test_streaming_frequency_estimator_basic() {
512 let mut sketch = StreamingFrequencyEstimator::new(3, 64);
513 sketch.insert(42);
514 sketch.insert(42);
515 sketch.insert(42);
516 sketch.insert(7);
517 let est = sketch.estimate(42);
518 assert!(
519 sketch.estimate_lower_bound_holds(42, 3),
520 "estimate {} < true freq 3",
521 est
522 );
523 assert!(sketch.estimate_lower_bound_holds(7, 1));
524 assert_eq!(sketch.total, 4);
525 }
526 #[test]
527 fn test_cache_oblivious_matrix_multiply() {
528 let mut a = CacheObliviousMatrix::new(2);
529 let mut b = CacheObliviousMatrix::new(2);
530 a.set(0, 0, 1.0);
531 a.set(0, 1, 2.0);
532 a.set(1, 0, 3.0);
533 a.set(1, 1, 4.0);
534 b.set(0, 0, 5.0);
535 b.set(0, 1, 6.0);
536 b.set(1, 0, 7.0);
537 b.set(1, 1, 8.0);
538 let c = CacheObliviousMatrix::multiply(&a, &b);
539 assert!(
540 (c.get(0, 0) - 19.0).abs() < 1e-9,
541 "c[0,0] = {}",
542 c.get(0, 0)
543 );
544 assert!(
545 (c.get(0, 1) - 22.0).abs() < 1e-9,
546 "c[0,1] = {}",
547 c.get(0, 1)
548 );
549 assert!(
550 (c.get(1, 0) - 43.0).abs() < 1e-9,
551 "c[1,0] = {}",
552 c.get(1, 0)
553 );
554 assert!(
555 (c.get(1, 1) - 50.0).abs() < 1e-9,
556 "c[1,1] = {}",
557 c.get(1, 1)
558 );
559 }
560 #[test]
561 fn test_certifying_union_find() {
562 let mut uf = CertifyingUnionFind::new(5);
563 assert_eq!(uf.num_components, 5);
564 assert!(uf.union(0, 1));
565 assert!(uf.union(2, 3));
566 assert!(!uf.union(0, 1));
567 assert_eq!(uf.num_components, 3);
568 assert!(uf.verify_certificate(5));
569 assert_eq!(uf.spanning_forest_certificate().len(), 2);
570 }
571 #[test]
572 fn test_online_scheduler_competitive_ratio() {
573 let mut sched = OnlineScheduler::new(1.0);
574 sched.schedule(0.4);
575 sched.schedule(0.4);
576 sched.schedule(0.4);
577 sched.schedule(0.4);
578 let ratio = sched.competitive_ratio();
579 assert!(ratio <= 2.0 + 1e-9, "competitive ratio {} exceeds 2", ratio);
580 assert!(sched.num_bins() >= 1);
581 }
582 #[test]
583 fn test_approximation_verifier_minimization() {
584 let verifier = ApproximationVerifier::new(true);
585 assert!(verifier.verify_ratio(15.0, 10.0, 2.0));
586 assert!(!verifier.verify_ratio(25.0, 10.0, 2.0));
587 let ratio = verifier.actual_ratio(15.0, 10.0);
588 assert!((ratio - 1.5).abs() < 1e-9, "ratio = {}", ratio);
589 }
590 #[test]
591 fn test_approximation_verifier_maximization() {
592 let verifier = ApproximationVerifier::new(false);
593 assert!(verifier.verify_ratio(75.0, 100.0, 4.0 / 3.0));
594 }
595 #[test]
596 fn test_build_certified_algorithms_env() {
597 let mut env = Environment::new();
598 let result = build_certified_algorithms_env(&mut env);
599 assert!(result.is_ok(), "build should succeed");
600 assert!(env.get(&Name::str("PotentialFunction")).is_some());
601 assert!(env.get(&Name::str("CountMinSketch")).is_some());
602 assert!(env.get(&Name::str("MarkovChain")).is_some());
603 assert!(env.get(&Name::str("DijkstraCorrect")).is_some());
604 assert!(env.get(&Name::str("ConvexHullCorrect")).is_some());
605 assert!(env.get(&Name::str("FLPImpossibility")).is_some());
606 assert!(env.get(&Name::str("KServerConjecture")).is_some());
607 }
608}
609#[cfg(test)]
610mod tests_cert_alg_ext {
611 use super::*;
612 #[test]
613 fn test_certified_hashmap() {
614 let map: CertHashMapExt<String, i32> = CertHashMapExt::new(16);
615 assert!(!map.needs_resize());
616 assert!((map.load_factor() - 0.0).abs() < 1e-10);
617 let desc = map.amortized_complexity_description();
618 assert!(desc.contains("CertifiedHashMap"));
619 }
620 #[test]
621 fn test_certified_union_find() {
622 let mut uf = CertifiedUnionFind::new(5);
623 assert!(uf.correctness_invariant());
624 assert!(!uf.are_connected(0, 4));
625 uf.union(0, 1);
626 uf.union(1, 4);
627 assert!(uf.are_connected(0, 4));
628 assert!(!uf.are_connected(0, 3));
629 }
630 #[test]
631 fn test_kmp_matcher() {
632 let kmp = KMPMatcher::new("aba");
633 let matches = kmp.search("abababa");
634 assert_eq!(matches, vec![0, 2, 4]);
635 let cplx = kmp.complexity_description();
636 assert!(cplx.contains("KMP"));
637 }
638 #[test]
639 fn test_kmp_no_match() {
640 let kmp = KMPMatcher::new("xyz");
641 let matches = kmp.search("abcdefg");
642 assert!(matches.is_empty());
643 }
644 #[test]
645 fn test_suffix_array() {
646 let sa = SuffixArray::new("banana");
647 let found = sa.pattern_search("ana");
648 assert!(found.is_some());
649 let not_found = sa.pattern_search("xyz");
650 assert!(not_found.is_none());
651 }
652 #[test]
653 fn test_certified_bfs() {
654 let mut bfs = CertBFSExt::new(6);
655 bfs.add_edge(0, 1);
656 bfs.add_edge(0, 2);
657 bfs.add_edge(1, 3);
658 bfs.add_edge(2, 4);
659 bfs.add_edge(4, 5);
660 bfs.bfs_from(0);
661 assert_eq!(bfs.distances[5], Some(3));
662 let path = bfs.shortest_path_to(5);
663 assert_eq!(path, Some(vec![0, 2, 4, 5]));
664 let wit = bfs.correctness_witness(0, 5);
665 assert!(wit.contains("dist(0,5) = 3"));
666 }
667 #[test]
668 fn test_bfs_disconnected() {
669 let mut bfs = CertBFSExt::new(4);
670 bfs.add_edge(0, 1);
671 bfs.bfs_from(0);
672 assert!(bfs.distances[3].is_none());
673 let path = bfs.shortest_path_to(3);
674 assert!(path.is_none());
675 }
676}