-
Notifications
You must be signed in to change notification settings - Fork 1
/
preliminaries.h
148 lines (125 loc) · 3.42 KB
/
preliminaries.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <iostream>
#include <assert.h>
#include <lemon/list_graph.h>
#include <lemon/bfs.h>
#include <lemon/dijkstra.h>
#include <lemon/preflow.h>
using namespace lemon;
using namespace std;
// TODO [EASY] Use conveninece macros to reduce amount of tpes
// TODO [EASY] Maybe subgraph does have a reference to the original graph?
// Like a subgraph, but keep around the orignal graph not to hide e.g. edged going out
template <typename MyGraph>
struct GraphSubset {
MyGraph &graph;
SubGraph<MyGraph> ⊂
GraphSubset(MyGraph& g, SubGraph<MyGraph> &s) : graph(g), subset(s) {};
};
// 1. Notations
// Undirected graphs
template <typename MyGraph>
int deg(const MyGraph &g, const typename MyGraph::Node &n) {
return countIncEdges(g, n);
}
// How will this work with an adaptor that hides verts?
template <typename MyGraph>
int vol(const MyGraph &g) {
int volume = 0;
for(typename MyGraph::NodeIt n(g); n != INVALID; ++n) {
volume += deg(g, n);
}
return volume;
}
template <typename MyGraph>
int vol(const GraphSubset<MyGraph> &gs) {
int volume = 0;
for(typename SubGraph<MyGraph>::NodeIt n(gs.subset); n != INVALID; ++n) {
volume += deg(gs.graph, n);
}
return volume;
}
// E(S,T) : edges between two subsets
template <typename GT>
int n_edges_between(const GraphSubset<GT> &S_, const GraphSubset<GT> &T_) {
assert(&S_.graph == &T_.graph);
const SubGraph<GT>& S = S_.subset;
const SubGraph<GT>& T = T_.subset;
const GT &G = S_.graph;
int n = 0;
for(typename GT::EdgeIt e(G); e != INVALID; ++e) {
typename GT::Node u = G.u(e);
typename GT::Node v = G.v(e);
bool crossing = S.status(u) && T.status(v);
crossing |= S.status(v) && T.status(u);
n += crossing ? 1 : 0;
}
return n;
}
template <typename GT>
int cut_size(const GraphSubset<GT> &S_) {
const SubGraph<GT>& S = S_.subset;
const GT &G = S_.graph;
int n = 0;
for(typename GT::EdgeIt e(G); e != INVALID; ++e) {
typename GT::Node u = G.u(e);
typename GT::Node v = G.v(e);
bool crossing = S.status(u) && !S.status(v);
crossing |= S.status(v) && !S.status(u);
n += crossing ? 1 : 0;
}
return n;
}
// conductance of cut S: cut-size(S) / min(vol S, vol comp s)
template <typename GT>
double conductance(const GraphSubset<GT> &S_) {
const SubGraph<GT>& S = S_.subset;
const GT &G = S_.graph;
int d = cut_size(S_);
int volS = vol(S_);
int volcompS = vol(G) - volS;
return ((double)d)/min(volS, volcompS);
}
/*
// This will be very interesting when we do conductances of subsets - need to track what "cuts" are opposite to inside of there.
// COnductace of graph -- total search
template <typename GT>
double conductance(const GT &G) {
ListGraph::NodeMap<bool> filter(G, false);
ListGraph::EdgeMap<bool> filterE(G, true);
SubGraph<ListGraph> g_(g, filter, filterE);
GraphSubset<ListGraph> gs(g, g_);
// Base case for empty graph, and also its the max possible
double min_cond = 1;
vector<GT::NodeIt> nodes;
for(typename GT::NodeIt n(G); e != INVALID; ++e) {
nodes.push_back(n);
}
// We'll be doing some binary counting here
bool carry = false;
int i = 0;
while(i < nodes.size()) {
if(carry) {
if(!filter[nodes[i]]) {
filter[nodes[i]] = true;
carry = false;
} else {
++i;
continue;
}
}
double cond = conductance(gs);
min_cond = min(min_cond, cond);
// ?
i = 0;
// "add one"
if(!filter[nodes[i]]) {
filter[nodes[i]] = true;
} else {
filter[nodes[i]] = false;
carry = true;
++i;
}
}
return min_cond;
}
*/