-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCircle.cpp
132 lines (117 loc) · 4.61 KB
/
Circle.cpp
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
#include <algorithm>
#include <iostream>
#include "Circle.h"
void Circle::print() const{
for (size_t i = 0; i < size(); i++) {
std::cout << edges[i].first << "-" << edges[i].second << " (" << (bool) isResidual[i] << ") | ";
}
std::cout << std::endl;
}
void Circle::addEdge(size_t node0, size_t node1, bool _isResidual) {
edges.push_back(std::make_pair(node0, node1));
isResidual.push_back(_isResidual);
length = edges.size();
}
//see paper for details and proof
void Circle::update(Circle& c) {
bool iR = c.getIsResidual()[0];
std::pair<size_t, size_t> edgeSame = c.getEdges()[0];
std::pair<size_t, size_t> edgeReverse = std::make_pair(edgeSame.second, edgeSame.first);
bool reversed = false;
size_t index = 0;
std::vector<std::pair<size_t, size_t>>::iterator it = edges.begin();
//find edgeSame if existent
for (index = 0; it != edges.end(); index++) {
if (iR == isResidual[index] and edges[index] == edgeSame) {break;}
it++;
}
//if edgeSame is in this->edges, reverse c, do if-case
//and reverse back
if (it != edges.end()) {
c.rotateBy(0, true);
reversed = true;
}
//else try to find edgeReverse
else {
it = edges.begin();
for (index = 0; it != edges.end(); index++) {
if (iR != isResidual[index] and edges[index] == edgeReverse) {break;}
it++;
}
}
//redirect this circle over c
if (it != edges.end()) {
std::vector<bool> toCopy (c.length, true);
size_t indexLeft = index - 1, indexRight = index + 1;
//take out all edges existent in both circles
toCopy[0] = false; //first edge not even in tree
//left from first edge
for (; indexLeft > 0; indexLeft--) {
//circles are in opposite directions, so reverse the edge for existence check
std::pair<size_t, size_t> checkEdge =
std::make_pair(c.getEdges()[index - indexLeft].second, c.getEdges()[index - indexLeft].first);
iR = c.getIsResidual()[index - indexLeft];
if (iR != isResidual[indexLeft] and edges[indexLeft] == checkEdge) {toCopy[index - indexLeft] = false;}
else {break;}
}
//right from first edge
for (; indexRight < this->length; indexRight++) {
//circles are in opposite directions, so reverse the edge for existence check
std::pair<size_t, size_t> checkEdge =
std::make_pair(c.getEdges()[c.length + index - indexRight].second, c.getEdges()[c.length + index - indexRight].first);
iR = c.getIsResidual()[c.length + index - indexRight];
if (iR != isResidual[indexRight] and edges[indexRight] == checkEdge) {toCopy[c.length + index - indexRight] = false;}
else {break;}
}
//construct new circle
std::vector<std::pair<size_t, size_t>> edgesNew;
std::vector<char> isResidualNew;
//first part of old circle
for (size_t i = 0; i <= indexLeft; i++) {
edgesNew.push_back(this->edges[i]);
isResidualNew.push_back(this->isResidual[i]);
}
//bypass
for (size_t i = 0; i < c.length; i++) {
if (toCopy[i]) {
edgesNew.push_back(c.getEdges()[i]);
isResidualNew.push_back(c.getIsResidual()[i]);
}
}
//last part of old circle
for (size_t i = indexRight; i < this->length; i++) {
edgesNew.push_back(this->edges[i]);
isResidualNew.push_back(this->isResidual[i]);
}
this->edges = edgesNew;
this->isResidual = isResidualNew;
}
//reverse back
if(reversed) {c.rotateBy(0, true);}
length = edges.size();
}
void Circle::rotateBy (size_t index, bool toReverse) {
//rotate in either case, such that
//the correct edge is on front
std::rotate(edges.begin(), edges.begin() + index, edges.end());
std::rotate(isResidual.begin(), isResidual.begin() + index, isResidual.end());
//all but the first entry might have to be reversed
if (toReverse) {
//change direction of all edges
for (size_t i = 0; i < this->length; i++) {
std::swap(edges[i].first, edges[i].second);
isResidual[i] = not isResidual[i];
}
std::reverse(edges.begin() + 1, edges.end());
std::reverse(isResidual.begin() + 1, isResidual.end());
}
}
const std::vector<std::pair<size_t, size_t>>& Circle::getEdges() const{
return edges;
}
const std::vector<char>& Circle::getIsResidual() const{
return isResidual;
}
size_t Circle::size() const{
return length;
}