-
Notifications
You must be signed in to change notification settings - Fork 1
/
evaluator.h
108 lines (92 loc) · 3.79 KB
/
evaluator.h
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
#pragma once
#include "edge.h"
#include "gadget.h"
#include "node.h"
#include "orbit.h"
#include "partial_assignment.h"
#include <cstdint>
#include <future>
#include <lemon/list_graph.h>
#include <lemon/preflow.h>
#include <map>
#include <utility>
#include <vector>
class Evaluator {
OrbitInfo orbitInfo;
public:
Evaluator(const OrbitInfo orbitInfo) : orbitInfo(orbitInfo) {}
PartialAssignment optimalRelaxedExtension(const PartialAssignment& partialAssignment, const Gadget& gadget) {
using namespace lemon;
// Construct nodes in the graph
ListDigraph g;
auto source = g.addNode();
auto sink = g.addNode();
std::vector<ListDigraph::Node> hypergraphNodes;
for (long long index = 0; index < (1LL<<dimension); index++) {
hypergraphNodes.emplace_back(g.addNode());
}
// Compute the capacity of each edge in the graph
ListDigraph::ArcMap<T> capacity(g);
for (long long index = 0; index < (1LL<<dimension); index++) {
Node node((uint32_t)index);
for (unsigned direction = 0; direction < dimension; direction++) {
auto destination = node.getNeighbour(direction);
auto arc = g.addArc(
hypergraphNodes[node.getIndex()],
hypergraphNodes[destination.getIndex()]);
T weight = gadget.getWeight(Edge(node, destination));
capacity[arc] = weight;
}
if (partialAssignment.isAssigned(node)) {
ListDigraph::Arc arc;
if (partialAssignment.getValue(node)) {
arc = g.addArc(
source,
hypergraphNodes[node.getIndex()]);
}
else {
arc = g.addArc(
hypergraphNodes[node.getIndex()],
sink);
}
capacity[arc] = gadget.getTotalWeight();
}
}
Preflow<ListDigraph, ListDigraph::ArcMap<T>> preflow(g, capacity, source, sink);
preflow.runMinCut();
std::map<Node, bool> assignment;
for (long long index = 0; index < (1LL<<dimension); index++) {
Node node((uint32_t)index);
assignment[Node((uint32_t)index)] = preflow.minCut(hypergraphNodes[index]);
if (partialAssignment.isAssigned(node)) {
assert(partialAssignment.getValue(node) == assignment[node]);
}
}
return PartialAssignment(assignment);
}
Rational<T> relaxedRandomCost(const Gadget& gadget) {
T totalValue = 0;
auto allOrbits = orbitInfo.getAllNodeOrbits();
for (const auto& orbit : allOrbits) {
Node representative = orbit[0];
std::map<Node, bool> assignment;
for (uint32_t S = 0; S < dimension; S++) {
assignment[orbitInfo.chi(S)] = (representative[S] == 1);
assignment[-orbitInfo.chi(S)] = !assignment[orbitInfo.chi(S)];
}
auto extendedAssignment = optimalRelaxedExtension(PartialAssignment(assignment), gadget);
T value = 0;
for (long long index = 0; index < (1LL<<dimension); index++) {
Node node((uint32_t)index);
for (unsigned direction = 0; direction < dimension; direction++) {
auto destination = node.getNeighbour(direction);
if (extendedAssignment.getValue(node) > extendedAssignment.getValue(destination)) {
value += gadget.getWeight(Edge(node, destination));
}
}
}
totalValue += orbit.size() * value;
}
return Rational<T>(totalValue, 1<<dimension);
}
};