TTK
Loading...
Searching...
No Matches
AssignmentExhaustive.h
Go to the documentation of this file.
1
16
17#pragma once
18
19#include <AssignmentSolver.h>
20#include <Debug.h>
21
22#include <iterator>
23#include <limits>
24#include <map>
25#include <queue>
26#include <set>
27
28namespace ttk {
29
30 template <class dataType>
31 class AssignmentExhaustive : virtual public Debug,
32 public AssignmentSolver<dataType> {
33
34 public:
36
37 ~AssignmentExhaustive() override = default;
38
39 int run(std::vector<MatchingType> &matchings) override;
40
41 void setSaveAsgn(bool doSave) {
42 saveAsgn = doSave;
43 }
44
45 dataType tryAssignment(std::vector<int> &asgn,
46 std::vector<MatchingType> &matchings);
47
48 std::string vectorToString(std::vector<dataType> &my_vector) {
49 std::stringstream result;
50 std::copy(my_vector.begin(), my_vector.end(),
51 std::ostream_iterator<dataType>(result, ""));
52 return result.str();
53 }
54
55 void enumerateAssignments(unsigned int min_dim,
56 unsigned int max_dim,
57 std::vector<std::vector<int>> &allAsgn) {
58 std::queue<std::tuple<std::vector<int>, std::vector<int>, bool,
59 std::vector<bool>, int>>
60 queue;
61
62 std::vector<int> asgn_temp, unasgn_temp;
63 std::vector<bool> const done_temp(max_dim, false);
64 queue.emplace(asgn_temp, unasgn_temp, false, done_temp, -1);
65
66 while(!queue.empty()) {
67 auto queueElem = queue.front();
68 queue.pop();
69 std::vector<int> const asgn = std::get<0>(queueElem);
70 std::vector<int> const unasgn = std::get<1>(queueElem);
71 bool const toUnasgn = std::get<2>(queueElem);
72 std::vector<bool> done = std::get<3>(queueElem);
73 unsigned int const maxDone = std::get<4>(queueElem);
74
75 unsigned int const ind = asgn.size();
76 for(unsigned int j = 0; j < max_dim + 1; ++j) {
77 std::vector<int> new_asgn(asgn);
78 std::vector<int> new_unasgn(unasgn);
79 std::vector<bool> new_done(done);
80 int new_maxDone = maxDone;
81 if(j < max_dim) {
82 if(not done[j]) {
83 if(ind >= min_dim and maxDone > j)
84 continue;
85 } else
86 continue;
87
88 if(not toUnasgn) {
89 new_asgn.push_back(j);
90 if(ind >= min_dim)
91 new_maxDone = std::max(maxDone, j);
92 } else {
93 new_unasgn.push_back(j);
94 new_maxDone = std::max(maxDone, j);
95 }
96 new_done[j] = true;
97
98 unsigned int const new_ind = new_asgn.size();
99 if(new_ind == max_dim) {
100 // A new assignment is made here
101 for(auto &new_unasgn_elem : new_unasgn)
102 new_asgn.push_back(new_unasgn_elem);
103 // std::sort(new_asgn.begin()+min_dim, new_asgn.end());
104 allAsgn.push_back(new_asgn);
105 } else
106 queue.emplace(new_asgn, new_unasgn, false, new_done, new_maxDone);
107
108 } else {
109 if(not toUnasgn and ind < min_dim) {
110 new_asgn.push_back(max_dim);
111 queue.emplace(new_asgn, new_unasgn, true, new_done, new_maxDone);
112 }
113 }
114 }
115 }
116 }
117
118 void printAssignments(std::vector<std::vector<int>> &allAsgn) {
120 std::stringstream ss;
121 ss << "{";
122 for(auto &vecTemp : allAsgn) {
123 ss << "{";
124 for(unsigned int i = 0; i < vecTemp.size(); ++i) {
125 auto valTemp = vecTemp[i];
126 ss << valTemp;
127 if(i != vecTemp.size() - 1)
128 ss << ",";
129 }
130 ss << "}, ";
131 }
132 ss << "}";
135 }
136
137 private:
138 // This attribute will store the computed assignments
139 std::map<std::string, std::vector<std::vector<int>>> savedAsgn;
140 bool saveAsgn = false;
141 };
142
143 template <typename dataType>
145 std::vector<int> &asgn, std::vector<MatchingType> &matchings) {
146 unsigned int const nRows = this->costMatrix.size() - 1;
147 unsigned int const nCols = this->costMatrix[0].size() - 1;
148 // int max_dim = std::max(nRows, nCols);
149 unsigned int const min_dim = std::min(nRows, nCols);
150 bool const transpose = nRows > nCols;
151
152 dataType cost = 0;
153 for(unsigned int ind = 0; ind < asgn.size(); ++ind) {
154 int const indMatrix = std::min(ind, min_dim);
155 int const i = (!transpose) ? indMatrix : asgn[ind];
156 int const j = (!transpose) ? asgn[ind] : indMatrix;
157 cost += this->costMatrix[i][j];
158 matchings.push_back(std::make_tuple(i, j, this->costMatrix[i][j]));
159 }
160 return cost;
161 }
162
163 template <typename dataType>
165 std::vector<MatchingType> &matchings) {
166 int const nRows = this->costMatrix.size() - 1;
167 int const nCols = this->costMatrix[0].size() - 1;
168 int const max_dim = std::max(nRows, nCols);
169 int const min_dim = std::min(nRows, nCols);
170
171 // --- Construct all possible assignments
172 std::vector<std::vector<int>> allAsgn;
173 // We hard write the basic assignments to avoid the call of
174 // enumerateAssignments
175 // These assignments are automatically generated by enumerateAssignments
176 if(min_dim == 1 and max_dim == 1)
177 allAsgn = {{0}, {1, 0}};
178 else if(min_dim == 1 and max_dim == 2)
179 allAsgn = {{0, 1}, {2, 0, 1}, {1, 0}};
180 else if(min_dim == 1 and max_dim == 3)
181 allAsgn = {{0, 1, 2}, {3, 0, 1, 2}, {1, 0, 2}, {2, 0, 1}};
182 else if(min_dim == 1 and max_dim == 4)
183 allAsgn = {{0, 1, 2, 3},
184 {4, 0, 1, 2, 3},
185 {1, 0, 2, 3},
186 {2, 0, 1, 3},
187 {3, 0, 1, 2}};
188 else if(min_dim == 1 and max_dim == 5)
189 allAsgn = {{0, 1, 2, 3, 4}, {5, 0, 1, 2, 3, 4}, {1, 0, 2, 3, 4},
190 {2, 0, 1, 3, 4}, {3, 0, 1, 2, 4}, {4, 0, 1, 2, 3}};
191 else if(min_dim == 1 and max_dim == 6)
192 allAsgn = {{0, 1, 2, 3, 4, 5}, {6, 0, 1, 2, 3, 4, 5}, {1, 0, 2, 3, 4, 5},
193 {2, 0, 1, 3, 4, 5}, {3, 0, 1, 2, 4, 5}, {4, 0, 1, 2, 3, 5},
194 {5, 0, 1, 2, 3, 4}};
195 else if(min_dim == 2 and max_dim == 2)
196 allAsgn = {{0, 1}, {0, 2, 1}, {2, 1, 0}, {2, 2, 0, 1},
197 {1, 0}, {1, 2, 0}, {2, 0, 1}};
198 else {
199 std::stringstream ss;
200 ss << min_dim << "_" << max_dim;
201 std::string const asgnName = ss.str();
202 // not found
203 if(not saveAsgn or savedAsgn.find(asgnName) == savedAsgn.end()) {
204 if(saveAsgn)
206 enumerateAssignments(min_dim, max_dim, allAsgn);
207 if(saveAsgn) {
208 savedAsgn[asgnName] = allAsgn;
209 std::stringstream ss2;
210 ss2 << allAsgn.size() << " done";
212 }
213 } else
214 allAsgn = savedAsgn[asgnName];
215 }
216
217 // --- Try these assignments and get the better
218 dataType bestCost = std::numeric_limits<dataType>::max();
219 std::vector<MatchingType> bestMatching;
220 for(std::vector<int> &asgn : allAsgn) {
221 std::vector<MatchingType> tempMatching;
222 dataType cost = tryAssignment(asgn, tempMatching);
223 if(bestCost > cost) {
224 bestCost = cost;
225 bestMatching = tempMatching;
226 }
227 }
228 matchings = bestMatching;
229
230 return 0;
231 }
232
233} // namespace ttk
~AssignmentExhaustive() override=default
void printAssignments(std::vector< std::vector< int > > &allAsgn)
std::string vectorToString(std::vector< dataType > &my_vector)
void enumerateAssignments(unsigned int min_dim, unsigned int max_dim, std::vector< std::vector< int > > &allAsgn)
int run(std::vector< MatchingType > &matchings) override
dataType tryAssignment(std::vector< int > &asgn, std::vector< MatchingType > &matchings)
Minimalist debugging class.
Definition Debug.h:88
The Topology ToolKit.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)