The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

external: Add Hungarian graph algorithm

authored by

Pete Black and committed by
Jakob Bornecrantz
0d07c2c3 af540f5e

+469
+4
src/external/CMakeLists.txt
··· 21 21 add_library(xrt-external-glad INTERFACE) 22 22 target_include_directories(xrt-external-glad INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/glad/include) 23 23 24 + # Hungarian graph algorithm 25 + add_library(xrt-external-hungarian INTERFACE) 26 + target_include_directories(xrt-external-hungarian INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/hungarian) 27 + 24 28 # OpenXR 25 29 add_library(xrt-external-openxr INTERFACE) 26 30 target_include_directories(xrt-external-openxr INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/openxr_includes)
+434
src/external/hungarian/Hungarian.hpp
··· 1 + /////////////////////////////////////////////////////////////////////////////// 2 + // Hungarian.h: Header file for Class HungarianAlgorithm. 3 + // 4 + // This is a C++ wrapper with slight modification of a hungarian algorithm implementation by Markus Buehren. 5 + // The original implementation is a few mex-functions for use in MATLAB, found here: 6 + // http://www.mathworks.com/matlabcentral/fileexchange/6543-functions-for-the-rectangular-assignment-problem 7 + // 8 + // Both this code and the orignal code are published under the BSD license. 9 + // by Cong Ma, 2016 10 + // 11 + 12 + #ifndef HUNGARIAN_H 13 + #define HUNGARIAN_H 14 + 15 + #include <iostream> 16 + #include <vector> 17 + 18 + using namespace std; 19 + 20 + 21 + class HungarianAlgorithm 22 + { 23 + public: 24 + HungarianAlgorithm(); 25 + ~HungarianAlgorithm(); 26 + double Solve(vector <vector<double> >& DistMatrix, vector<int>& Assignment); 27 + 28 + private: 29 + void assignmentoptimal(int *assignment, double *cost, double *distMatrix, int nOfRows, int nOfColumns); 30 + void buildassignmentvector(int *assignment, bool *starMatrix, int nOfRows, int nOfColumns); 31 + void computeassignmentcost(int *assignment, double *cost, double *distMatrix, int nOfRows); 32 + void step2a(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim); 33 + void step2b(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim); 34 + void step3(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim); 35 + void step4(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim, int row, int col); 36 + void step5(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim); 37 + }; 38 + 39 + 40 + #endif/////////////////////////////////////////////////////////////////////////////// 41 + // Hungarian.cpp: Implementation file for Class HungarianAlgorithm. 42 + // 43 + // This is a C++ wrapper with slight modification of a hungarian algorithm implementation by Markus Buehren. 44 + // The original implementation is a few mex-functions for use in MATLAB, found here: 45 + // http://www.mathworks.com/matlabcentral/fileexchange/6543-functions-for-the-rectangular-assignment-problem 46 + // 47 + // Both this code and the orignal code are published under the BSD license. 48 + // by Cong Ma, 2016 49 + // 50 + 51 + #include <stdlib.h> 52 + #include <cfloat> // for DBL_MAX 53 + #include <cmath> // for fabs() 54 + //#include "Hungarian.hpp" 55 + 56 + 57 + HungarianAlgorithm::HungarianAlgorithm(){} 58 + HungarianAlgorithm::~HungarianAlgorithm(){} 59 + 60 + 61 + //********************************************************// 62 + // A single function wrapper for solving assignment problem. 63 + //********************************************************// 64 + double HungarianAlgorithm::Solve(vector <vector<double> >& DistMatrix, vector<int>& Assignment) 65 + { 66 + unsigned int nRows = DistMatrix.size(); 67 + unsigned int nCols = DistMatrix[0].size(); 68 + 69 + double *distMatrixIn = new double[nRows * nCols]; 70 + int *assignment = new int[nRows]; 71 + double cost = 0.0; 72 + 73 + // Fill in the distMatrixIn. Mind the index is "i + nRows * j". 74 + // Here the cost matrix of size MxN is defined as a double precision array of N*M elements. 75 + // In the solving functions matrices are seen to be saved MATLAB-internally in row-order. 76 + // (i.e. the matrix [1 2; 3 4] will be stored as a vector [1 3 2 4], NOT [1 2 3 4]). 77 + for (unsigned int i = 0; i < nRows; i++) 78 + for (unsigned int j = 0; j < nCols; j++) 79 + distMatrixIn[i + nRows * j] = DistMatrix[i][j]; 80 + 81 + // call solving function 82 + assignmentoptimal(assignment, &cost, distMatrixIn, nRows, nCols); 83 + 84 + Assignment.clear(); 85 + for (unsigned int r = 0; r < nRows; r++) 86 + Assignment.push_back(assignment[r]); 87 + 88 + delete[] distMatrixIn; 89 + delete[] assignment; 90 + return cost; 91 + } 92 + 93 + 94 + //********************************************************// 95 + // Solve optimal solution for assignment problem using Munkres algorithm, also known as Hungarian Algorithm. 96 + //********************************************************// 97 + void HungarianAlgorithm::assignmentoptimal(int *assignment, double *cost, double *distMatrixIn, int nOfRows, int nOfColumns) 98 + { 99 + double *distMatrix, *distMatrixTemp, *distMatrixEnd, *columnEnd, value, minValue; 100 + bool *coveredColumns, *coveredRows, *starMatrix, *newStarMatrix, *primeMatrix; 101 + int nOfElements, minDim, row, col; 102 + 103 + /* initialization */ 104 + *cost = 0; 105 + for (row = 0; row<nOfRows; row++) 106 + assignment[row] = -1; 107 + 108 + /* generate working copy of distance Matrix */ 109 + /* check if all matrix elements are positive */ 110 + nOfElements = nOfRows * nOfColumns; 111 + distMatrix = (double *)malloc(nOfElements * sizeof(double)); 112 + distMatrixEnd = distMatrix + nOfElements; 113 + 114 + for (row = 0; row<nOfElements; row++) 115 + { 116 + value = distMatrixIn[row]; 117 + if (value < 0) 118 + cerr << "All matrix elements have to be non-negative." << endl; 119 + distMatrix[row] = value; 120 + } 121 + 122 + 123 + /* memory allocation */ 124 + coveredColumns = (bool *)calloc(nOfColumns, sizeof(bool)); 125 + coveredRows = (bool *)calloc(nOfRows, sizeof(bool)); 126 + starMatrix = (bool *)calloc(nOfElements, sizeof(bool)); 127 + primeMatrix = (bool *)calloc(nOfElements, sizeof(bool)); 128 + newStarMatrix = (bool *)calloc(nOfElements, sizeof(bool)); /* used in step4 */ 129 + 130 + /* preliminary steps */ 131 + if (nOfRows <= nOfColumns) 132 + { 133 + minDim = nOfRows; 134 + 135 + for (row = 0; row<nOfRows; row++) 136 + { 137 + /* find the smallest element in the row */ 138 + distMatrixTemp = distMatrix + row; 139 + minValue = *distMatrixTemp; 140 + distMatrixTemp += nOfRows; 141 + while (distMatrixTemp < distMatrixEnd) 142 + { 143 + value = *distMatrixTemp; 144 + if (value < minValue) 145 + minValue = value; 146 + distMatrixTemp += nOfRows; 147 + } 148 + 149 + /* subtract the smallest element from each element of the row */ 150 + distMatrixTemp = distMatrix + row; 151 + while (distMatrixTemp < distMatrixEnd) 152 + { 153 + *distMatrixTemp -= minValue; 154 + distMatrixTemp += nOfRows; 155 + } 156 + } 157 + 158 + /* Steps 1 and 2a */ 159 + for (row = 0; row<nOfRows; row++) 160 + for (col = 0; col<nOfColumns; col++) 161 + if (fabs(distMatrix[row + nOfRows*col]) < DBL_EPSILON) 162 + if (!coveredColumns[col]) 163 + { 164 + starMatrix[row + nOfRows*col] = true; 165 + coveredColumns[col] = true; 166 + break; 167 + } 168 + } 169 + else /* if(nOfRows > nOfColumns) */ 170 + { 171 + minDim = nOfColumns; 172 + 173 + for (col = 0; col<nOfColumns; col++) 174 + { 175 + /* find the smallest element in the column */ 176 + distMatrixTemp = distMatrix + nOfRows*col; 177 + columnEnd = distMatrixTemp + nOfRows; 178 + 179 + minValue = *distMatrixTemp++; 180 + while (distMatrixTemp < columnEnd) 181 + { 182 + value = *distMatrixTemp++; 183 + if (value < minValue) 184 + minValue = value; 185 + } 186 + 187 + /* subtract the smallest element from each element of the column */ 188 + distMatrixTemp = distMatrix + nOfRows*col; 189 + while (distMatrixTemp < columnEnd) 190 + *distMatrixTemp++ -= minValue; 191 + } 192 + 193 + /* Steps 1 and 2a */ 194 + for (col = 0; col<nOfColumns; col++) 195 + for (row = 0; row<nOfRows; row++) 196 + if (fabs(distMatrix[row + nOfRows*col]) < DBL_EPSILON) 197 + if (!coveredRows[row]) 198 + { 199 + starMatrix[row + nOfRows*col] = true; 200 + coveredColumns[col] = true; 201 + coveredRows[row] = true; 202 + break; 203 + } 204 + for (row = 0; row<nOfRows; row++) 205 + coveredRows[row] = false; 206 + 207 + } 208 + 209 + /* move to step 2b */ 210 + step2b(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim); 211 + 212 + /* compute cost and remove invalid assignments */ 213 + computeassignmentcost(assignment, cost, distMatrixIn, nOfRows); 214 + 215 + /* free allocated memory */ 216 + free(distMatrix); 217 + free(coveredColumns); 218 + free(coveredRows); 219 + free(starMatrix); 220 + free(primeMatrix); 221 + free(newStarMatrix); 222 + 223 + return; 224 + } 225 + 226 + /********************************************************/ 227 + void HungarianAlgorithm::buildassignmentvector(int *assignment, bool *starMatrix, int nOfRows, int nOfColumns) 228 + { 229 + int row, col; 230 + 231 + for (row = 0; row<nOfRows; row++) 232 + for (col = 0; col<nOfColumns; col++) 233 + if (starMatrix[row + nOfRows*col]) 234 + { 235 + #ifdef ONE_INDEXING 236 + assignment[row] = col + 1; /* MATLAB-Indexing */ 237 + #else 238 + assignment[row] = col; 239 + #endif 240 + break; 241 + } 242 + } 243 + 244 + /********************************************************/ 245 + void HungarianAlgorithm::computeassignmentcost(int *assignment, double *cost, double *distMatrix, int nOfRows) 246 + { 247 + int row, col; 248 + 249 + for (row = 0; row<nOfRows; row++) 250 + { 251 + col = assignment[row]; 252 + if (col >= 0) 253 + *cost += distMatrix[row + nOfRows*col]; 254 + } 255 + } 256 + 257 + /********************************************************/ 258 + void HungarianAlgorithm::step2a(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim) 259 + { 260 + bool *starMatrixTemp, *columnEnd; 261 + int col; 262 + 263 + /* cover every column containing a starred zero */ 264 + for (col = 0; col<nOfColumns; col++) 265 + { 266 + starMatrixTemp = starMatrix + nOfRows*col; 267 + columnEnd = starMatrixTemp + nOfRows; 268 + while (starMatrixTemp < columnEnd){ 269 + if (*starMatrixTemp++) 270 + { 271 + coveredColumns[col] = true; 272 + break; 273 + } 274 + } 275 + } 276 + 277 + /* move to step 3 */ 278 + step2b(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim); 279 + } 280 + 281 + /********************************************************/ 282 + void HungarianAlgorithm::step2b(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim) 283 + { 284 + int col, nOfCoveredColumns; 285 + 286 + /* count covered columns */ 287 + nOfCoveredColumns = 0; 288 + for (col = 0; col<nOfColumns; col++) 289 + if (coveredColumns[col]) 290 + nOfCoveredColumns++; 291 + 292 + if (nOfCoveredColumns == minDim) 293 + { 294 + /* algorithm finished */ 295 + buildassignmentvector(assignment, starMatrix, nOfRows, nOfColumns); 296 + } 297 + else 298 + { 299 + /* move to step 3 */ 300 + step3(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim); 301 + } 302 + 303 + } 304 + 305 + /********************************************************/ 306 + void HungarianAlgorithm::step3(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim) 307 + { 308 + bool zerosFound; 309 + int row, col, starCol; 310 + 311 + zerosFound = true; 312 + while (zerosFound) 313 + { 314 + zerosFound = false; 315 + for (col = 0; col<nOfColumns; col++) 316 + if (!coveredColumns[col]) 317 + for (row = 0; row<nOfRows; row++) 318 + if ((!coveredRows[row]) && (fabs(distMatrix[row + nOfRows*col]) < DBL_EPSILON)) 319 + { 320 + /* prime zero */ 321 + primeMatrix[row + nOfRows*col] = true; 322 + 323 + /* find starred zero in current row */ 324 + for (starCol = 0; starCol<nOfColumns; starCol++) 325 + if (starMatrix[row + nOfRows*starCol]) 326 + break; 327 + 328 + if (starCol == nOfColumns) /* no starred zero found */ 329 + { 330 + /* move to step 4 */ 331 + step4(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim, row, col); 332 + return; 333 + } 334 + else 335 + { 336 + coveredRows[row] = true; 337 + coveredColumns[starCol] = false; 338 + zerosFound = true; 339 + break; 340 + } 341 + } 342 + } 343 + 344 + /* move to step 5 */ 345 + step5(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim); 346 + } 347 + 348 + /********************************************************/ 349 + void HungarianAlgorithm::step4(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim, int row, int col) 350 + { 351 + int n, starRow, starCol, primeRow, primeCol; 352 + int nOfElements = nOfRows*nOfColumns; 353 + 354 + /* generate temporary copy of starMatrix */ 355 + for (n = 0; n<nOfElements; n++) 356 + newStarMatrix[n] = starMatrix[n]; 357 + 358 + /* star current zero */ 359 + newStarMatrix[row + nOfRows*col] = true; 360 + 361 + /* find starred zero in current column */ 362 + starCol = col; 363 + for (starRow = 0; starRow<nOfRows; starRow++) 364 + if (starMatrix[starRow + nOfRows*starCol]) 365 + break; 366 + 367 + while (starRow<nOfRows) 368 + { 369 + /* unstar the starred zero */ 370 + newStarMatrix[starRow + nOfRows*starCol] = false; 371 + 372 + /* find primed zero in current row */ 373 + primeRow = starRow; 374 + for (primeCol = 0; primeCol<nOfColumns; primeCol++) 375 + if (primeMatrix[primeRow + nOfRows*primeCol]) 376 + break; 377 + 378 + /* star the primed zero */ 379 + newStarMatrix[primeRow + nOfRows*primeCol] = true; 380 + 381 + /* find starred zero in current column */ 382 + starCol = primeCol; 383 + for (starRow = 0; starRow<nOfRows; starRow++) 384 + if (starMatrix[starRow + nOfRows*starCol]) 385 + break; 386 + } 387 + 388 + /* use temporary copy as new starMatrix */ 389 + /* delete all primes, uncover all rows */ 390 + for (n = 0; n<nOfElements; n++) 391 + { 392 + primeMatrix[n] = false; 393 + starMatrix[n] = newStarMatrix[n]; 394 + } 395 + for (n = 0; n<nOfRows; n++) 396 + coveredRows[n] = false; 397 + 398 + /* move to step 2a */ 399 + step2a(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim); 400 + } 401 + 402 + /********************************************************/ 403 + void HungarianAlgorithm::step5(int *assignment, double *distMatrix, bool *starMatrix, bool *newStarMatrix, bool *primeMatrix, bool *coveredColumns, bool *coveredRows, int nOfRows, int nOfColumns, int minDim) 404 + { 405 + double h, value; 406 + int row, col; 407 + 408 + /* find smallest uncovered element h */ 409 + h = DBL_MAX; 410 + for (row = 0; row<nOfRows; row++) 411 + if (!coveredRows[row]) 412 + for (col = 0; col<nOfColumns; col++) 413 + if (!coveredColumns[col]) 414 + { 415 + value = distMatrix[row + nOfRows*col]; 416 + if (value < h) 417 + h = value; 418 + } 419 + 420 + /* add h to each covered row */ 421 + for (row = 0; row<nOfRows; row++) 422 + if (coveredRows[row]) 423 + for (col = 0; col<nOfColumns; col++) 424 + distMatrix[row + nOfRows*col] += h; 425 + 426 + /* subtract h from each uncovered column */ 427 + for (col = 0; col<nOfColumns; col++) 428 + if (!coveredColumns[col]) 429 + for (row = 0; row<nOfRows; row++) 430 + distMatrix[row + nOfRows*col] -= h; 431 + 432 + /* move to step 3 */ 433 + step3(assignment, distMatrix, starMatrix, newStarMatrix, primeMatrix, coveredColumns, coveredRows, nOfRows, nOfColumns, minDim); 434 + }
+23
src/external/hungarian/LICENSE
··· 1 + Copyright (c) 2016, mcximing 2 + All rights reserved. 3 + 4 + Redistribution and use in source and binary forms, with or without 5 + modification, are permitted provided that the following conditions are met: 6 + 7 + * Redistributions of source code must retain the above copyright notice, this 8 + list of conditions and the following disclaimer. 9 + 10 + * Redistributions in binary form must reproduce the above copyright notice, 11 + this list of conditions and the following disclaimer in the documentation 12 + and/or other materials provided with the distribution. 13 + 14 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+7
src/external/hungarian/README.txt
··· 1 + 2 + Hungarian algorithm, also known as Munkres algorithm or Kuhn-Munkres algorithm, is a method for solving the assignment problem, for example assigning workers to jobs, which goal is to compute the optimal assignment that minimizes the total cost, and the like. 3 + 4 + This is a C++ wrapper with slight modification of a hungarian algorithm implementation by Markus Buehren. 5 + The original code is a few mex-functions for use in MATLAB, found here: 6 + http://www.mathworks.com/matlabcentral/fileexchange/6543-functions-for-the-rectangular-assignment-problem 7 +
+1
src/external/meson.build
··· 4 4 cjson_include = include_directories('cjson') 5 5 flexkalman_include = include_directories('flexkalman') 6 6 glad_include = include_directories('glad/include') 7 + hungarian_include = include_directories('hungarian') 7 8 imgui_include = include_directories('imgui') 8 9 openxr_include = include_directories('openxr_includes')