7template <
typename dataType>
9 std::vector<MatchingType> &matchings) {
12 const int maxIter = 100000;
16 std::vector<std::vector<dataType>> inputMatrix(
17 this->rowSize, std::vector<dataType>(this->colSize));
18 copyInputMatrix(inputMatrix);
23 "Step " + std::to_string(step) +
", Iteration " + std::to_string(iter),
24 debug::Priority::DETAIL);
26 if(iter > 20 && (iter % (
int)std::round((
double)maxIter / 5.0) == 0)) {
28 = std::round(100.0 * (
double)iter / (
double)maxIter);
36 this->
printMsg(
"Failed to converge after " + std::to_string(maxIter)
37 +
" iterations. Aborting.");
76 this->computeAffectationCost(inputMatrix);
77 this->affect(matchings, inputMatrix);
84template <
typename dataType>
88 std::vector<std::vector<dataType>> *C
92 dataType maxVal = std::numeric_limits<dataType>::max();
93 for(
int r = 0; r < this->rowSize - 1; ++r) {
94 rowLimitsPlus[r] = -1;
95 rowLimitsMinus[r] = -1;
97 for(
int c = 0; c < this->colSize - 1; ++c) {
98 colLimitsPlus[c] = -1;
99 colLimitsMinus[c] = -1;
102 int droppedMinus = 0;
105 for(
int r = 0; r < this->rowSize - 1; ++r) {
106 for(
int c = 0; c < this->colSize - 1; ++c)
107 if((*C)[r][c] != maxVal) {
108 rowLimitsMinus[r] = c;
111 if(rowLimitsMinus[r] == -1) {
113 rowLimitsMinus[r] = 0;
116 for(
int c = this->colSize - 2; c >= 0; --c)
117 if((*C)[r][c] != maxVal) {
118 rowLimitsPlus[r] = c + 1;
121 if(rowLimitsPlus[r] == -1) {
123 rowLimitsPlus[r] = this->colSize - 1;
127 if(droppedMinus > 0) {
129 "Unexpected non-assignable row [minus], dropping optimisation for "
130 + std::to_string(droppedMinus) +
" row(s).",
131 debug::Priority::DETAIL);
134 if(droppedPlus > 0) {
136 "Unexpected non-assignable row [plus], dropping optimisation for "
137 + std::to_string(droppedPlus) +
" row(s).",
138 debug::Priority::DETAIL);
144 for(
int c = 0; c < this->colSize - 1; ++c) {
145 for(
int r = 0; r < this->rowSize - 1; ++r)
146 if((*C)[r][c] != maxVal) {
147 colLimitsMinus[c] = r;
150 for(
int r = this->rowSize - 1; r >= 0; --r)
151 if((*C)[r][c] != maxVal) {
152 colLimitsPlus[c] = r + 1;
155 if(colLimitsPlus[c] == -1) {
157 colLimitsMinus[c] = 0;
159 if(colLimitsMinus[c] == -1) {
161 colLimitsMinus[c] = this->rowSize;
165 if(droppedMinus > 0) {
167 "Unexpected non-assignable row [minus], dropping optimisation for "
168 + std::to_string(droppedMinus) +
" row(s).",
169 debug::Priority::DETAIL);
172 if(droppedPlus > 0) {
174 "Unexpected non-assignable row [plus], dropping optimisation for "
175 + std::to_string(droppedPlus) +
" row(s).",
176 debug::Priority::DETAIL);
179 rowLimitsMinus[this->rowSize - 1] = 0;
180 rowLimitsPlus[this->rowSize - 1] = this->colSize - 1;
184 for(
int r = 0; r < this->rowSize - 1; ++r) {
185 dataType lastElement = (*C)[r][this->colSize - 1];
186 for(
int c = 0; c < this->colSize - 1; ++c) {
187 (*C)[r][c] -= lastElement;
192 for(
int c = 0; c < this->colSize - 1; ++c) {
193 minInCol = (*C)[0][c];
195 for(
int r = 0; r < this->rowSize; ++r)
196 if((*C)[r][c] < minInCol)
197 minInCol = (*C)[r][c];
199 for(
int r = 0; r < this->rowSize; ++r)
200 (*C)[r][c] -= minInCol;
209template <
typename dataType>
212 std::vector<std::vector<dataType>> *C
213 = AssignmentSolver<dataType>::getCostMatrixPointer();
215 for(
int r = 0; r < this->rowSize - 1; ++r) {
216 for(
int c = 0; c < this->colSize - 1; ++c) {
217 if(!rowCover[r] && !colCover[c] && isZero((*C)[r][c])) {
228 for(
int c = 0; c < this->colSize - 1; ++c)
229 if(isZero((*C)[this->rowSize - 1][c]) && !colCover[c]) {
230 M[this->rowSize - 1][c] = 1;
236 for(
int r = 0; r < this->rowSize; ++r)
239 for(
int c = 0; c < this->colSize - 1; ++c)
249template <
typename dataType>
252 for(
int r = 0; r < this->rowSize; ++r) {
253 const int start = rowLimitsMinus[r];
254 const int end = rowLimitsPlus[r];
255 for(
int c = start; c <
end; ++c)
260 int processedCols = 0;
262 for(
int c = 0; c < this->colSize - 1; ++c)
266 if(processedCols >= this->colSize - 1)
278template <
typename dataType>
295 const int colOfStarInRow = findStarInRow(row);
297 if(colOfStarInRow > -1 && row < this->rowSize - 1) {
298 rowCover[row] =
true;
299 colCover[colOfStarInRow] =
false;
314template <
typename dataType>
316 const int start = rowLimitsMinus[row];
317 const int end = rowLimitsPlus[row];
318 for(
int c = start; c <
end; ++c)
324template <
typename dataType>
326 auto *C = AssignmentSolver<dataType>::getCostMatrixPointer();
331 while(createdZeros.size() > 0) {
332 const std::pair<int, int> zero = createdZeros.back();
333 const int f = zero.first;
334 const int s = zero.second;
335 createdZeros.pop_back();
336 if(!rowCover[f] && !colCover[s]) {
343 for(
int r = 0; r < this->rowSize; ++r) {
344 const int start = rowLimitsMinus[r];
345 const int end = rowLimitsPlus[r];
349 for(
int c = start; c <
end; ++c) {
352 if((*C)[r][c] == (dataType)0) {
360 this->
printMsg(
"Zero not found.", debug::Priority::DETAIL);
373template <
typename dataType>
381 path[pathCount - 1][0] = pathRow0;
382 path[pathCount - 1][1] = pathCol0;
386 r = findStarInCol(path[pathCount - 1][1]);
392 path[pathCount - 1][0] = r;
393 path[pathCount - 1][1] = path[pathCount - 2][1];
395 c = findPrimeInRow(path[pathCount - 1][0]);
397 this->printWrn(
"Did not find an expected prime.");
400 path[pathCount - 1][0] = path[pathCount - 2][0];
401 path[pathCount - 1][1] = c;
407 for(
int p = 0; p < pathCount; ++p) {
408 if(M[path[p][0]][path[p][1]] == 1)
409 M[path[p][0]][path[p][1]] = 0;
411 M[path[p][0]][path[p][1]] = 1;
415 for(
int r = 0; r < this->rowSize; ++r)
417 for(
int c = 0; c < this->colSize - 1; ++c)
421 for(
int r = 0; r < this->rowSize; ++r) {
422 const int start = rowLimitsMinus[r];
423 const int end = rowLimitsPlus[r];
424 for(
int c = start; c <
end; ++c)
433template <
typename dataType>
435 const int start = colLimitsMinus[col];
436 const int end = colLimitsPlus[col];
437 for(
int r = start; r <
end; ++r)
441 if(M[this->rowSize - 1][col] == 1)
442 return (this->rowSize - 1);
446template <
typename dataType>
448 const int start = rowLimitsMinus[row];
449 const int end = rowLimitsPlus[row];
450 for(
int c = start; c <
end; ++c)
459template <
typename dataType>
462 auto *C = AssignmentSolver<dataType>::getCostMatrixPointer();
464 dataType minVal = std::numeric_limits<dataType>::max();
467 for(
int r = 0; r < this->rowSize; ++r) {
471 const int start = rowLimitsMinus[r];
472 const int end = rowLimitsPlus[r];
474 for(
int c = start; c <
end; ++c) {
477 if((*C)[r][c] < minVal)
482 createdZeros.clear();
485 for(
int r = 0; r < this->rowSize; ++r) {
487 const int start = rowLimitsMinus[r];
488 const int end = rowLimitsPlus[r];
490 for(
int c = start; c <
end; ++c) {
492 (*C)[r][c] = (*C)[r][c] + minVal;
494 (*C)[r][c] = (*C)[r][c] - minVal;
495 if(isZero((*C)[r][c])) {
496 createdZeros.emplace_back(r, c);
506template <
typename dataType>
508 this->
printMsg(
"Step 7 over.", debug::Priority::DETAIL);
512template <
typename dataType>
514 std::vector<MatchingType> &matchings,
515 const std::vector<std::vector<dataType>> &C) {
516 const int nbC = this->colSize;
517 const int nbR = this->rowSize;
521 for(
int r = 0; r < nbR; ++r)
522 for(
int c = 0; c < nbC; ++c)
524 matchings.emplace_back(r, c, C[r][c]);
531 for(
int r = 0; r < nbR - 1; ++r) {
534 matchings.emplace_back(r, nbC - 1, C[r][nbC - 1]);
545template <
typename dataType>
547 const std::vector<std::vector<dataType>> &C) {
548 const int nbC = this->colSize;
549 const int nbR = this->rowSize;
553 for(
int r = 0; r < nbR; ++r)
554 for(
int c = 0; c < nbC; ++c)
559 this->
printMsg(
"Total cost: " + std::to_string(total));
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
int run(std::vector< MatchingType > &matchings) override
T end(std::pair< T, T > &p)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)