11using AbstractTrees
2- using Base: oneto
2+ using Base: @kwdef , oneto
33using Base. Order
44using CliqueTrees
5- using CliqueTrees: DoublyLinkedList, sympermute, cliquetree!
5+ using CliqueTrees: DoublyLinkedList, EliminationAlgorithm, sympermute, cliquetree!
66using Graphs
77using Graphs: SimpleEdge
88using JET
@@ -35,6 +35,26 @@ const TYPES = (
3535 (Catlab. SymmetricGraph, Int, Int),
3636)
3737
38+ @kwdef struct SafeFlowCutter <: EliminationAlgorithm
39+ time:: Int = 5
40+ seed:: Int = 0
41+ end
42+
43+ function CliqueTrees. permutation (graph, alg:: SafeFlowCutter )
44+ time = alg. time
45+ seed = alg. seed
46+
47+ for i in 1 : 4
48+ try
49+ return permutation (graph, FlowCutter (; time, seed))
50+ catch
51+ @warn " FlowCutter failed (attempt $i )."
52+ end
53+ end
54+
55+ return permutation (graph, FlowCutter (; time, seed))
56+ end
57+
3858@testset " errors" begin
3959 matrix = [
4060 0 1 1 0 0 0 0 0
@@ -54,10 +74,10 @@ const TYPES = (
5474 @test_throws ArgumentError permutation (matrix; alg = BT ())
5575end
5676
57- using AMD: AMD as AMDJL
58- using Laplacians : Laplacians
59- using Metis : Metis
60- using TreeWidthSolver : TreeWidthSolver
77+ import AMD as AMDLib
78+ import Laplacians
79+ import Metis
80+ import TreeWidthSolver
6181
6282@testset " trees" begin
6383 @testset " interface" begin
@@ -421,16 +441,16 @@ end
421441 ND {1} (; limit = 5 ),
422442 ND {2} (; limit = 5 ),
423443 Spectral (),
424- FlowCutter (; time= 1 ),
444+ SafeFlowCutter (; time= 1 ),
425445 BT (),
426446 SAT {CryptoMiniSat_jll} (),
427447 MinimalChordal (),
428448 CompositeRotations ([1 , 2 , 3 ]),
429449 SafeRules (),
430450 SafeSeparators (),
431451 ConnectedComponents (),
432- BestWidth (MMD (), MF ()),
433- BestFill (MMD (), MF ()),
452+ BestWidth (MCS (), MF ()),
453+ BestFill (MCS (), MF ()),
434454 )
435455 @test isa (repr (" text/plain" , alg), String)
436456 end
@@ -492,14 +512,14 @@ end
492512 MMD (),
493513 # METIS(),
494514 # Spectral(),
495- FlowCutter (; time= 1 ),
515+ SafeFlowCutter (; time= 1 ),
496516 BT (),
497517 MinimalChordal (),
498518 CompositeRotations ([]),
499519 SafeRules (),
500520 SafeSeparators (),
501521 ConnectedComponents (),
502- BestWidth (MMD (), MF ()),
522+ BestWidth (MCS (), MF ()),
503523 )
504524 @test permutation (graph; alg) == ([], [])
505525 end
@@ -540,14 +560,14 @@ end
540560 ND {1} (; limit = 5 ),
541561 ND {2} (; limit = 5 ),
542562 # Spectral,
543- FlowCutter (; time= 1 ),
563+ SafeFlowCutter (; time= 1 ),
544564 BT (),
545565 CompositeRotations ([1 ]),
546566 SafeRules (),
547567 SafeSeparators (),
548568 ConnectedComponents (),
549- BestWidth (MMD (), MF ()),
550- BestFill (MMD (), MF ()),
569+ BestWidth (MCS (), MF ()),
570+ BestFill (MCS (), MF ()),
551571 )
552572 @test permutation (graph; alg) == ([1 ], [1 ])
553573 end
@@ -799,15 +819,15 @@ end
799819 ND {1} (; limit = 5 ),
800820 ND {2} (; limit = 5 ),
801821 Spectral (),
802- FlowCutter (; time= 1 ),
822+ SafeFlowCutter (; time= 1 ),
803823 BT (),
804824 MinimalChordal (),
805825 CompositeRotations ([1 , 3 ]),
806826 SafeRules (),
807827 SafeSeparators (),
808828 ConnectedComponents (),
809- BestWidth (MMD (), MF ()),
810- BestFill (MMD (), MF ()),
829+ BestWidth (MCS (), MF ()),
830+ BestFill (MCS (), MF ()),
811831 )
812832 order, index = permutation (graph; alg)
813833 order, index = permutation (ones (17 ), graph; alg)
@@ -1055,15 +1075,16 @@ end
10551075 end
10561076end
10571077
1058- @testset " greedy " begin
1078+ @testset " fill " begin
10591079 ssmc = ssmc_db ()
10601080
1061- greedy = (
1081+ algs = (
10621082 MMD (),
10631083 MMD (; delta= 5 ),
10641084 AMF (; speed= 1 ),
10651085 AMF (; speed= 2 ),
10661086 AMF (; speed= 3 ),
1087+ ND {2} (),
10671088 MF (),
10681089 )
10691090
@@ -1076,7 +1097,7 @@ end
10761097 for (name, fill) in matrices
10771098 matrix = mmread (joinpath (fetch_ssmc (ssmc[ssmc. name .== name, :]; format= " MM" )[1 ], " $(name) .mtx" ))
10781099
1079- for alg in greedy
1100+ for alg in algs
10801101 @test treefill (matrix; alg) <= fill
10811102 end
10821103 end
@@ -1087,7 +1108,32 @@ end
10871108end
10881109
10891110@testset " exact treewidth" begin
1090- __graph1 = BipartiteGraph (
1111+ lalgs = (
1112+ MMW {1} (),
1113+ MMW {2} (),
1114+ MMW {3} (),
1115+ )
1116+
1117+ ualgs = (
1118+ SAT {libpicosat_jll} (),
1119+ SAT {Lingeling_jll} (),
1120+ SAT {PicoSAT_jll} (),
1121+ SAT {CryptoMiniSat_jll} (),
1122+ SafeRules (SAT {CryptoMiniSat_jll} ()),
1123+ SafeSeparators (SAT {CryptoMiniSat_jll} ()),
1124+ SafeRules (SafeSeparators (BT ())),
1125+ SafeSeparators (BT ()),
1126+ )
1127+
1128+ walgs = (
1129+ SafeRules (SafeSeparators (BT ())),
1130+ SafeSeparators (BT ()),
1131+ )
1132+
1133+ weights1 = log2 .([2 , 2 , 4 , 2 , 4 , 2 , 2 , 2 , 2 , 2 , 4 , 2 , 4 , 2 , 4 , 2 ])
1134+ weights2 = log2 .([4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 ])
1135+
1136+ graph1 = BipartiteGraph (
10911137 [
10921138 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0
10931139 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0
@@ -1108,7 +1154,7 @@ end
11081154 ]
11091155 )
11101156
1111- __graph2 = BipartiteGraph (
1157+ graph2 = BipartiteGraph (
11121158 [
11131159 0 1 1 0 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11141160 1 0 1 1 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
@@ -1145,125 +1191,46 @@ end
11451191 ]
11461192 )
11471193
1148- weights1 = log2 .([2 , 2 , 4 , 2 , 4 , 2 , 2 , 2 , 2 , 2 , 4 , 2 , 4 , 2 , 4 , 2 ])
1149- weights2 = log2 .([4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 3 , 4 , 4 , 3 , 4 ])
1194+ graphs = (
1195+ (weights1, graph1, 4 , 0 , 0 , 5.0 , 0 , 0 ),
1196+ (weights2, graph2, 9 , 21 , 94 , 19.169925001442312 , 21 , 94 ),
1197+ )
11501198
11511199 for (G, V, E) in TYPES
11521200 @testset " $(nameof (G)) " begin
1153- graph1 = G (__graph1)
1154- graph2 = G (__graph2)
1155-
1156- kernel1, rest1... = CliqueTrees. pr4 (graph1, lowerbound (graph1))
1157- @test nv (kernel1) === V (0 )
1158- @test ne (kernel1) === 0
1159-
1160- kernel1, rest1... = CliqueTrees. pr4 (weights1, graph1, lowerbound (weights1, graph1))
1161- @test nv (kernel1) === V (0 )
1162- @test ne (kernel1) === 0
1163-
1164- kernel2, rest2... = CliqueTrees. pr4 (graph2, lowerbound (graph2))
1165- @test nv (kernel2) === V (21 )
1166- @test ne (kernel2) === 94
1167-
1168- kernel2, rest2... = CliqueTrees. pr4 (weights2, graph2, lowerbound (weights2, graph2))
1169- @test nv (kernel2) === V (21 )
1170- @test ne (kernel2) === 94
1171-
1172- width1 = V (4 )
1173- lb11 = lowerbound (graph1, MMW {1} ())
1174- lb12 = lowerbound (graph1, MMW {2} ())
1175- lb13 = lowerbound (graph1, MMW {3} ())
1176- ub1 = treewidth (graph1)
1177-
1178- @test isa (lb11, V)
1179- @test isa (lb12, V)
1180- @test isa (lb13, V)
1181- @test isa (ub1, V)
1182- @test lb11 <= width1
1183- @test lb12 <= width1
1184- @test lb13 <= width1
1185- @test width1 <= ub1
1186- # @test treewidth(graph1; alg=ConnectedComponents(BT())) === width1
1187- @test treewidth (graph1; alg = SAT {libpicosat_jll} ()) === width1
1188- @test treewidth (graph1; alg = SAT {Lingeling_jll} ()) === width1
1189- @test treewidth (graph1; alg = SAT {PicoSAT_jll} ()) === width1
1190- @test treewidth (graph1; alg = SAT {CryptoMiniSat_jll} ()) === width1
1191- # @test treewidth(graph1; alg=SafeRules(ConnectedComponents(BT()))) === width1
1192- @test treewidth (graph1; alg = SafeRules (SAT {libpicosat_jll} ())) === width1
1193- @test treewidth (graph1; alg = SafeRules (SAT {Lingeling_jll} ())) === width1
1194- @test treewidth (graph1; alg = SafeRules (SAT {PicoSAT_jll} ())) === width1
1195- @test treewidth (graph1; alg = SafeRules (SAT {CryptoMiniSat_jll} ())) === width1
1196- @test treewidth (graph1; alg = SafeSeparators (BT ())) === width1
1197- @test treewidth (graph1; alg = SafeSeparators (SAT {libpicosat_jll} ())) === width1
1198- @test treewidth (graph1; alg = SafeSeparators (SAT {Lingeling_jll} ())) === width1
1199- @test treewidth (graph1; alg = SafeSeparators (SAT {PicoSAT_jll} ())) === width1
1200- @test treewidth (graph1; alg = SafeSeparators (SAT {CryptoMiniSat_jll} ())) === width1
1201-
1202- width1 = 5.0
1203- lb11 = lowerbound (weights1, graph1, MMW {1} ())
1204- lb12 = lowerbound (weights1, graph1, MMW {2} ())
1205- lb13 = lowerbound (weights1, graph1, MMW {3} ())
1206- ub1 = treewidth (weights1, graph1)
1207-
1208- @test isa (lb11, Float64)
1209- @test isa (lb12, Float64)
1210- @test isa (lb13, Float64)
1211- @test isa (ub1, Float64)
1212- @test lb11 <= width1
1213- @test lb12 <= width1
1214- @test lb13 <= width1
1215- @test width1 <= ub1
1216- # @test treewidth(weights1, graph1; alg=ConnectedComponents(BT())) === width1
1217- # @test treewidth(weights1, graph1; alg=SafeRules(ConnectedComponents(BT()))) === width1
1218- @test treewidth (weights1, graph1; alg = SafeSeparators (BT ())) === width1
1219-
1220- width2 = V (9 )
1221- lb21 = lowerbound (graph2, MMW {1} ())
1222- lb22 = lowerbound (graph2, MMW {2} ())
1223- lb23 = lowerbound (graph2, MMW {3} ())
1224- ub2 = treewidth (graph2)
1225-
1226- @test isa (lb21, V)
1227- @test isa (lb22, V)
1228- @test isa (lb23, V)
1229- @test isa (ub2, V)
1230- @test lb21 <= width2
1231- @test lb22 <= width2
1232- @test lb23 <= width2
1233- @test width2 <= ub2
1234- @test treewidth (graph2; alg = BT ()) === width2
1235- @test treewidth (graph2; alg = SAT {libpicosat_jll} ()) === width2
1236- @test treewidth (graph2; alg = SAT {Lingeling_jll} ()) === width2
1237- @test treewidth (graph2; alg = SAT {PicoSAT_jll} ()) === width2
1238- @test treewidth (graph2; alg = SAT {CryptoMiniSat_jll} ()) === width2
1239- @test treewidth (graph2; alg = SafeRules (BT ())) === width2
1240- @test treewidth (graph2; alg = SafeRules (SAT {libpicosat_jll} ())) === width2
1241- @test treewidth (graph2; alg = SafeRules (SAT {Lingeling_jll} ())) === width2
1242- @test treewidth (graph2; alg = SafeRules (SAT {PicoSAT_jll} ())) === width2
1243- @test treewidth (graph2; alg = SafeRules (SAT {CryptoMiniSat_jll} ())) === width2
1244- @test treewidth (graph2; alg = SafeSeparators (BT ())) === width2
1245- @test treewidth (graph2; alg = SafeSeparators (SAT {libpicosat_jll} ())) === width2
1246- @test treewidth (graph2; alg = SafeSeparators (SAT {Lingeling_jll} ())) === width2
1247- @test treewidth (graph2; alg = SafeSeparators (SAT {PicoSAT_jll} ())) === width2
1248- @test treewidth (graph2; alg = SafeSeparators (SAT {CryptoMiniSat_jll} ())) === width2
1249-
1250- width2 = 19.169925001442312
1251- lb21 = lowerbound (weights2, graph2, MMW {1} ())
1252- lb22 = lowerbound (weights2, graph2, MMW {2} ())
1253- lb23 = lowerbound (weights2, graph2, MMW {3} ())
1254- ub2 = treewidth (weights2, graph2)
1255-
1256- @test isa (lb21, Float64)
1257- @test isa (lb22, Float64)
1258- @test isa (lb23, Float64)
1259- @test isa (ub2, Float64)
1260- @test lb21 <= width2
1261- @test lb22 <= width2
1262- @test lb23 <= width2
1263- @test width2 <= ub2
1264- @test treewidth (weights2, graph2; alg = BT ()) === width2
1265- @test treewidth (weights2, graph2; alg = SafeRules (BT ())) === width2
1266- @test treewidth (weights2, graph2; alg = SafeSeparators (BT ())) === width2
1201+ for (weights, graph, uwidth, un, um, wwidth, wn, wm) in graphs
1202+ graph = G (graph); uwidth = V (uwidth); un = V (un); wn = V (wn)
1203+
1204+ ukernel, urest... = CliqueTrees. pr4 (graph, lowerbound (graph))
1205+ wkernel, wrest... = CliqueTrees. pr4 (weights, graph, lowerbound (weights, graph))
1206+ @test nv (ukernel) === un
1207+ @test nv (wkernel) === wn
1208+ @test ne (ukernel) === um
1209+ @test ne (wkernel) === wm
1210+
1211+ for alg in lalgs
1212+ u = lowerbound (graph; alg)
1213+ w = lowerbound (weights, graph; alg)
1214+ @test isa (u, V)
1215+ @test isa (w, Float64)
1216+ @test u <= uwidth
1217+ @test w <= wwidth
1218+ end
1219+
1220+ for alg in ualgs
1221+ order, tree = cliquetree (graph; alg)
1222+ @test treewidth (graph; alg= order) == uwidth
1223+ @test treewidth (tree) == uwidth
1224+ @test treefill (graph; alg= order) == treefill (tree)
1225+ end
1226+
1227+ for alg in walgs
1228+ order, tree = cliquetree (weights, graph; alg)
1229+ @test treewidth (weights, graph; alg= order) == wwidth
1230+ @test treewidth (view (weights, order), tree) == wwidth
1231+ @test treefill (weights, graph; alg= order) == treefill (view (weights, order), tree)
1232+ end
1233+ end
12671234 end
12681235 end
12691236end
0 commit comments