Changeset 149 in tspsg-svn for trunk/src/tspsolver.cpp
- Timestamp:
- Dec 20, 2010, 9:53:45 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/tspsolver.cpp
r124 r149 35 35 QString CTSPSolver::getVersionId() 36 36 { 37 37 return QString("$Id$"); 38 38 } 39 39 … … 43 43 */ 44 44 CTSPSolver::CTSPSolver(QObject *parent) 45 45 : QObject(parent), cc(true), nCities(0), total(0), root(NULL) {} 46 46 47 47 /*! … … 55 55 void CTSPSolver::cleanup(bool processEvents) 56 56 { 57 58 59 60 57 route.clear(); 58 mayNotBeOptimal = false; 59 if (root != NULL) 60 deleteTree(root, processEvents); 61 61 } 62 62 … … 72 72 QString CTSPSolver::getSortedPath(const QString &city, const QString &separator) const 73 73 { 74 75 74 if (!root || route.isEmpty() || (route.size() != nCities)) 75 return QString(); 76 76 77 77 int i = 0; // We start from City 1 78 78 QStringList path; 79 80 81 82 83 84 85 86 79 path << city.arg(1); 80 while ((i = route[i]) != 0) { 81 path << city.arg(i + 1); 82 } 83 // And finish in City 1, too 84 path << city.arg(1); 85 86 return path.join(separator); 87 87 } 88 88 … … 94 94 int CTSPSolver::getTotalSteps() const 95 95 { 96 96 return total; 97 97 } 98 98 … … 106 106 bool CTSPSolver::isOptimal() const 107 107 { 108 108 return !mayNotBeOptimal; 109 109 } 110 110 … … 121 121 void CTSPSolver::setCleanupOnCancel(bool enable) 122 122 { 123 123 cc = enable; 124 124 } 125 125 … … 134 134 SStep *CTSPSolver::solve(int numCities, const TMatrix &task) 135 135 { 136 137 136 if (numCities < 3) 137 return NULL; 138 138 139 139 QMutexLocker locker(&mutex); 140 141 142 143 144 140 cleanup(); 141 canceled = false; 142 locker.unlock(); 143 144 nCities = numCities; 145 145 146 146 SStep *step = new SStep(); 147 148 149 150 151 147 step->matrix = task; 148 // We need to distinguish the values forbidden by the user 149 // from the values forbidden by the algorithm. 150 // So we replace user's infinities by the maximum available double value. 151 normalize(step->matrix); 152 152 #ifdef DEBUG 153 153 qDebug() << step->matrix; 154 154 #endif // DEBUG 155 156 155 step->price = align(step->matrix); 156 root = step; 157 157 158 158 SStep *left, *right; … … 160 160 bool firstStep = true; 161 161 double check = INFINITY; 162 163 164 165 166 162 total = 0; 163 while (route.size() < nCities) { 164 step->alts = findCandidate(step->matrix,nRow,nCol); 165 166 while (hasSubCycles(nRow,nCol)) { 167 167 #ifdef DEBUG 168 168 qDebug() << "Forbidden: (" << nRow << ";" << nCol << ")"; 169 169 #endif // DEBUG 170 171 172 173 170 step->matrix[nRow][nCol] = INFINITY; 171 step->price += align(step->matrix); 172 step->alts = findCandidate(step->matrix,nRow,nCol); 173 } 174 174 175 175 #ifdef DEBUG 176 177 178 176 qDebug() /*<< step->matrix*/ << "Selected: (" << nRow << ";" << nCol << ")"; 177 qDebug() << "Alternate:" << step->alts; 178 qDebug() << "Step price:" << step->price << endl; 179 179 #endif // DEBUG 180 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 181 locker.relock(); 182 if ((nRow == -1) || (nCol == -1) || canceled) { 183 if (canceled && cc) 184 cleanup(); 185 return NULL; 186 } 187 locker.unlock(); 188 189 // Route with (nRow,nCol) path 190 right = new SStep(); 191 right->pNode = step; 192 right->matrix = step->matrix; 193 for (int k = 0; k < nCities; k++) { 194 if (k != nCol) 195 right->matrix[nRow][k] = INFINITY; 196 if (k != nRow) 197 right->matrix[k][nCol] = INFINITY; 198 } 199 right->price = step->price + align(right->matrix); 200 // Forbid the selected route to exclude its reuse in next steps. 201 right->matrix[nCol][nRow] = INFINITY; 202 right->matrix[nRow][nCol] = INFINITY; 203 204 // Route without (nRow,nCol) path 205 left = new SStep(); 206 left->pNode = step; 207 left->matrix = step->matrix; 208 left->matrix[nRow][nCol] = INFINITY; 209 left->price = step->price + align(left->matrix); 210 211 step->candidate.nRow = nRow; 212 step->candidate.nCol = nCol; 213 step->plNode = left; 214 step->prNode = right; 215 216 // This matrix is not used anymore. Restoring infinities back. 217 denormalize(step->matrix); 218 219 if (right->price <= left->price) { 220 // Route with (nRow,nCol) path is cheaper 221 step->next = SStep::RightBranch; 222 step = right; 223 route[nRow] = nCol; 224 emit routePartFound(route.size()); 225 if (firstStep) { 226 check = left->price; 227 firstStep = false; 228 } 229 } else { 230 // Route without (nRow,nCol) path is cheaper 231 step->next = SStep::LeftBranch; 232 step = left; 233 QCoreApplication::processEvents(); 234 if (firstStep) { 235 check = right->price; 236 firstStep = false; 237 } 238 } 239 total++; 240 } 241 242 mayNotBeOptimal = (check < step->price); 243 244 return root; 245 245 } 246 246 … … 252 252 { 253 253 QMutexLocker locker(&mutex); 254 254 return canceled; 255 255 } 256 256 … … 261 261 { 262 262 QMutexLocker locker(&mutex); 263 263 canceled = true; 264 264 } 265 265 266 266 CTSPSolver::~CTSPSolver() 267 267 { 268 269 268 if (root != NULL) 269 deleteTree(root); 270 270 } 271 271 … … 276 276 double r = 0; 277 277 double min; 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 278 for (int k = 0; k < nCities; k++) { 279 min = findMinInRow(k,matrix); 280 if (min > 0) { 281 r += min; 282 if (min < MAX_DOUBLE) 283 subRow(matrix,k,min); 284 } 285 } 286 for (int k = 0; k < nCities; k++) { 287 min = findMinInCol(k,matrix); 288 if (min > 0) { 289 r += min; 290 if (min < MAX_DOUBLE) 291 subCol(matrix,k,min); 292 } 293 } 294 return (r != MAX_DOUBLE) ? r : INFINITY; 295 295 } 296 296 297 297 void CTSPSolver::deleteTree(SStep *&root, bool processEvents) 298 298 { 299 300 299 if (root == NULL) 300 return; 301 301 SStep *step = root; 302 302 SStep *parent; 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 303 forever { 304 if (processEvents) 305 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); 306 if (step->plNode != NULL) { 307 // We have left child node - going inside it 308 step = step->plNode; 309 step->pNode->plNode = NULL; 310 continue; 311 } else if (step->prNode != NULL) { 312 // We have right child node - going inside it 313 step = step->prNode; 314 step->pNode->prNode = NULL; 315 continue; 316 } else { 317 // We have no child nodes. Deleting the current one. 318 parent = step->pNode; 319 delete step; 320 if (parent != NULL) { 321 // Going back to the parent node. 322 step = parent; 323 } else { 324 // We came back to the root node. Finishing. 325 root = NULL; 326 break; 327 } 328 } 329 } 330 330 } 331 331 332 332 void CTSPSolver::denormalize(TMatrix &matrix) const 333 333 { 334 335 336 337 334 for (int r = 0; r < nCities; r++) 335 for (int c = 0; c < nCities; c++) 336 if ((r != c) && (matrix.at(r).at(c) == MAX_DOUBLE)) 337 matrix[r][c] = INFINITY; 338 338 } 339 339 340 340 QList<SStep::SCandidate> CTSPSolver::findCandidate(const TMatrix &matrix, int &nRow, int &nCol) const 341 341 { 342 343 342 nRow = -1; 343 nCol = -1; 344 344 QList<SStep::SCandidate> alts; 345 345 SStep::SCandidate cand; 346 346 double h = -1; 347 347 double sum; 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 348 for (int r = 0; r < nCities; r++) 349 for (int c = 0; c < nCities; c++) 350 if (matrix.at(r).at(c) == 0) { 351 sum = findMinInRow(r,matrix,c) + findMinInCol(c,matrix,r); 352 if (sum > h) { 353 h = sum; 354 nRow = r; 355 nCol = c; 356 alts.clear(); 357 } else if ((sum == h) && !hasSubCycles(r,c)) { 358 cand.nRow = r; 359 cand.nCol = c; 360 alts.append(cand); 361 } 362 } 363 return alts; 364 364 } 365 365 … … 367 367 { 368 368 double min = INFINITY; 369 370 371 372 369 for (int k = 0; k < nCities; k++) 370 if ((k != exr) && (min > matrix.at(k).at(nCol))) 371 min = matrix.at(k).at(nCol); 372 return (min == INFINITY) ? 0 : min; 373 373 } 374 374 … … 376 376 { 377 377 double min = INFINITY; 378 379 380 381 382 378 for (int k = 0; k < nCities; k++) { 379 if (((k != exc)) && (min > matrix.at(nRow).at(k))) 380 min = matrix.at(nRow).at(k); 381 } 382 return (min == INFINITY) ? 0 : min; 383 383 } 384 384 385 385 bool CTSPSolver::hasSubCycles(int nRow, int nCol) const 386 386 { 387 388 387 if ((nRow < 0) || (nCol < 0) || route.isEmpty() || !(route.size() < nCities - 1) || !route.contains(nCol)) 388 return false; 389 389 int i = nCol; 390 391 392 393 394 395 396 390 forever { 391 if ((i = route.value(i)) == nRow) 392 return true; 393 if (!route.contains(i)) 394 return false; 395 } 396 return false; 397 397 } 398 398 399 399 void CTSPSolver::normalize(TMatrix &matrix) const 400 400 { 401 402 403 404 401 for (int r = 0; r < nCities; r++) 402 for (int c = 0; c < nCities; c++) 403 if ((r != c) && (matrix.at(r).at(c) == INFINITY)) 404 matrix[r][c] = MAX_DOUBLE; 405 405 } 406 406 407 407 void CTSPSolver::subCol(TMatrix &matrix, int nCol, double val) 408 408 { 409 410 411 409 for (int k = 0; k < nCities; k++) 410 if (k != nCol) 411 matrix[k][nCol] -= val; 412 412 } 413 413 414 414 void CTSPSolver::subRow(TMatrix &matrix, int nRow, double val) 415 415 { 416 417 418 416 for (int k = 0; k < nCities; k++) 417 if (k != nRow) 418 matrix[nRow][k] -= val; 419 419 } 420 420 … … 424 424 QDebug operator<<(QDebug dbg, const TSPSolver::TMatrix &matrix) 425 425 { 426 427 428 429 430 431 426 for (int r = 0; r < matrix.count(); r++) { 427 for (int c = 0; c < matrix.at(r).count(); c++) 428 dbg.space() << QString::number(matrix.at(r).at(c)).leftJustified(5); 429 dbg << endl; 430 } 431 return dbg; 432 432 } 433 433 434 434 QDebug operator<<(QDebug dbg, const TSPSolver::SStep::SCandidate &cand) 435 435 { 436 437 436 dbg.nospace() << "(" << cand.nRow << ";" << cand.nCol << ")"; 437 return dbg; 438 438 } 439 439 #endif // DEBUG
Note: See TracChangeset
for help on using the changeset viewer.