Skip to content

Commit 947fa4a

Browse files
committed
add tests
1 parent f7c4218 commit 947fa4a

1 file changed

Lines changed: 105 additions & 138 deletions

File tree

test/core.jl

Lines changed: 105 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using AbstractTrees
2-
using Base: oneto
2+
using Base: @kwdef, oneto
33
using Base.Order
44
using CliqueTrees
5-
using CliqueTrees: DoublyLinkedList, sympermute, cliquetree!
5+
using CliqueTrees: DoublyLinkedList, EliminationAlgorithm, sympermute, cliquetree!
66
using Graphs
77
using Graphs: SimpleEdge
88
using 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())
5575
end
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
10561076
end
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
10871108
end
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
12691236
end

0 commit comments

Comments
 (0)