-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmao.hpp
132 lines (114 loc) · 3.81 KB
/
mao.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#pragma once
#include "graph.hpp"
template <int N>
bool isDirectedEdgeInVStructure(const Graph<N>& graph, int i, int j) {
assert(i >= 0 && i < graph.size());
assert(j >= 0 && j < graph.size());
assert(i != j);
return setDifference(
graph.directedEdgesIn(j).without(i),
graph.neighbors(i)
).isNonEmpty();
}
template <int N>
bool isValidEssentialGraph(const Graph<N>& graph) {
for(int u = 0; u < graph.size(); ++u) {
bool ret = true;
graph.bidirectionalNeighbors(u).iterateWhile([&](int v) {
ret = setDifference(graph.directedEdgesIn(v), graph.neighbors(u)).isEmpty();
return ret;
});
if(!ret) {
return false;
}
}
for(int u = 0; u < graph.size(); ++u) {
bool ret = true;
graph.directedEdgesOut(u).iterateWhile([&](int v) {
ret = false;
ret = ret || setDifference(graph.directedEdgesIn(v), graph.neighbors(u)).without(u).isNonEmpty();
ret = ret || setDifference(graph.directedEdgesIn(u), graph.neighbors(v)).isNonEmpty();
ret = ret || setIntersection(graph.directedEdgesOut(u), graph.directedEdgesIn(v)).isNonEmpty();
ret = ret || !setIntersection(graph.bidirectionalNeighbors(u), graph.directedEdgesIn(v)).isSingletonOrEmpty();
return ret;
});
if(!ret) {
return false;
}
}
for(int v = 0; v < graph.size(); ++v) {
if(setIntersection(graph.reachableVertices(v), graph.directedEdgesIn(v)).isNonEmpty()) {
return false;
}
}
bool ret = true;
graph.iterateBidirectionalComponents([&](const auto& comp) {
if(ret) {
Graph subgraph = graph.inducedSubgraph(comp);
ret = subgraph.isUndirected() && subgraph.isChordal();
}
});
return ret;
}
template <int N, typename F>
void iterateMAO_(
Graph<N>& graph,
F& f,
int i,
int j
) {
int n = graph.size();
if(i >= n) {
f((const Graph<N>&)graph);
return;
}
if(j >= n) {
iterateMAO_(graph, f, i + 1, i + 2);
return;
}
if(graph(i, j) && graph(j, i)) {
if(
!isDirectedEdgeInVStructure(graph, i, j) &&
!graph.isDirectedReachable(j, i)
) {
graph.delD(j, i);
iterateMAO_(graph, f, i, j + 1);
graph.addD(j, i);
}
if(
!isDirectedEdgeInVStructure(graph, j, i) &&
!graph.isDirectedReachable(i, j)
) {
graph.delD(i, j);
iterateMAO_(graph, f, i, j + 1);
graph.addD(i, j);
}
} else {
iterateMAO_(graph, f, i, j + 1);
}
}
template <int N, typename F>
void iterateMAO(Graph<N> graph, F f) {
assert(isValidEssentialGraph(graph));
iterateMAO_(graph, f, 0, 1);
}
// mao/enumeration.cpp
Z countMAOUsingEnumeration(const GraphData& graphData);
// mao/he_et_al_2015.cpp
Z countMAOUsingHeEtAl2015(const GraphData& graphData);
// mao/he_et_al_2016.cpp
Z countMAOUsingHeEtAl2016(const GraphData& graphData);
// mao/dynamic_programming.cpp
Z countMAOUsingDynamicProgramming(const GraphData& graphData);
// mao/treedecomp.cpp
Z countMAOUsingTreeDecompositionDP(const GraphData& graphData);
// mao/treedecomp_sym.cpp
Z countMAOUsingTreeDecompositionDPSymmetryReduction(const GraphData& graphData);
static const vector<pair<string, Z (*)(const GraphData&)>> countMAOMethods = {
{"Enumeration", countMAOUsingEnumeration},
{"He et al. 2015", countMAOUsingHeEtAl2015},
{"He et al. 2016", countMAOUsingHeEtAl2016},
{"Dynamic Programming", countMAOUsingDynamicProgramming},
{"Tree Decomposition DP", countMAOUsingTreeDecompositionDP},
{"Symmetry Reduction Tree Decomposition DP", countMAOUsingTreeDecompositionDPSymmetryReduction}
};