-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
198 lines (144 loc) · 5.03 KB
/
main.cpp
File metadata and controls
198 lines (144 loc) · 5.03 KB
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <iostream>
#include <vector>
#include <random>
#include <limits.h>
class Vertex {
public:
std::vector<int> data;
Vertex() = default;
Vertex(const std::vector<int> &input) {
data = input;
}
// Combines two vertices
Vertex operator+(const Vertex& vec2) {
std::vector<int> new_vec(this->data);
new_vec.insert(new_vec.end(), vec2.data.begin(), vec2.data.end());
return Vertex(new_vec);
}
// Overloading == operator
bool operator==(const Vertex& other) {
return (this->data == other.data);
}
// Overloading << operator
friend std::ostream& operator<<(std::ostream& os, const Vertex& input) {
for (auto const& i : input.data) {
os << i << " ";
}
return os;
}
};
class Arc {
public:
Vertex v1;
Vertex v2;
Arc() = default;
Arc(const Vertex& input1, const Vertex& input2) {
v1 = input1;
v2 = input2;
}
// Overloading << operator
friend std::ostream& operator<<(std::ostream& os, const Arc& arc) {
os << "(" << arc.v1 << ", " << arc.v2 << ")";
return os;
}
// Overloading == operator
bool operator==(const Arc& arc) {
return (this->v1 == arc.v1 and this->v2 == arc.v2);
}
};
/**
* Generate a random integer from the range [0, max_val]
*/
const int random_int(const int max_val) {
std::random_device rd; // obtain a random number from hardware
std::mt19937 gen(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, max_val); // define the range
return distr(gen);
}
/**
* Perform the edge contraction operation: given the selected edge (u,v), remove it and it's identical edges,
* merges the nodes u and v to a single node uv, and "reattached" to the merged node all edges
* which contains either u or v .
*/
void contraction(Arc &selected_arc, std::vector<Arc> &arcs) {
Vertex new_vertex = selected_arc.v1 + selected_arc.v2;
std::vector<Arc> new_arcs;
for (std::vector<Arc>::iterator it= arcs.begin(); it != arcs.end(); it++) {
// remove arc which is the same as the selected arc
if (*it == selected_arc) {
arcs.erase(it);
it--;
continue;
}
if (it->v1 == selected_arc.v1 or it->v1==selected_arc.v2) {
new_arcs.insert(new_arcs.end(), Arc(new_vertex, it->v2));
arcs.erase(it);
it--;
continue;
}
if (it->v2==selected_arc.v1 or it->v2==selected_arc.v2) {
new_arcs.insert(new_arcs.end(), Arc(new_vertex, it->v1));
arcs.erase(it);
it--;
continue;
}
}
arcs.insert(arcs.begin(),new_arcs.begin(),new_arcs.end());
}
/**
* Implement one iteration of Karger's algorithm.
*/
auto karger_alg_loop(std::vector<Arc> arcs, int num_vertex)
{
int rand_int;
while (num_vertex > 2) {
rand_int = random_int(arcs.size() - 1);
Arc selected_arc = arcs[rand_int];
contraction(selected_arc, arcs);
num_vertex--;
}
Arc final = arcs[0]; // all arcs are identical now, so we pick one of them in order to get the two groups of vertices
struct result{Arc arc; unsigned long cut_size;};
return result{final, arcs.size()};
}
/**
* Implementation of Karger's algorithm for finding a minimum cut with high probability.
* @param arcs - list of the graph arcs
* @param num_vertex - number of vertices in the graph
* @param iterations - number of iterations
* @return a struct which contains: cut_size - the size of the resulting cut
* group1, group2 - the two groups of vertices which defines the cut.
*/
auto karger_alg(std::vector<Arc> arcs, int num_vertex, int iterations)
{
unsigned long temp_cut_size = ULONG_MAX;
Arc temp_arc;
for (int i=0; i < iterations; i++) {
auto [arc, cut_size] = karger_alg_loop(arcs, num_vertex);
if (cut_size < temp_cut_size) { // check if we did find smaller cut
temp_cut_size = cut_size;
temp_arc = arc;
if (arcs.size() == 1) {
break;
}
}
}
struct result{Vertex group1, group2; unsigned long cut_size;};
return result{temp_arc.v1, temp_arc.v2, temp_cut_size};
}
int main() {
// 1-----3
// | /
// | /
// |/
// 0-----2
Arc arc1(std::vector<int> {1}, std::vector<int> {3});
Arc arc2(std::vector<int> {1}, std::vector<int> {0});
Arc arc3(std::vector<int> {3}, std::vector<int> {0});
Arc arc4(std::vector<int> {0}, std::vector<int> {2});
std::vector<Arc> arcs_list {arc1, arc2, arc3, arc4};
int num_vertex = 4;
auto [group1, group2, mincut_size] = karger_alg(arcs_list, num_vertex, 3);
std::cout << "**Results**\nCut size:" << mincut_size << "\nGroup1: " << group1 << "\nGroup2: " << group2;
return 0;
}