-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatching.cpp
More file actions
117 lines (109 loc) · 3.18 KB
/
matching.cpp
File metadata and controls
117 lines (109 loc) · 3.18 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
/*
* mini-cp is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3
* as published by the Free Software Foundation.
*
* mini-cp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with mini-cp. If not, see http://www.gnu.org/licenses/lgpl-3.0.en.html
*
* Copyright (c) 2018. by Laurent Michel, Pierre Schaus, Pascal Van Hentenryck
*/
#include "matching.hpp"
void MaximumMatching::setup() {
_min = INT32_MAX;
_max = INT32_MIN;
for(auto& xi : _x) {
_min = std::min(_min,xi->min());
_max = std::max(_max,xi->max());
}
_valSize = _max - _min + 1;
_valMatch = new (_store) int[_valSize];
for(int k=0;k < _valSize;k++) _valMatch[k] = -1;
_magic = 0;
_match = new (_store) int[_x.size()];
for(auto k=0u;k < _x.size();k++) _match[k] = INT32_MIN;
_varSeen = new (_store) int[_x.size()];
_valSeen = new (_store) int[_valSize];
findInitialMatching();
}
void MaximumMatching::findInitialMatching() {
_szMatching = 0;
for(auto k=0u;k < _x.size();k++) {
const int minv = _x[k]->min(),maxv = _x[k]->max();
for(int i=minv;i <= maxv;i++) {
if (_valMatch[i - _min] < 0)
if (_x[k]->contains(i)) {
_match[k] = i;
_valMatch[i - _min] = k;
_szMatching++;
break;
}
}
}
}
int MaximumMatching::findMaximalMatching() {
if (_szMatching < (int)_x.size()) {
for(auto k=0u;k < _x.size();k++) {
if (_match[k] == INT32_MIN) { // not matched
_magic++;
if (findAlternatingPathFromVar(k))
_szMatching++;
}
}
}
return _szMatching;
}
bool MaximumMatching::findAlternatingPathFromVar(int i) {
if (_varSeen[i] != _magic) {
_varSeen[i] = _magic;
const int xMin = _x[i]->min(),xMax = _x[i]->max();
for(int v=xMin;v <= xMax;v++) {
if (_match[i] != v) {
if (_x[i]->contains(v)) {
if (findAlternatingPathFromVal(v)) {
_match[i] = v;
_valMatch[v - _min] = i;
return true;
}
}
}
}
}
return false;
}
bool MaximumMatching::findAlternatingPathFromVal(int v) {
if (_valSeen[v - _min] != _magic) {
_valSeen[v - _min] = _magic;
if (_valMatch[v - _min] == -1)
return true;
if (findAlternatingPathFromVar(_valMatch[v - _min]))
return true;
}
return false;
}
MaximumMatching::~MaximumMatching()
{
delete[] _valMatch;
delete[] _match;
delete[] _varSeen;
delete[] _valSeen;
}
int MaximumMatching::compute(int result[]) {
for(auto k=0u;k < _x.size();k++) {
if (_match[k] != INT32_MIN) {
if (!_x[k]->contains(_match[k])) {
_valMatch[_match[k] - _min] = -1;
_match[k] = INT32_MIN;
_szMatching--;
}
}
}
int rv = findMaximalMatching();
for(auto k=0u; k < _x.size();k++)
result[k] = _match[k];
return rv;
}