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