1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6use std::collections::{HashSet, VecDeque};
7
8use super::types::{
9 DiGraph, ExpanderChecker, GraphonSampler, SzemerédiRegularityLemma, TreewidthHeuristic,
10 TuttePolynomialEval, UndirectedGraph,
11};
12
13#[allow(dead_code)]
14pub fn app(f: Expr, a: Expr) -> Expr {
15 Expr::App(Box::new(f), Box::new(a))
16}
17#[allow(dead_code)]
18pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
19 app(app(f, a), b)
20}
21#[allow(dead_code)]
22pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
23 app(app2(f, a, b), c)
24}
25pub fn cst(s: &str) -> Expr {
26 Expr::Const(Name::str(s), vec![])
27}
28pub fn prop() -> Expr {
29 Expr::Sort(Level::zero())
30}
31pub fn type0() -> Expr {
32 Expr::Sort(Level::succ(Level::zero()))
33}
34pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
35 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
36}
37pub fn arrow(a: Expr, b: Expr) -> Expr {
38 pi(BinderInfo::Default, "_", a, b)
39}
40pub fn impl_pi(name: &str, dom: Expr, body: Expr) -> Expr {
41 pi(BinderInfo::Implicit, name, dom, body)
42}
43pub fn nat_ty() -> Expr {
44 cst("Nat")
45}
46pub fn bool_ty() -> Expr {
47 cst("Bool")
48}
49pub fn simple_graph_ty() -> Expr {
51 pi(BinderInfo::Default, "V", type0(), type0())
52}
53pub fn simple_graph_adj_ty() -> Expr {
55 impl_pi(
56 "V",
57 type0(),
58 arrow(
59 app(cst("SimpleGraph"), bvar(0)),
60 arrow(bvar(0), arrow(bvar(1), prop())),
61 ),
62 )
63}
64pub fn bvar(n: u32) -> Expr {
65 Expr::BVar(n)
66}
67pub fn simple_graph_degree_ty() -> Expr {
69 impl_pi(
70 "V",
71 type0(),
72 arrow(app(cst("SimpleGraph"), bvar(0)), arrow(bvar(0), nat_ty())),
73 )
74}
75pub fn digraph_ty() -> Expr {
77 pi(BinderInfo::Default, "V", type0(), type0())
78}
79pub fn digraph_adj_ty() -> Expr {
81 impl_pi(
82 "V",
83 type0(),
84 arrow(
85 app(cst("Digraph"), bvar(0)),
86 arrow(bvar(0), arrow(bvar(1), bool_ty())),
87 ),
88 )
89}
90pub fn walk_ty() -> Expr {
92 impl_pi(
93 "V",
94 type0(),
95 arrow(
96 app(cst("SimpleGraph"), bvar(0)),
97 arrow(bvar(0), arrow(bvar(1), type0())),
98 ),
99 )
100}
101pub fn simple_graph_connected_ty() -> Expr {
103 impl_pi(
104 "V",
105 type0(),
106 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
107 )
108}
109pub fn is_tree_ty() -> Expr {
111 impl_pi(
112 "V",
113 type0(),
114 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
115 )
116}
117pub fn chromatic_number_ty() -> Expr {
119 impl_pi(
120 "V",
121 type0(),
122 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
123 )
124}
125pub fn is_eulerian_ty() -> Expr {
128 impl_pi(
129 "V",
130 type0(),
131 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
132 )
133}
134pub fn is_hamiltonian_ty() -> Expr {
137 impl_pi(
138 "V",
139 type0(),
140 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
141 )
142}
143pub fn is_bipartite_ty() -> Expr {
145 impl_pi(
146 "V",
147 type0(),
148 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
149 )
150}
151pub fn is_planar_ty() -> Expr {
153 impl_pi(
154 "V",
155 type0(),
156 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
157 )
158}
159pub fn matching_ty() -> Expr {
161 impl_pi(
162 "V",
163 type0(),
164 arrow(app(cst("SimpleGraph"), bvar(0)), type0()),
165 )
166}
167pub fn is_perfect_matching_ty() -> Expr {
169 impl_pi(
170 "V",
171 type0(),
172 arrow(
173 app(cst("SimpleGraph"), bvar(0)),
174 arrow(app2(cst("Matching"), bvar(0), bvar(0)), prop()),
175 ),
176 )
177}
178pub fn four_color_theorem_ty() -> Expr {
180 impl_pi(
181 "V",
182 type0(),
183 pi(
184 BinderInfo::Default,
185 "G",
186 app(cst("SimpleGraph"), bvar(0)),
187 arrow(
188 app(cst("IsPlanar"), bvar(0)),
189 app2(
190 cst("Nat.le"),
191 app(cst("chromatic_number"), bvar(1)),
192 Expr::Lit(oxilean_kernel::Literal::Nat(4)),
193 ),
194 ),
195 ),
196 )
197}
198pub fn euler_formula_ty() -> Expr {
200 pi(
201 BinderInfo::Default,
202 "v",
203 nat_ty(),
204 pi(
205 BinderInfo::Default,
206 "e",
207 nat_ty(),
208 pi(
209 BinderInfo::Default,
210 "f",
211 nat_ty(),
212 arrow(
213 app3(cst("IsConnectedPlanar"), bvar(2), bvar(1), bvar(0)),
214 app2(
215 app(cst("Eq"), nat_ty()),
216 app2(
217 cst("Nat.add"),
218 app2(cst("Nat.sub"), bvar(2), bvar(1)),
219 bvar(0),
220 ),
221 Expr::Lit(oxilean_kernel::Literal::Nat(2)),
222 ),
223 ),
224 ),
225 ),
226 )
227}
228pub fn eulerian_circuit_thm_ty() -> Expr {
230 impl_pi(
231 "V",
232 type0(),
233 pi(
234 BinderInfo::Default,
235 "G",
236 app(cst("SimpleGraph"), bvar(0)),
237 app2(
238 cst("Iff"),
239 app(cst("IsEulerian"), bvar(0)),
240 app2(
241 cst("And"),
242 app(cst("SimpleGraph.Connected"), bvar(1)),
243 app(cst("AllDegreesEven"), bvar(1)),
244 ),
245 ),
246 ),
247 )
248}
249pub fn halls_theorem_ty() -> Expr {
252 impl_pi(
253 "V",
254 type0(),
255 pi(
256 BinderInfo::Default,
257 "G",
258 app(cst("SimpleGraph"), bvar(0)),
259 arrow(
260 app(cst("IsBipartite"), bvar(0)),
261 app2(
262 cst("Iff"),
263 app(cst("HasPerfectMatching"), bvar(1)),
264 app(cst("HallCondition"), bvar(1)),
265 ),
266 ),
267 ),
268 )
269}
270pub fn kuratowski_theorem_ty() -> Expr {
272 impl_pi(
273 "V",
274 type0(),
275 pi(
276 BinderInfo::Default,
277 "G",
278 app(cst("SimpleGraph"), bvar(0)),
279 app2(
280 cst("Iff"),
281 app(cst("IsPlanar"), bvar(0)),
282 app(cst("NoK5OrK33Subdivision"), bvar(0)),
283 ),
284 ),
285 )
286}
287pub fn real_ty() -> Expr {
288 cst("Real")
289}
290#[allow(dead_code)]
293pub fn graph_minor_ty() -> Expr {
294 impl_pi(
295 "V",
296 type0(),
297 impl_pi(
298 "W",
299 type0(),
300 arrow(
301 app(cst("SimpleGraph"), bvar(1)),
302 arrow(app(cst("SimpleGraph"), bvar(1)), prop()),
303 ),
304 ),
305 )
306}
307#[allow(dead_code)]
310pub fn robertson_seymour_wqo_ty() -> Expr {
311 impl_pi(
312 "V",
313 type0(),
314 pi(
315 BinderInfo::Default,
316 "seq",
317 arrow(nat_ty(), app(cst("SimpleGraph"), bvar(0))),
318 app(cst("WellQuasiOrdered"), app(cst("GraphMinor"), bvar(0))),
319 ),
320 )
321}
322#[allow(dead_code)]
325pub fn excluded_minor_characterization_ty() -> Expr {
326 impl_pi(
327 "V",
328 type0(),
329 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
330 )
331}
332#[allow(dead_code)]
335pub fn vertex_expansion_ty() -> Expr {
336 impl_pi(
337 "V",
338 type0(),
339 arrow(app(cst("SimpleGraph"), bvar(0)), arrow(real_ty(), prop())),
340 )
341}
342#[allow(dead_code)]
345pub fn edge_expansion_ty() -> Expr {
346 impl_pi(
347 "V",
348 type0(),
349 arrow(app(cst("SimpleGraph"), bvar(0)), arrow(real_ty(), prop())),
350 )
351}
352#[allow(dead_code)]
355pub fn cheeger_constant_ty() -> Expr {
356 impl_pi(
357 "V",
358 type0(),
359 arrow(app(cst("SimpleGraph"), bvar(0)), real_ty()),
360 )
361}
362#[allow(dead_code)]
366pub fn cheeger_inequality_ty() -> Expr {
367 impl_pi(
368 "V",
369 type0(),
370 pi(
371 BinderInfo::Default,
372 "G",
373 app(cst("SimpleGraph"), bvar(0)),
374 app2(
375 cst("CheegerBounds"),
376 app(cst("SpectralGap"), bvar(0)),
377 app(cst("CheegerConstant"), bvar(0)),
378 ),
379 ),
380 )
381}
382#[allow(dead_code)]
385pub fn spectral_gap_ty() -> Expr {
386 impl_pi(
387 "V",
388 type0(),
389 arrow(app(cst("SimpleGraph"), bvar(0)), real_ty()),
390 )
391}
392#[allow(dead_code)]
395pub fn erdos_renyi_graph_ty() -> Expr {
396 arrow(
397 nat_ty(),
398 arrow(real_ty(), app(cst("SimpleGraph"), nat_ty())),
399 )
400}
401#[allow(dead_code)]
404pub fn connectivity_threshold_ty() -> Expr {
405 arrow(nat_ty(), real_ty())
406}
407#[allow(dead_code)]
410pub fn phase_transition_ty() -> Expr {
411 pi(
412 BinderInfo::Default,
413 "n",
414 nat_ty(),
415 pi(
416 BinderInfo::Default,
417 "p",
418 real_ty(),
419 arrow(
420 app2(cst("Real.gt"), bvar(0), app(cst("Real.inv"), bvar(1))),
421 app(
422 cst("GiantComponentExists"),
423 app2(cst("ErdosRenyiGraph"), bvar(1), bvar(0)),
424 ),
425 ),
426 ),
427 )
428}
429#[allow(dead_code)]
432pub fn graphon_ty() -> Expr {
433 type0()
434}
435#[allow(dead_code)]
438pub fn graphon_cut_distance_ty() -> Expr {
439 arrow(cst("Graphon"), arrow(cst("Graphon"), real_ty()))
440}
441#[allow(dead_code)]
445pub fn szemeredi_regularity_ty() -> Expr {
446 impl_pi(
447 "V",
448 type0(),
449 pi(
450 BinderInfo::Default,
451 "G",
452 app(cst("SimpleGraph"), bvar(0)),
453 pi(
454 BinderInfo::Default,
455 "eps",
456 real_ty(),
457 app2(
458 cst("Exists"),
459 cst("Partition"),
460 app2(cst("IsEpsRegular"), bvar(1), bvar(0)),
461 ),
462 ),
463 ),
464 )
465}
466#[allow(dead_code)]
469pub fn is_perfect_graph_ty() -> Expr {
470 impl_pi(
471 "V",
472 type0(),
473 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
474 )
475}
476#[allow(dead_code)]
480pub fn strong_perfect_graph_thm_ty() -> Expr {
481 impl_pi(
482 "V",
483 type0(),
484 pi(
485 BinderInfo::Default,
486 "G",
487 app(cst("SimpleGraph"), bvar(0)),
488 app2(
489 cst("Iff"),
490 app(cst("IsPerfectGraph"), bvar(0)),
491 app2(
492 cst("And"),
493 app(cst("NoOddHole"), bvar(0)),
494 app(cst("NoOddAntihole"), bvar(0)),
495 ),
496 ),
497 ),
498 )
499}
500#[allow(dead_code)]
503pub fn clique_cover_number_ty() -> Expr {
504 impl_pi(
505 "V",
506 type0(),
507 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
508 )
509}
510#[allow(dead_code)]
513pub fn vertex_connectivity_ty() -> Expr {
514 impl_pi(
515 "V",
516 type0(),
517 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
518 )
519}
520#[allow(dead_code)]
523pub fn edge_connectivity_ty() -> Expr {
524 impl_pi(
525 "V",
526 type0(),
527 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
528 )
529}
530#[allow(dead_code)]
534pub fn mengers_theorem_ty() -> Expr {
535 impl_pi(
536 "V",
537 type0(),
538 pi(
539 BinderInfo::Default,
540 "G",
541 app(cst("SimpleGraph"), bvar(0)),
542 pi(
543 BinderInfo::Default,
544 "s",
545 bvar(1),
546 pi(
547 BinderInfo::Default,
548 "t",
549 bvar(2),
550 app2(
551 app(cst("Eq"), nat_ty()),
552 app3(cst("MaxDisjointPaths"), bvar(2), bvar(1), bvar(0)),
553 app3(cst("MinVertexCut"), bvar(2), bvar(1), bvar(0)),
554 ),
555 ),
556 ),
557 ),
558 )
559}
560#[allow(dead_code)]
564pub fn max_flow_min_cut_ty() -> Expr {
565 pi(
566 BinderInfo::Default,
567 "n",
568 nat_ty(),
569 pi(
570 BinderInfo::Default,
571 "s",
572 nat_ty(),
573 pi(
574 BinderInfo::Default,
575 "t",
576 nat_ty(),
577 pi(
578 BinderInfo::Default,
579 "cap",
580 arrow(nat_ty(), arrow(nat_ty(), real_ty())),
581 app2(
582 app(cst("Eq"), real_ty()),
583 app3(app(cst("MaxFlowVal"), bvar(3)), bvar(2), bvar(1), bvar(0)),
584 app3(
585 app(cst("MinCutCapacity"), bvar(3)),
586 bvar(2),
587 bvar(1),
588 bvar(0),
589 ),
590 ),
591 ),
592 ),
593 ),
594 )
595}
596#[allow(dead_code)]
599pub fn genus_ty() -> Expr {
600 impl_pi(
601 "V",
602 type0(),
603 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
604 )
605}
606#[allow(dead_code)]
609pub fn crossing_number_ty() -> Expr {
610 impl_pi(
611 "V",
612 type0(),
613 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
614 )
615}
616#[allow(dead_code)]
620pub fn wagner_theorem_ty() -> Expr {
621 impl_pi(
622 "V",
623 type0(),
624 pi(
625 BinderInfo::Default,
626 "G",
627 app(cst("SimpleGraph"), bvar(0)),
628 app2(
629 cst("Iff"),
630 app(cst("IsPlanar"), bvar(0)),
631 app2(
632 cst("And"),
633 app(cst("NoK5Minor"), bvar(0)),
634 app(cst("NoK33Minor"), bvar(0)),
635 ),
636 ),
637 ),
638 )
639}
640#[allow(dead_code)]
643pub fn hypergraph_ty() -> Expr {
644 pi(BinderInfo::Default, "V", type0(), type0())
645}
646#[allow(dead_code)]
649pub fn hypergraph_coloring_ty() -> Expr {
650 impl_pi(
651 "V",
652 type0(),
653 arrow(app(cst("Hypergraph"), bvar(0)), arrow(nat_ty(), prop())),
654 )
655}
656#[allow(dead_code)]
660pub fn sunflower_lemma_ty() -> Expr {
661 pi(
662 BinderInfo::Default,
663 "p",
664 nat_ty(),
665 pi(
666 BinderInfo::Default,
667 "k",
668 nat_ty(),
669 pi(
670 BinderInfo::Default,
671 "F",
672 app(cst("Finset"), app(cst("Finset"), nat_ty())),
673 arrow(
674 app2(
675 cst("SunflowerSizeCondition"),
676 bvar(2),
677 app(cst("Finset.card"), bvar(0)),
678 ),
679 app2(cst("HasSunflower"), bvar(0), bvar(2)),
680 ),
681 ),
682 ),
683 )
684}
685#[allow(dead_code)]
688pub fn hypergraph_turan_ty() -> Expr {
689 pi(
690 BinderInfo::Default,
691 "r",
692 nat_ty(),
693 pi(
694 BinderInfo::Default,
695 "k",
696 nat_ty(),
697 pi(
698 BinderInfo::Default,
699 "n",
700 nat_ty(),
701 app3(cst("TuranDensity"), bvar(2), bvar(1), bvar(0)),
702 ),
703 ),
704 )
705}
706#[allow(dead_code)]
709pub fn graph_homomorphism_ty() -> Expr {
710 impl_pi(
711 "V",
712 type0(),
713 impl_pi(
714 "W",
715 type0(),
716 arrow(
717 app(cst("SimpleGraph"), bvar(1)),
718 arrow(app(cst("SimpleGraph"), bvar(1)), type0()),
719 ),
720 ),
721 )
722}
723#[allow(dead_code)]
726pub fn lovasz_theta_ty() -> Expr {
727 impl_pi(
728 "V",
729 type0(),
730 arrow(app(cst("SimpleGraph"), bvar(0)), real_ty()),
731 )
732}
733#[allow(dead_code)]
736pub fn fractional_chromatic_number_ty() -> Expr {
737 impl_pi(
738 "V",
739 type0(),
740 arrow(app(cst("SimpleGraph"), bvar(0)), real_ty()),
741 )
742}
743#[allow(dead_code)]
747pub fn homomorphism_duality_ty() -> Expr {
748 impl_pi(
749 "V",
750 type0(),
751 impl_pi(
752 "W",
753 type0(),
754 pi(
755 BinderInfo::Default,
756 "H",
757 app(cst("SimpleGraph"), bvar(1)),
758 pi(
759 BinderInfo::Default,
760 "G",
761 app(cst("SimpleGraph"), bvar(1)),
762 app2(
763 cst("Iff"),
764 app(cst("Not"), app2(cst("GraphHom"), bvar(1), bvar(0))),
765 app2(cst("HasDualObstruction"), cst("Digraph"), bvar(0)),
766 ),
767 ),
768 ),
769 ),
770 )
771}
772#[allow(dead_code)]
775pub fn tree_decomposition_ty() -> Expr {
776 impl_pi(
777 "V",
778 type0(),
779 arrow(app(cst("SimpleGraph"), bvar(0)), type0()),
780 )
781}
782#[allow(dead_code)]
785pub fn treewidth_ty() -> Expr {
786 impl_pi(
787 "V",
788 type0(),
789 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
790 )
791}
792#[allow(dead_code)]
795pub fn pathwidth_ty() -> Expr {
796 impl_pi(
797 "V",
798 type0(),
799 arrow(app(cst("SimpleGraph"), bvar(0)), nat_ty()),
800 )
801}
802#[allow(dead_code)]
806pub fn treewidth_duality_ty() -> Expr {
807 impl_pi(
808 "V",
809 type0(),
810 pi(
811 BinderInfo::Default,
812 "G",
813 app(cst("SimpleGraph"), bvar(0)),
814 pi(
815 BinderInfo::Default,
816 "k",
817 nat_ty(),
818 app2(
819 cst("Iff"),
820 app2(cst("Nat.le"), app(cst("Treewidth"), bvar(1)), bvar(0)),
821 app(
822 cst("Not"),
823 app2(cst("HasBranchDecompositionObstruction"), bvar(1), bvar(0)),
824 ),
825 ),
826 ),
827 ),
828 )
829}
830#[allow(dead_code)]
833pub fn adjacency_matrix_ty() -> Expr {
834 impl_pi(
835 "V",
836 type0(),
837 arrow(
838 app(cst("SimpleGraph"), bvar(0)),
839 app3(cst("Matrix"), bvar(0), bvar(0), real_ty()),
840 ),
841 )
842}
843#[allow(dead_code)]
846pub fn graph_laplacian_ty() -> Expr {
847 impl_pi(
848 "V",
849 type0(),
850 arrow(
851 app(cst("SimpleGraph"), bvar(0)),
852 app3(cst("Matrix"), bvar(0), bvar(0), real_ty()),
853 ),
854 )
855}
856#[allow(dead_code)]
860pub fn eigenvalue_interlacing_ty() -> Expr {
861 impl_pi(
862 "V",
863 type0(),
864 pi(
865 BinderInfo::Default,
866 "G",
867 app(cst("SimpleGraph"), bvar(0)),
868 pi(
869 BinderInfo::Default,
870 "H",
871 app(cst("SimpleGraph"), bvar(1)),
872 arrow(
873 app2(cst("IsInducedSubgraph"), bvar(0), bvar(1)),
874 app2(
875 cst("InterlacesEigenvalues"),
876 app(cst("GraphLaplacian"), bvar(1)),
877 app(cst("GraphLaplacian"), bvar(0)),
878 ),
879 ),
880 ),
881 ),
882 )
883}
884#[allow(dead_code)]
887pub fn ihara_zeta_function_ty() -> Expr {
888 impl_pi(
889 "V",
890 type0(),
891 arrow(
892 app(cst("SimpleGraph"), bvar(0)),
893 arrow(cst("Complex"), cst("Complex")),
894 ),
895 )
896}
897#[allow(dead_code)]
900pub fn chromatic_polynomial_ty() -> Expr {
901 impl_pi(
902 "V",
903 type0(),
904 arrow(
905 app(cst("SimpleGraph"), bvar(0)),
906 arrow(nat_ty(), cst("Int")),
907 ),
908 )
909}
910#[allow(dead_code)]
913pub fn tutte_polynomial_ty() -> Expr {
914 impl_pi(
915 "V",
916 type0(),
917 arrow(
918 app(cst("SimpleGraph"), bvar(0)),
919 arrow(real_ty(), arrow(real_ty(), real_ty())),
920 ),
921 )
922}
923#[allow(dead_code)]
926pub fn matching_polynomial_ty() -> Expr {
927 impl_pi(
928 "V",
929 type0(),
930 arrow(
931 app(cst("SimpleGraph"), bvar(0)),
932 arrow(real_ty(), real_ty()),
933 ),
934 )
935}
936#[allow(dead_code)]
940pub fn deletion_contraction_tutte_ty() -> Expr {
941 impl_pi(
942 "V",
943 type0(),
944 pi(
945 BinderInfo::Default,
946 "G",
947 app(cst("SimpleGraph"), bvar(0)),
948 pi(
949 BinderInfo::Default,
950 "e",
951 app(cst("Edge"), bvar(1)),
952 app2(
953 app(cst("Eq"), arrow(real_ty(), arrow(real_ty(), real_ty()))),
954 app(cst("TuttePolynomial"), bvar(1)),
955 app2(
956 cst("TutteSum"),
957 app(
958 cst("TuttePolynomial"),
959 app2(cst("Delete"), bvar(1), bvar(0)),
960 ),
961 app(
962 cst("TuttePolynomial"),
963 app2(cst("Contract"), bvar(1), bvar(0)),
964 ),
965 ),
966 ),
967 ),
968 ),
969 )
970}
971#[allow(dead_code)]
974pub fn cayley_graph_ty() -> Expr {
975 pi(
976 BinderInfo::Default,
977 "G",
978 cst("Group"),
979 pi(
980 BinderInfo::Default,
981 "S",
982 app(cst("Finset"), bvar(0)),
983 app(cst("SimpleGraph"), bvar(1)),
984 ),
985 )
986}
987#[allow(dead_code)]
991pub fn strongly_regular_graph_ty() -> Expr {
992 impl_pi(
993 "V",
994 type0(),
995 pi(
996 BinderInfo::Default,
997 "G",
998 app(cst("SimpleGraph"), bvar(0)),
999 pi(
1000 BinderInfo::Default,
1001 "k",
1002 nat_ty(),
1003 pi(
1004 BinderInfo::Default,
1005 "lam",
1006 nat_ty(),
1007 pi(BinderInfo::Default, "mu", nat_ty(), prop()),
1008 ),
1009 ),
1010 ),
1011 )
1012}
1013#[allow(dead_code)]
1016pub fn dynamic_graph_ty() -> Expr {
1017 pi(BinderInfo::Default, "V", type0(), type0())
1018}
1019#[allow(dead_code)]
1022pub fn fully_dynamic_connectivity_ty() -> Expr {
1023 impl_pi(
1024 "V",
1025 type0(),
1026 arrow(app(cst("DynamicGraph"), bvar(0)), prop()),
1027 )
1028}
1029#[allow(dead_code)]
1032pub fn incremental_connectivity_ty() -> Expr {
1033 impl_pi(
1034 "V",
1035 type0(),
1036 arrow(app(cst("DynamicGraph"), bvar(0)), prop()),
1037 )
1038}
1039#[allow(dead_code)]
1042pub fn semi_streaming_sketch_ty() -> Expr {
1043 impl_pi(
1044 "V",
1045 type0(),
1046 arrow(app(cst("SimpleGraph"), bvar(0)), type0()),
1047 )
1048}
1049#[allow(dead_code)]
1052pub fn sketched_connectivity_ty() -> Expr {
1053 impl_pi(
1054 "V",
1055 type0(),
1056 arrow(app(cst("SemiStreamingSketch"), bvar(0)), prop()),
1057 )
1058}
1059#[allow(dead_code)]
1061pub fn build_graph_theory_env(env: &mut Environment) -> Result<(), String> {
1062 let _ = env.add(Declaration::Axiom {
1063 name: Name::str("SimpleGraph"),
1064 univ_params: vec![],
1065 ty: simple_graph_ty(),
1066 });
1067 let _ = env.add(Declaration::Axiom {
1068 name: Name::str("SimpleGraph.adj"),
1069 univ_params: vec![],
1070 ty: simple_graph_adj_ty(),
1071 });
1072 let _ = env.add(Declaration::Axiom {
1073 name: Name::str("SimpleGraph.degree"),
1074 univ_params: vec![],
1075 ty: simple_graph_degree_ty(),
1076 });
1077 let _ = env.add(Declaration::Axiom {
1078 name: Name::str("Digraph"),
1079 univ_params: vec![],
1080 ty: digraph_ty(),
1081 });
1082 let _ = env.add(Declaration::Axiom {
1083 name: Name::str("Digraph.adj"),
1084 univ_params: vec![],
1085 ty: digraph_adj_ty(),
1086 });
1087 let _ = env.add(Declaration::Axiom {
1088 name: Name::str("Walk"),
1089 univ_params: vec![],
1090 ty: walk_ty(),
1091 });
1092 let _ = env.add(Declaration::Axiom {
1093 name: Name::str("SimpleGraph.Connected"),
1094 univ_params: vec![],
1095 ty: simple_graph_connected_ty(),
1096 });
1097 let _ = env.add(Declaration::Axiom {
1098 name: Name::str("IsTree"),
1099 univ_params: vec![],
1100 ty: is_tree_ty(),
1101 });
1102 let _ = env.add(Declaration::Axiom {
1103 name: Name::str("chromatic_number"),
1104 univ_params: vec![],
1105 ty: chromatic_number_ty(),
1106 });
1107 let _ = env.add(Declaration::Axiom {
1108 name: Name::str("IsEulerian"),
1109 univ_params: vec![],
1110 ty: is_eulerian_ty(),
1111 });
1112 let _ = env.add(Declaration::Axiom {
1113 name: Name::str("IsHamiltonian"),
1114 univ_params: vec![],
1115 ty: is_hamiltonian_ty(),
1116 });
1117 let _ = env.add(Declaration::Axiom {
1118 name: Name::str("IsBipartite"),
1119 univ_params: vec![],
1120 ty: is_bipartite_ty(),
1121 });
1122 let _ = env.add(Declaration::Axiom {
1123 name: Name::str("IsPlanar"),
1124 univ_params: vec![],
1125 ty: is_planar_ty(),
1126 });
1127 let _ = env.add(Declaration::Axiom {
1128 name: Name::str("four_color_theorem"),
1129 univ_params: vec![],
1130 ty: four_color_theorem_ty(),
1131 });
1132 let _ = env.add(Declaration::Axiom {
1133 name: Name::str("eulerian_circuit_theorem"),
1134 univ_params: vec![],
1135 ty: eulerian_circuit_thm_ty(),
1136 });
1137 let _ = env.add(Declaration::Axiom {
1138 name: Name::str("halls_theorem"),
1139 univ_params: vec![],
1140 ty: halls_theorem_ty(),
1141 });
1142 let _ = env.add(Declaration::Axiom {
1143 name: Name::str("kuratowski_theorem"),
1144 univ_params: vec![],
1145 ty: kuratowski_theorem_ty(),
1146 });
1147 let _ = env.add(Declaration::Axiom {
1148 name: Name::str("GraphMinor"),
1149 univ_params: vec![],
1150 ty: graph_minor_ty(),
1151 });
1152 let _ = env.add(Declaration::Axiom {
1153 name: Name::str("robertson_seymour_wqo"),
1154 univ_params: vec![],
1155 ty: robertson_seymour_wqo_ty(),
1156 });
1157 let _ = env.add(Declaration::Axiom {
1158 name: Name::str("VertexExpansion"),
1159 univ_params: vec![],
1160 ty: vertex_expansion_ty(),
1161 });
1162 let _ = env.add(Declaration::Axiom {
1163 name: Name::str("EdgeExpansion"),
1164 univ_params: vec![],
1165 ty: edge_expansion_ty(),
1166 });
1167 let _ = env.add(Declaration::Axiom {
1168 name: Name::str("CheegerConstant"),
1169 univ_params: vec![],
1170 ty: cheeger_constant_ty(),
1171 });
1172 let _ = env.add(Declaration::Axiom {
1173 name: Name::str("SpectralGap"),
1174 univ_params: vec![],
1175 ty: spectral_gap_ty(),
1176 });
1177 let _ = env.add(Declaration::Axiom {
1178 name: Name::str("Graphon"),
1179 univ_params: vec![],
1180 ty: graphon_ty(),
1181 });
1182 let _ = env.add(Declaration::Axiom {
1183 name: Name::str("GraphonCutDistance"),
1184 univ_params: vec![],
1185 ty: graphon_cut_distance_ty(),
1186 });
1187 let _ = env.add(Declaration::Axiom {
1188 name: Name::str("IsPerfectGraph"),
1189 univ_params: vec![],
1190 ty: is_perfect_graph_ty(),
1191 });
1192 let _ = env.add(Declaration::Axiom {
1193 name: Name::str("strong_perfect_graph_theorem"),
1194 univ_params: vec![],
1195 ty: strong_perfect_graph_thm_ty(),
1196 });
1197 let _ = env.add(Declaration::Axiom {
1198 name: Name::str("VertexConnectivity"),
1199 univ_params: vec![],
1200 ty: vertex_connectivity_ty(),
1201 });
1202 let _ = env.add(Declaration::Axiom {
1203 name: Name::str("EdgeConnectivity"),
1204 univ_params: vec![],
1205 ty: edge_connectivity_ty(),
1206 });
1207 let _ = env.add(Declaration::Axiom {
1208 name: Name::str("Genus"),
1209 univ_params: vec![],
1210 ty: genus_ty(),
1211 });
1212 let _ = env.add(Declaration::Axiom {
1213 name: Name::str("CrossingNumber"),
1214 univ_params: vec![],
1215 ty: crossing_number_ty(),
1216 });
1217 let _ = env.add(Declaration::Axiom {
1218 name: Name::str("Hypergraph"),
1219 univ_params: vec![],
1220 ty: hypergraph_ty(),
1221 });
1222 let _ = env.add(Declaration::Axiom {
1223 name: Name::str("HypergraphColoring"),
1224 univ_params: vec![],
1225 ty: hypergraph_coloring_ty(),
1226 });
1227 let _ = env.add(Declaration::Axiom {
1228 name: Name::str("GraphHomomorphism"),
1229 univ_params: vec![],
1230 ty: graph_homomorphism_ty(),
1231 });
1232 let _ = env.add(Declaration::Axiom {
1233 name: Name::str("LovaszTheta"),
1234 univ_params: vec![],
1235 ty: lovasz_theta_ty(),
1236 });
1237 let _ = env.add(Declaration::Axiom {
1238 name: Name::str("FractionalChromaticNumber"),
1239 univ_params: vec![],
1240 ty: fractional_chromatic_number_ty(),
1241 });
1242 let _ = env.add(Declaration::Axiom {
1243 name: Name::str("TreeDecomposition"),
1244 univ_params: vec![],
1245 ty: tree_decomposition_ty(),
1246 });
1247 let _ = env.add(Declaration::Axiom {
1248 name: Name::str("Treewidth"),
1249 univ_params: vec![],
1250 ty: treewidth_ty(),
1251 });
1252 let _ = env.add(Declaration::Axiom {
1253 name: Name::str("Pathwidth"),
1254 univ_params: vec![],
1255 ty: pathwidth_ty(),
1256 });
1257 let _ = env.add(Declaration::Axiom {
1258 name: Name::str("AdjacencyMatrix"),
1259 univ_params: vec![],
1260 ty: adjacency_matrix_ty(),
1261 });
1262 let _ = env.add(Declaration::Axiom {
1263 name: Name::str("GraphLaplacian"),
1264 univ_params: vec![],
1265 ty: graph_laplacian_ty(),
1266 });
1267 let _ = env.add(Declaration::Axiom {
1268 name: Name::str("IharaZetaFunction"),
1269 univ_params: vec![],
1270 ty: ihara_zeta_function_ty(),
1271 });
1272 let _ = env.add(Declaration::Axiom {
1273 name: Name::str("ChromaticPolynomial"),
1274 univ_params: vec![],
1275 ty: chromatic_polynomial_ty(),
1276 });
1277 let _ = env.add(Declaration::Axiom {
1278 name: Name::str("TuttePolynomial"),
1279 univ_params: vec![],
1280 ty: tutte_polynomial_ty(),
1281 });
1282 let _ = env.add(Declaration::Axiom {
1283 name: Name::str("MatchingPolynomial"),
1284 univ_params: vec![],
1285 ty: matching_polynomial_ty(),
1286 });
1287 let _ = env.add(Declaration::Axiom {
1288 name: Name::str("CayleyGraph"),
1289 univ_params: vec![],
1290 ty: cayley_graph_ty(),
1291 });
1292 let _ = env.add(Declaration::Axiom {
1293 name: Name::str("StronglyRegularGraph"),
1294 univ_params: vec![],
1295 ty: strongly_regular_graph_ty(),
1296 });
1297 let _ = env.add(Declaration::Axiom {
1298 name: Name::str("DynamicGraph"),
1299 univ_params: vec![],
1300 ty: dynamic_graph_ty(),
1301 });
1302 let _ = env.add(Declaration::Axiom {
1303 name: Name::str("FullyDynamicConnectivity"),
1304 univ_params: vec![],
1305 ty: fully_dynamic_connectivity_ty(),
1306 });
1307 let _ = env.add(Declaration::Axiom {
1308 name: Name::str("SemiStreamingSketch"),
1309 univ_params: vec![],
1310 ty: semi_streaming_sketch_ty(),
1311 });
1312 Ok(())
1313}
1314pub fn kruskal_mst(n: usize, mut edges: Vec<(usize, usize, i64)>) -> Vec<(usize, usize, i64)> {
1316 edges.sort_by_key(|&(_, _, w)| w);
1317 let mut parent: Vec<usize> = (0..n).collect();
1318 let mut rank = vec![0usize; n];
1319 fn find(parent: &mut Vec<usize>, x: usize) -> usize {
1320 if parent[x] != x {
1321 parent[x] = find(parent, parent[x]);
1322 }
1323 parent[x]
1324 }
1325 fn union(parent: &mut Vec<usize>, rank: &mut Vec<usize>, x: usize, y: usize) -> bool {
1326 let rx = find(parent, x);
1327 let ry = find(parent, y);
1328 if rx == ry {
1329 return false;
1330 }
1331 if rank[rx] < rank[ry] {
1332 parent[rx] = ry;
1333 } else if rank[rx] > rank[ry] {
1334 parent[ry] = rx;
1335 } else {
1336 parent[ry] = rx;
1337 rank[rx] += 1;
1338 }
1339 true
1340 }
1341 let mut mst = Vec::new();
1342 for (u, v, w) in edges {
1343 if union(&mut parent, &mut rank, u, v) {
1344 mst.push((u, v, w));
1345 if mst.len() == n - 1 {
1346 break;
1347 }
1348 }
1349 }
1350 mst
1351}
1352pub fn max_flow(n: usize, source: usize, sink: usize, capacity: &[Vec<i64>]) -> i64 {
1354 let mut flow_matrix = vec![vec![0i64; n]; n];
1355 let mut total_flow = 0i64;
1356 loop {
1357 let mut parent = vec![usize::MAX; n];
1358 parent[source] = source;
1359 let mut queue = VecDeque::new();
1360 queue.push_back(source);
1361 while let Some(u) = queue.pop_front() {
1362 if u == sink {
1363 break;
1364 }
1365 for v in 0..n {
1366 let residual = capacity[u][v] - flow_matrix[u][v];
1367 if parent[v] == usize::MAX && residual > 0 {
1368 parent[v] = u;
1369 queue.push_back(v);
1370 }
1371 }
1372 }
1373 if parent[sink] == usize::MAX {
1374 break;
1375 }
1376 let mut bottleneck = i64::MAX;
1377 let mut v = sink;
1378 while v != source {
1379 let u = parent[v];
1380 bottleneck = bottleneck.min(capacity[u][v] - flow_matrix[u][v]);
1381 v = u;
1382 }
1383 v = sink;
1384 while v != source {
1385 let u = parent[v];
1386 flow_matrix[u][v] += bottleneck;
1387 flow_matrix[v][u] -= bottleneck;
1388 v = u;
1389 }
1390 total_flow += bottleneck;
1391 }
1392 total_flow
1393}
1394#[cfg(test)]
1395mod tests {
1396 use super::*;
1397 #[test]
1398 fn test_bfs_connected() {
1399 let mut g = UndirectedGraph::new(4);
1400 g.add_edge(0, 1);
1401 g.add_edge(1, 2);
1402 g.add_edge(2, 3);
1403 assert!(g.is_connected());
1404 let dist = g.bfs(0);
1405 assert_eq!(dist, vec![0, 1, 2, 3]);
1406 }
1407 #[test]
1408 fn test_bfs_disconnected() {
1409 let mut g = UndirectedGraph::new(4);
1410 g.add_edge(0, 1);
1411 g.add_edge(2, 3);
1412 assert!(!g.is_connected());
1413 assert_eq!(g.num_components(), 2);
1414 }
1415 #[test]
1416 fn test_bipartite() {
1417 let k33 = UndirectedGraph::complete_bipartite(3, 3);
1418 assert!(k33.is_bipartite());
1419 let k3 = UndirectedGraph::complete(3);
1420 assert!(!k3.is_bipartite());
1421 }
1422 #[test]
1423 fn test_eulerian_even_cycle() {
1424 let c4 = UndirectedGraph::cycle(4);
1425 assert!(c4.all_degrees_even());
1426 assert!(c4.has_eulerian_circuit());
1427 }
1428 #[test]
1429 fn test_eulerian_odd_cycle_fails() {
1430 let p4 = UndirectedGraph::path(4);
1431 assert!(!p4.all_degrees_even());
1432 assert!(!p4.has_eulerian_circuit());
1433 }
1434 #[test]
1435 fn test_greedy_coloring_path() {
1436 let p4 = UndirectedGraph::path(4);
1437 let (k, coloring) = p4.greedy_coloring();
1438 assert!(k <= 2);
1439 assert!(p4.is_proper_coloring(&coloring));
1440 }
1441 #[test]
1442 fn test_greedy_coloring_complete() {
1443 let k4 = UndirectedGraph::complete(4);
1444 let (k, coloring) = k4.greedy_coloring();
1445 assert_eq!(k, 4);
1446 assert!(k4.is_proper_coloring(&coloring));
1447 }
1448 #[test]
1449 fn test_spanning_tree() {
1450 let k4 = UndirectedGraph::complete(4);
1451 let tree = k4.spanning_tree();
1452 assert_eq!(tree.len(), 3);
1453 }
1454 #[test]
1455 fn test_digraph_bfs() {
1456 let mut g = DiGraph::new(5);
1457 g.add_edge(0, 1, 1);
1458 g.add_edge(1, 2, 1);
1459 g.add_edge(2, 3, 1);
1460 g.add_edge(3, 4, 1);
1461 let dist = g.bfs(0);
1462 assert_eq!(dist, vec![0, 1, 2, 3, 4]);
1463 }
1464 #[test]
1465 fn test_topo_sort_dag() {
1466 let mut g = DiGraph::new(4);
1467 g.add_edge(0, 1, 0);
1468 g.add_edge(0, 2, 0);
1469 g.add_edge(1, 3, 0);
1470 g.add_edge(2, 3, 0);
1471 let order = g.topo_sort().expect("topo_sort should succeed");
1472 assert_eq!(order.len(), 4);
1473 }
1474 #[test]
1475 fn test_topo_sort_cycle() {
1476 let mut g = DiGraph::new(3);
1477 g.add_edge(0, 1, 0);
1478 g.add_edge(1, 2, 0);
1479 g.add_edge(2, 0, 0);
1480 assert!(g.topo_sort().is_none());
1481 }
1482 #[test]
1483 fn test_scc() {
1484 let mut g = DiGraph::new(4);
1485 g.add_edge(0, 1, 0);
1486 g.add_edge(1, 0, 0);
1487 g.add_edge(2, 3, 0);
1488 let sccs = g.scc();
1489 assert_eq!(sccs.len(), 3);
1490 }
1491 #[test]
1492 fn test_dijkstra() {
1493 let mut g = DiGraph::new(4);
1494 g.add_edge(0, 1, 1);
1495 g.add_edge(0, 2, 4);
1496 g.add_edge(1, 2, 2);
1497 g.add_edge(1, 3, 5);
1498 g.add_edge(2, 3, 1);
1499 let (dist, _) = g.dijkstra(0);
1500 assert_eq!(dist[3], 4);
1501 }
1502 #[test]
1503 fn test_bellman_ford() {
1504 let mut g = DiGraph::new(3);
1505 g.add_edge(0, 1, -1);
1506 g.add_edge(1, 2, 3);
1507 let dist = g.bellman_ford(0).expect("bellman_ford should succeed");
1508 assert_eq!(dist[2], 2);
1509 }
1510 #[test]
1511 fn test_floyd_warshall() {
1512 let mut g = DiGraph::new(3);
1513 g.add_edge(0, 1, 5);
1514 g.add_edge(1, 2, 3);
1515 g.add_edge(0, 2, 10);
1516 let d = g.floyd_warshall();
1517 assert_eq!(d[0][2], 8);
1518 }
1519 #[test]
1520 fn test_kruskal_mst() {
1521 let edges = vec![(0, 1, 1), (1, 2, 2), (0, 2, 10), (2, 3, 3)];
1522 let mst = kruskal_mst(4, edges);
1523 assert_eq!(mst.len(), 3);
1524 let total: i64 = mst.iter().map(|&(_, _, w)| w).sum();
1525 assert_eq!(total, 6);
1526 }
1527 #[test]
1528 fn test_max_flow() {
1529 let n = 4;
1530 let mut cap = vec![vec![0i64; n]; n];
1531 cap[0][1] = 3;
1532 cap[0][2] = 2;
1533 cap[1][3] = 2;
1534 cap[2][3] = 3;
1535 cap[1][2] = 1;
1536 let flow = max_flow(n, 0, 3, &cap);
1537 assert_eq!(flow, 5);
1538 }
1539 #[test]
1540 fn test_build_graph_theory_env() {
1541 let mut env = Environment::new();
1542 let _ = env.add(Declaration::Axiom {
1543 name: Name::str("Nat"),
1544 univ_params: vec![],
1545 ty: type0(),
1546 });
1547 let _ = env.add(Declaration::Axiom {
1548 name: Name::str("Bool"),
1549 univ_params: vec![],
1550 ty: type0(),
1551 });
1552 let _ = env.add(Declaration::Axiom {
1553 name: Name::str("Nat.le"),
1554 univ_params: vec![],
1555 ty: arrow(nat_ty(), arrow(nat_ty(), prop())),
1556 });
1557 let _ = env.add(Declaration::Axiom {
1558 name: Name::str("AllDegreesEven"),
1559 univ_params: vec![],
1560 ty: impl_pi(
1561 "V",
1562 type0(),
1563 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
1564 ),
1565 });
1566 let _ = env.add(Declaration::Axiom {
1567 name: Name::str("HasPerfectMatching"),
1568 univ_params: vec![],
1569 ty: impl_pi(
1570 "V",
1571 type0(),
1572 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
1573 ),
1574 });
1575 let _ = env.add(Declaration::Axiom {
1576 name: Name::str("HallCondition"),
1577 univ_params: vec![],
1578 ty: impl_pi(
1579 "V",
1580 type0(),
1581 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
1582 ),
1583 });
1584 let _ = env.add(Declaration::Axiom {
1585 name: Name::str("NoK5OrK33Subdivision"),
1586 univ_params: vec![],
1587 ty: impl_pi(
1588 "V",
1589 type0(),
1590 arrow(app(cst("SimpleGraph"), bvar(0)), prop()),
1591 ),
1592 });
1593 let _ = env.add(Declaration::Axiom {
1594 name: Name::str("IsConnectedPlanar"),
1595 univ_params: vec![],
1596 ty: arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), prop()))),
1597 });
1598 let result = build_graph_theory_env(&mut env);
1599 assert!(result.is_ok());
1600 }
1601 #[test]
1602 fn test_expander_checker_complete_graph() {
1603 let k4 = UndirectedGraph::complete(4);
1604 let checker = ExpanderChecker::new(k4);
1605 let h = checker.approximate_cheeger();
1606 assert!(h >= 1.0, "K_4 should have good expansion: h = {}", h);
1607 assert!(checker.is_expander(1.0));
1608 }
1609 #[test]
1610 fn test_expander_checker_path_graph() {
1611 let p4 = UndirectedGraph::path(4);
1612 let checker = ExpanderChecker::new(p4);
1613 let h = checker.approximate_cheeger();
1614 assert!(
1615 h < 2.0,
1616 "Path graph should have limited expansion: h = {}",
1617 h
1618 );
1619 }
1620 #[test]
1621 fn test_graphon_sampler_constant() {
1622 let sampler = GraphonSampler::new(5, Box::new(|_x, _y| 0.8));
1623 let g = sampler.sample_deterministic();
1624 assert_eq!(g.edge_count(), 10);
1625 }
1626 #[test]
1627 fn test_graphon_sampler_zero() {
1628 let sampler = GraphonSampler::new(5, Box::new(|_x, _y| 0.3));
1629 let g = sampler.sample_deterministic();
1630 assert_eq!(g.edge_count(), 0);
1631 }
1632 #[test]
1633 fn test_graphon_sampler_threshold() {
1634 let n = 6usize;
1635 let sampler = GraphonSampler::new(
1636 n,
1637 Box::new(move |x, y| {
1638 let half = 0.5f64;
1639 if (x < half) != (y < half) {
1640 0.9
1641 } else {
1642 0.1
1643 }
1644 }),
1645 );
1646 let g = sampler.sample_at_threshold(0.5);
1647 assert!(g.edge_count() > 0);
1648 assert!(g.is_bipartite());
1649 }
1650 #[test]
1651 fn test_treewidth_heuristic_tree() {
1652 let p5 = UndirectedGraph::path(5);
1653 let mut h = TreewidthHeuristic::new(&p5);
1654 let (_order, tw) = h.run();
1655 assert_eq!(tw, 1, "Path graph has treewidth 1");
1656 }
1657 #[test]
1658 fn test_treewidth_heuristic_complete() {
1659 let k4 = UndirectedGraph::complete(4);
1660 let mut h = TreewidthHeuristic::new(&k4);
1661 let (_order, tw) = h.run();
1662 assert!(tw >= 3, "K_4 treewidth should be at least 3, got {}", tw);
1663 }
1664 #[test]
1665 fn test_tutte_polynomial_tree() {
1666 let p3 = UndirectedGraph::path(3);
1667 let eval = TuttePolynomialEval::from_graph(&p3);
1668 let val = eval.evaluate(2.0, 2.0);
1669 assert!((val - 4.0).abs() < 1e-9, "T(path3; 2,2) = {}", val);
1670 }
1671 #[test]
1672 fn test_tutte_polynomial_single_edge() {
1673 let mut g = UndirectedGraph::new(2);
1674 g.add_edge(0, 1);
1675 let eval = TuttePolynomialEval::from_graph(&g);
1676 let val = eval.evaluate(2.0, 2.0);
1677 assert!(
1678 (val - 2.0).abs() < 1e-9,
1679 "T(K2; 2,2) = {} (expected 2.0)",
1680 val
1681 );
1682 }
1683 #[test]
1684 fn test_szemeredi_regularity_complete() {
1685 let k5 = UndirectedGraph::complete(5);
1686 let rl = SzemerédiRegularityLemma::new(k5, 0.5);
1687 let (parts, regular_pairs) = rl.run(2);
1688 assert_eq!(parts.len(), 2);
1689 let _ = regular_pairs;
1690 }
1691 #[test]
1692 fn test_szemeredi_density_bipartite() {
1693 let k33 = UndirectedGraph::complete_bipartite(3, 3);
1694 let rl = SzemerédiRegularityLemma::new(k33, 0.5);
1695 let part_a: Vec<usize> = (0..3).collect();
1696 let part_b: Vec<usize> = (3..6).collect();
1697 let d = rl.density(&part_a, &part_b);
1698 assert!((d - 1.0).abs() < 1e-9, "K_3,3 density = {}", d);
1699 assert!(rl.is_regular_pair(&part_a, &part_b));
1700 }
1701 #[test]
1702 fn test_new_axiom_types_build() {
1703 let _ = graph_minor_ty();
1704 let _ = vertex_expansion_ty();
1705 let _ = edge_expansion_ty();
1706 let _ = cheeger_constant_ty();
1707 let _ = spectral_gap_ty();
1708 let _ = graphon_ty();
1709 let _ = graphon_cut_distance_ty();
1710 let _ = is_perfect_graph_ty();
1711 let _ = strong_perfect_graph_thm_ty();
1712 let _ = vertex_connectivity_ty();
1713 let _ = edge_connectivity_ty();
1714 let _ = genus_ty();
1715 let _ = crossing_number_ty();
1716 let _ = hypergraph_ty();
1717 let _ = hypergraph_coloring_ty();
1718 let _ = graph_homomorphism_ty();
1719 let _ = lovasz_theta_ty();
1720 let _ = fractional_chromatic_number_ty();
1721 let _ = tree_decomposition_ty();
1722 let _ = treewidth_ty();
1723 let _ = pathwidth_ty();
1724 let _ = adjacency_matrix_ty();
1725 let _ = graph_laplacian_ty();
1726 let _ = ihara_zeta_function_ty();
1727 let _ = chromatic_polynomial_ty();
1728 let _ = tutte_polynomial_ty();
1729 let _ = matching_polynomial_ty();
1730 let _ = cayley_graph_ty();
1731 let _ = strongly_regular_graph_ty();
1732 let _ = dynamic_graph_ty();
1733 let _ = fully_dynamic_connectivity_ty();
1734 let _ = semi_streaming_sketch_ty();
1735 }
1736}