2 #ifndef ANDRES_GRAPH_MULTICUT_ILP_HXX
3 #define ANDRES_GRAPH_MULTICUT_ILP_HXX
13 #include "andres/partition.hxx"
14 #include "andres/graph/complete-graph.hxx"
15 #include "andres/graph/paths.hxx"
16 #include "andres/graph/components.hxx"
17 #include "andres/graph/shortest-paths.hxx"
31 template<
typename ILP,
typename GRAPH,
typename ECA,
typename ELA,
typename VIS>
36 const ELA& inputLabels,
39 size_t numberOfIterations = std::numeric_limits<size_t>::max()
41 struct SubgraphWithCut {
42 SubgraphWithCut(
const ILP&
ilp)
45 bool vertex(
const size_t v)
const
47 bool edge(
const size_t e)
const
48 {
return ilp_.label(e) == 0; }
54 std::deque<size_t> path;
55 std::vector<ptrdiff_t> buffer;
56 std::vector<double> variables(graph.numberOfEdges());
57 std::vector<double> coefficients(graph.numberOfEdges());
59 auto addCycleInequalities = [&] ()
61 components.
build(graph, SubgraphWithCut(ilp));
66 #pragma omp parallel for firstprivate(path, buffer, variables, coefficients), schedule(guided)
67 for (
size_t edge = 0; edge < graph.numberOfEdges(); ++edge)
68 if (ilp.label(edge) == 1)
70 auto v0 = graph.vertexOfEdge(edge, 0);
71 auto v1 = graph.vertexOfEdge(edge, 1);
76 spsp(graph, SubgraphWithCut(ilp), v0, v1, path, buffer);
79 if (
findChord(graph, path.begin(), path.end(),
true).first)
83 auto sz = path.size();
85 for (
size_t j = 0; j < sz - 1; ++j)
87 variables[j] =
static_cast<double>(graph.findEdge(path[j], path[j + 1]).second);
88 coefficients[j] = 1.0;
91 variables[sz-1] =
static_cast<double>(edge);
92 coefficients[sz-1] = -1.0;
95 ilp.addConstraint(variables.begin(), variables.begin() + sz, coefficients.begin(), 0, std::numeric_limits<double>::infinity());
105 auto repairSolution = [&] ()
107 for (
size_t edge = 0; edge < graph.numberOfEdges(); ++edge)
109 auto v0 = graph.vertexOfEdge(edge, 0);
110 auto v1 = graph.vertexOfEdge(edge, 1);
112 outputLabels[edge] = components.
areConnected(v0, v1) ? 0 : 1;
115 ilp.setStart(outputLabels.begin());
118 ilp.initModel(graph.numberOfEdges(), edgeCosts.data());
119 ilp.setStart(inputLabels.begin());
121 for (
size_t i = 0; numberOfIterations == 0 || i < numberOfIterations; ++i)
127 if (!visitor(outputLabels))
133 if (addCycleInequalities() == 0)
140 template<
typename ILP,
typename GRAPH,
typename ECA,
typename ELA>
144 const ECA& edgeCosts,
145 const ELA& inputLabels,
147 size_t numberOfIterations = std::numeric_limits<size_t>::max()
150 bool operator()(ELA
const& edge_labels)
const {
155 ilp<ILP>(graph, edgeCosts, inputLabels, outputLabels, visitor, numberOfIterations);
163 template<
typename ILP,
typename GRAPH_VISITOR,
typename ECA,
typename ELA,
typename VIS>
167 const ECA& edgeCosts,
168 const ELA& inputLabels,
171 size_t numberOfIterations = std::numeric_limits<size_t>::max()
173 struct SubgraphWithCut {
174 SubgraphWithCut(
const ILP&
ilp)
177 bool vertex(
const size_t v)
const
179 bool edge(
const size_t e)
const
180 {
return ilp_.label(e) == 0; }
186 std::array<double, 3> variables;
187 std::array<double, 3> coefficients;
189 auto addCycleInequalities = [&] ()
191 components.
build(graph, SubgraphWithCut(ilp));
195 #pragma omp parallel for firstprivate(variables, coefficients), schedule(guided)
197 if (ilp.label(edge) == 1)
206 if (i == v0 || i == v1)
209 variables[0] = graph.
findEdge(v0, i).second;
210 variables[1] = graph.
findEdge(v1, i).second;
212 if (ilp.label(variables[0]) == 0 && ilp.label(variables[1]) == 0)
214 coefficients[0] = 1.0;
215 coefficients[1] = 1.0;
216 coefficients[2] = -1.0;
219 ilp.addConstraint(variables.begin(), variables.end(), coefficients.begin(), 0, std::numeric_limits<double>::infinity());
230 auto repairSolution = [&] ()
237 outputLabels[edge] = components.
areConnected(v0, v1) ? 0 : 1;
240 ilp.setStart(outputLabels.begin());
244 ilp.setStart(inputLabels.begin());
246 for (
size_t i = 0; numberOfIterations == 0 || i < numberOfIterations; ++i)
252 if (!visitor(outputLabels))
258 if (addCycleInequalities() == 0)
265 template<
typename ILP,
typename GRAPH_VISITOR,
typename ECA,
typename ELA>
269 const ECA& edgeCosts,
270 const ELA& inputLabels,
272 size_t numberOfIterations = std::numeric_limits<size_t>::max()
276 bool operator()(ELA
const& edge_labels)
const
282 ilp<ILP>(graph, edgeCosts, inputLabels, outputLabels, visitor, numberOfIterations);
289 #endif // #ifndef ANDRES_GRAPH_MULTICUT_ILP_HXX