0
3
0
| ... | ... |
@@ -141,29 +141,28 @@ |
| 141 | 141 |
typedef typename TR::Path Path; |
| 142 | 142 |
|
| 143 | 143 |
/// The \ref HartmannOrlinDefaultTraits "traits class" of the algorithm |
| 144 | 144 |
typedef TR Traits; |
| 145 | 145 |
|
| 146 | 146 |
private: |
| 147 | 147 |
|
| 148 | 148 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 149 | 149 |
|
| 150 | 150 |
// Data sturcture for path data |
| 151 | 151 |
struct PathData |
| 152 | 152 |
{
|
| 153 |
bool found; |
|
| 154 | 153 |
LargeValue dist; |
| 155 | 154 |
Arc pred; |
| 156 |
PathData(bool f = false, LargeValue d = 0, Arc p = INVALID) : |
|
| 157 |
found(f), dist(d), pred(p) {}
|
|
| 155 |
PathData(LargeValue d, Arc p = INVALID) : |
|
| 156 |
dist(d), pred(p) {}
|
|
| 158 | 157 |
}; |
| 159 | 158 |
|
| 160 | 159 |
typedef typename Digraph::template NodeMap<std::vector<PathData> > |
| 161 | 160 |
PathDataNodeMap; |
| 162 | 161 |
|
| 163 | 162 |
private: |
| 164 | 163 |
|
| 165 | 164 |
// The digraph the algorithm runs on |
| 166 | 165 |
const Digraph &_gr; |
| 167 | 166 |
// The length of the arcs |
| 168 | 167 |
const LengthMap &_length; |
| 169 | 168 |
|
| ... | ... |
@@ -182,24 +181,27 @@ |
| 182 | 181 |
int _curr_level, _best_level; |
| 183 | 182 |
|
| 184 | 183 |
Path *_cycle_path; |
| 185 | 184 |
bool _local_path; |
| 186 | 185 |
|
| 187 | 186 |
// Node map for storing path data |
| 188 | 187 |
PathDataNodeMap _data; |
| 189 | 188 |
// The processed nodes in the last round |
| 190 | 189 |
std::vector<Node> _process; |
| 191 | 190 |
|
| 192 | 191 |
Tolerance _tolerance; |
| 193 | 192 |
|
| 193 |
// Infinite constant |
|
| 194 |
const LargeValue INF; |
|
| 195 |
|
|
| 194 | 196 |
public: |
| 195 | 197 |
|
| 196 | 198 |
/// \name Named Template Parameters |
| 197 | 199 |
/// @{
|
| 198 | 200 |
|
| 199 | 201 |
template <typename T> |
| 200 | 202 |
struct SetLargeValueTraits : public Traits {
|
| 201 | 203 |
typedef T LargeValue; |
| 202 | 204 |
typedef lemon::Tolerance<T> Tolerance; |
| 203 | 205 |
}; |
| 204 | 206 |
|
| 205 | 207 |
/// \brief \ref named-templ-param "Named parameter" for setting |
| ... | ... |
@@ -236,25 +238,28 @@ |
| 236 | 238 |
public: |
| 237 | 239 |
|
| 238 | 240 |
/// \brief Constructor. |
| 239 | 241 |
/// |
| 240 | 242 |
/// The constructor of the class. |
| 241 | 243 |
/// |
| 242 | 244 |
/// \param digraph The digraph the algorithm runs on. |
| 243 | 245 |
/// \param length The lengths (costs) of the arcs. |
| 244 | 246 |
HartmannOrlin( const Digraph &digraph, |
| 245 | 247 |
const LengthMap &length ) : |
| 246 | 248 |
_gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph), |
| 247 | 249 |
_best_found(false), _best_length(0), _best_size(1), |
| 248 |
_cycle_path(NULL), _local_path(false), _data(digraph) |
|
| 250 |
_cycle_path(NULL), _local_path(false), _data(digraph), |
|
| 251 |
INF(std::numeric_limits<LargeValue>::has_infinity ? |
|
| 252 |
std::numeric_limits<LargeValue>::infinity() : |
|
| 253 |
std::numeric_limits<LargeValue>::max()) |
|
| 249 | 254 |
{}
|
| 250 | 255 |
|
| 251 | 256 |
/// Destructor. |
| 252 | 257 |
~HartmannOrlin() {
|
| 253 | 258 |
if (_local_path) delete _cycle_path; |
| 254 | 259 |
} |
| 255 | 260 |
|
| 256 | 261 |
/// \brief Set the path structure for storing the found cycle. |
| 257 | 262 |
/// |
| 258 | 263 |
/// This function sets an external path structure for storing the |
| 259 | 264 |
/// found cycle. |
| 260 | 265 |
/// |
| ... | ... |
@@ -463,35 +468,35 @@ |
| 463 | 468 |
} |
| 464 | 469 |
} |
| 465 | 470 |
} |
| 466 | 471 |
|
| 467 | 472 |
// Initialize path data for the current component |
| 468 | 473 |
bool initComponent(int comp) {
|
| 469 | 474 |
_nodes = &(_comp_nodes[comp]); |
| 470 | 475 |
int n = _nodes->size(); |
| 471 | 476 |
if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
|
| 472 | 477 |
return false; |
| 473 | 478 |
} |
| 474 | 479 |
for (int i = 0; i < n; ++i) {
|
| 475 |
_data[(*_nodes)[i]].resize(n + 1); |
|
| 480 |
_data[(*_nodes)[i]].resize(n + 1, PathData(INF)); |
|
| 476 | 481 |
} |
| 477 | 482 |
return true; |
| 478 | 483 |
} |
| 479 | 484 |
|
| 480 | 485 |
// Process all rounds of computing path data for the current component. |
| 481 | 486 |
// _data[v][k] is the length of a shortest directed walk from the root |
| 482 | 487 |
// node to node v containing exactly k arcs. |
| 483 | 488 |
void processRounds() {
|
| 484 | 489 |
Node start = (*_nodes)[0]; |
| 485 |
_data[start][0] = PathData( |
|
| 490 |
_data[start][0] = PathData(0); |
|
| 486 | 491 |
_process.clear(); |
| 487 | 492 |
_process.push_back(start); |
| 488 | 493 |
|
| 489 | 494 |
int k, n = _nodes->size(); |
| 490 | 495 |
int next_check = 4; |
| 491 | 496 |
bool terminate = false; |
| 492 | 497 |
for (k = 1; k <= n && int(_process.size()) < n && !terminate; ++k) {
|
| 493 | 498 |
processNextBuildRound(k); |
| 494 | 499 |
if (k == next_check || k == n) {
|
| 495 | 500 |
terminate = checkTermination(k); |
| 496 | 501 |
next_check = next_check * 3 / 2; |
| 497 | 502 |
} |
| ... | ... |
@@ -508,98 +513,95 @@ |
| 508 | 513 |
// Process one round and rebuild _process |
| 509 | 514 |
void processNextBuildRound(int k) {
|
| 510 | 515 |
std::vector<Node> next; |
| 511 | 516 |
Node u, v; |
| 512 | 517 |
Arc e; |
| 513 | 518 |
LargeValue d; |
| 514 | 519 |
for (int i = 0; i < int(_process.size()); ++i) {
|
| 515 | 520 |
u = _process[i]; |
| 516 | 521 |
for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
|
| 517 | 522 |
e = _out_arcs[u][j]; |
| 518 | 523 |
v = _gr.target(e); |
| 519 | 524 |
d = _data[u][k-1].dist + _length[e]; |
| 520 |
if (!_data[v][k].found) {
|
|
| 521 |
next.push_back(v); |
|
| 522 |
_data[v][k] = PathData(true, _data[u][k-1].dist + _length[e], e); |
|
| 523 |
} |
|
| 524 |
else if (_tolerance.less(d, _data[v][k].dist)) {
|
|
| 525 |
_data[v][k] = PathData(true, d, e); |
|
| 525 |
if (_tolerance.less(d, _data[v][k].dist)) {
|
|
| 526 |
if (_data[v][k].dist == INF) next.push_back(v); |
|
| 527 |
_data[v][k] = PathData(d, e); |
|
| 526 | 528 |
} |
| 527 | 529 |
} |
| 528 | 530 |
} |
| 529 | 531 |
_process.swap(next); |
| 530 | 532 |
} |
| 531 | 533 |
|
| 532 | 534 |
// Process one round using _nodes instead of _process |
| 533 | 535 |
void processNextFullRound(int k) {
|
| 534 | 536 |
Node u, v; |
| 535 | 537 |
Arc e; |
| 536 | 538 |
LargeValue d; |
| 537 | 539 |
for (int i = 0; i < int(_nodes->size()); ++i) {
|
| 538 | 540 |
u = (*_nodes)[i]; |
| 539 | 541 |
for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
|
| 540 | 542 |
e = _out_arcs[u][j]; |
| 541 | 543 |
v = _gr.target(e); |
| 542 | 544 |
d = _data[u][k-1].dist + _length[e]; |
| 543 |
if (!_data[v][k].found || _tolerance.less(d, _data[v][k].dist)) {
|
|
| 544 |
_data[v][k] = PathData(true, d, e); |
|
| 545 |
if (_tolerance.less(d, _data[v][k].dist)) {
|
|
| 546 |
_data[v][k] = PathData(d, e); |
|
| 545 | 547 |
} |
| 546 | 548 |
} |
| 547 | 549 |
} |
| 548 | 550 |
} |
| 549 | 551 |
|
| 550 | 552 |
// Check early termination |
| 551 | 553 |
bool checkTermination(int k) {
|
| 552 | 554 |
typedef std::pair<int, int> Pair; |
| 553 | 555 |
typename GR::template NodeMap<Pair> level(_gr, Pair(-1, 0)); |
| 554 | 556 |
typename GR::template NodeMap<LargeValue> pi(_gr); |
| 555 | 557 |
int n = _nodes->size(); |
| 556 | 558 |
LargeValue length; |
| 557 | 559 |
int size; |
| 558 | 560 |
Node u; |
| 559 | 561 |
|
| 560 | 562 |
// Search for cycles that are already found |
| 561 | 563 |
_curr_found = false; |
| 562 | 564 |
for (int i = 0; i < n; ++i) {
|
| 563 | 565 |
u = (*_nodes)[i]; |
| 564 |
if ( |
|
| 566 |
if (_data[u][k].dist == INF) continue; |
|
| 565 | 567 |
for (int j = k; j >= 0; --j) {
|
| 566 | 568 |
if (level[u].first == i && level[u].second > 0) {
|
| 567 | 569 |
// A cycle is found |
| 568 | 570 |
length = _data[u][level[u].second].dist - _data[u][j].dist; |
| 569 | 571 |
size = level[u].second - j; |
| 570 | 572 |
if (!_curr_found || length * _curr_size < _curr_length * size) {
|
| 571 | 573 |
_curr_length = length; |
| 572 | 574 |
_curr_size = size; |
| 573 | 575 |
_curr_node = u; |
| 574 | 576 |
_curr_level = level[u].second; |
| 575 | 577 |
_curr_found = true; |
| 576 | 578 |
} |
| 577 | 579 |
} |
| 578 | 580 |
level[u] = Pair(i, j); |
| 579 | 581 |
u = _gr.source(_data[u][j].pred); |
| 580 | 582 |
} |
| 581 | 583 |
} |
| 582 | 584 |
|
| 583 | 585 |
// If at least one cycle is found, check the optimality condition |
| 584 | 586 |
LargeValue d; |
| 585 | 587 |
if (_curr_found && k < n) {
|
| 586 | 588 |
// Find node potentials |
| 587 | 589 |
for (int i = 0; i < n; ++i) {
|
| 588 | 590 |
u = (*_nodes)[i]; |
| 589 |
pi[u] = |
|
| 591 |
pi[u] = INF; |
|
| 590 | 592 |
for (int j = 0; j <= k; ++j) {
|
| 591 |
d = _data[u][j].dist * _curr_size - j * _curr_length; |
|
| 592 |
if (_data[u][j].found && _tolerance.less(d, pi[u])) {
|
|
| 593 |
|
|
| 593 |
if (_data[u][j].dist < INF) {
|
|
| 594 |
d = _data[u][j].dist * _curr_size - j * _curr_length; |
|
| 595 |
if (_tolerance.less(d, pi[u])) pi[u] = d; |
|
| 594 | 596 |
} |
| 595 | 597 |
} |
| 596 | 598 |
} |
| 597 | 599 |
|
| 598 | 600 |
// Check the optimality condition for all arcs |
| 599 | 601 |
bool done = true; |
| 600 | 602 |
for (ArcIt a(_gr); a != INVALID; ++a) {
|
| 601 | 603 |
if (_tolerance.less(_length[a] * _curr_size - _curr_length, |
| 602 | 604 |
pi[_gr.target(a)] - pi[_gr.source(a)]) ) {
|
| 603 | 605 |
done = false; |
| 604 | 606 |
break; |
| 605 | 607 |
} |
| ... | ... |
@@ -169,24 +169,27 @@ |
| 169 | 169 |
int _comp_num; |
| 170 | 170 |
typename Digraph::template NodeMap<int> _comp; |
| 171 | 171 |
std::vector<std::vector<Node> > _comp_nodes; |
| 172 | 172 |
std::vector<Node>* _nodes; |
| 173 | 173 |
typename Digraph::template NodeMap<std::vector<Arc> > _in_arcs; |
| 174 | 174 |
|
| 175 | 175 |
// Queue used for BFS search |
| 176 | 176 |
std::vector<Node> _queue; |
| 177 | 177 |
int _qfront, _qback; |
| 178 | 178 |
|
| 179 | 179 |
Tolerance _tolerance; |
| 180 | 180 |
|
| 181 |
// Infinite constant |
|
| 182 |
const LargeValue INF; |
|
| 183 |
|
|
| 181 | 184 |
public: |
| 182 | 185 |
|
| 183 | 186 |
/// \name Named Template Parameters |
| 184 | 187 |
/// @{
|
| 185 | 188 |
|
| 186 | 189 |
template <typename T> |
| 187 | 190 |
struct SetLargeValueTraits : public Traits {
|
| 188 | 191 |
typedef T LargeValue; |
| 189 | 192 |
typedef lemon::Tolerance<T> Tolerance; |
| 190 | 193 |
}; |
| 191 | 194 |
|
| 192 | 195 |
/// \brief \ref named-templ-param "Named parameter" for setting |
| ... | ... |
@@ -221,27 +224,31 @@ |
| 221 | 224 |
/// @} |
| 222 | 225 |
|
| 223 | 226 |
public: |
| 224 | 227 |
|
| 225 | 228 |
/// \brief Constructor. |
| 226 | 229 |
/// |
| 227 | 230 |
/// The constructor of the class. |
| 228 | 231 |
/// |
| 229 | 232 |
/// \param digraph The digraph the algorithm runs on. |
| 230 | 233 |
/// \param length The lengths (costs) of the arcs. |
| 231 | 234 |
Howard( const Digraph &digraph, |
| 232 | 235 |
const LengthMap &length ) : |
| 233 |
_gr(digraph), _length(length), |
|
| 236 |
_gr(digraph), _length(length), _best_found(false), |
|
| 237 |
_best_length(0), _best_size(1), _cycle_path(NULL), _local_path(false), |
|
| 234 | 238 |
_policy(digraph), _reached(digraph), _level(digraph), _dist(digraph), |
| 235 |
_comp(digraph), _in_arcs(digraph) |
|
| 239 |
_comp(digraph), _in_arcs(digraph), |
|
| 240 |
INF(std::numeric_limits<LargeValue>::has_infinity ? |
|
| 241 |
std::numeric_limits<LargeValue>::infinity() : |
|
| 242 |
std::numeric_limits<LargeValue>::max()) |
|
| 236 | 243 |
{}
|
| 237 | 244 |
|
| 238 | 245 |
/// Destructor. |
| 239 | 246 |
~Howard() {
|
| 240 | 247 |
if (_local_path) delete _cycle_path; |
| 241 | 248 |
} |
| 242 | 249 |
|
| 243 | 250 |
/// \brief Set the path structure for storing the found cycle. |
| 244 | 251 |
/// |
| 245 | 252 |
/// This function sets an external path structure for storing the |
| 246 | 253 |
/// found cycle. |
| 247 | 254 |
/// |
| ... | ... |
@@ -298,25 +305,25 @@ |
| 298 | 305 |
init(); |
| 299 | 306 |
findComponents(); |
| 300 | 307 |
|
| 301 | 308 |
// Find the minimum cycle mean in the components |
| 302 | 309 |
for (int comp = 0; comp < _comp_num; ++comp) {
|
| 303 | 310 |
// Find the minimum mean cycle in the current component |
| 304 | 311 |
if (!buildPolicyGraph(comp)) continue; |
| 305 | 312 |
while (true) {
|
| 306 | 313 |
findPolicyCycle(); |
| 307 | 314 |
if (!computeNodeDistances()) break; |
| 308 | 315 |
} |
| 309 | 316 |
// Update the best cycle (global minimum mean cycle) |
| 310 |
if ( !_best_found || |
|
| 317 |
if ( _curr_found && (!_best_found || |
|
| 311 | 318 |
_curr_length * _best_size < _best_length * _curr_size) ) {
|
| 312 | 319 |
_best_found = true; |
| 313 | 320 |
_best_length = _curr_length; |
| 314 | 321 |
_best_size = _curr_size; |
| 315 | 322 |
_best_node = _curr_node; |
| 316 | 323 |
} |
| 317 | 324 |
} |
| 318 | 325 |
return _best_found; |
| 319 | 326 |
} |
| 320 | 327 |
|
| 321 | 328 |
/// \brief Find a minimum mean directed cycle. |
| 322 | 329 |
/// |
| ... | ... |
@@ -437,25 +444,25 @@ |
| 437 | 444 |
} |
| 438 | 445 |
} |
| 439 | 446 |
|
| 440 | 447 |
// Build the policy graph in the given strongly connected component |
| 441 | 448 |
// (the out-degree of every node is 1) |
| 442 | 449 |
bool buildPolicyGraph(int comp) {
|
| 443 | 450 |
_nodes = &(_comp_nodes[comp]); |
| 444 | 451 |
if (_nodes->size() < 1 || |
| 445 | 452 |
(_nodes->size() == 1 && _in_arcs[(*_nodes)[0]].size() == 0)) {
|
| 446 | 453 |
return false; |
| 447 | 454 |
} |
| 448 | 455 |
for (int i = 0; i < int(_nodes->size()); ++i) {
|
| 449 |
_dist[(*_nodes)[i]] = |
|
| 456 |
_dist[(*_nodes)[i]] = INF; |
|
| 450 | 457 |
} |
| 451 | 458 |
Node u, v; |
| 452 | 459 |
Arc e; |
| 453 | 460 |
for (int i = 0; i < int(_nodes->size()); ++i) {
|
| 454 | 461 |
v = (*_nodes)[i]; |
| 455 | 462 |
for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
|
| 456 | 463 |
e = _in_arcs[v][j]; |
| 457 | 464 |
u = _gr.source(e); |
| 458 | 465 |
if (_length[e] < _dist[u]) {
|
| 459 | 466 |
_dist[u] = _length[e]; |
| 460 | 467 |
_policy[u] = e; |
| 461 | 468 |
} |
| ... | ... |
@@ -139,29 +139,28 @@ |
| 139 | 139 |
typedef typename TR::Path Path; |
| 140 | 140 |
|
| 141 | 141 |
/// The \ref KarpDefaultTraits "traits class" of the algorithm |
| 142 | 142 |
typedef TR Traits; |
| 143 | 143 |
|
| 144 | 144 |
private: |
| 145 | 145 |
|
| 146 | 146 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 147 | 147 |
|
| 148 | 148 |
// Data sturcture for path data |
| 149 | 149 |
struct PathData |
| 150 | 150 |
{
|
| 151 |
bool found; |
|
| 152 | 151 |
LargeValue dist; |
| 153 | 152 |
Arc pred; |
| 154 |
PathData(bool f = false, LargeValue d = 0, Arc p = INVALID) : |
|
| 155 |
found(f), dist(d), pred(p) {}
|
|
| 153 |
PathData(LargeValue d, Arc p = INVALID) : |
|
| 154 |
dist(d), pred(p) {}
|
|
| 156 | 155 |
}; |
| 157 | 156 |
|
| 158 | 157 |
typedef typename Digraph::template NodeMap<std::vector<PathData> > |
| 159 | 158 |
PathDataNodeMap; |
| 160 | 159 |
|
| 161 | 160 |
private: |
| 162 | 161 |
|
| 163 | 162 |
// The digraph the algorithm runs on |
| 164 | 163 |
const Digraph &_gr; |
| 165 | 164 |
// The length of the arcs |
| 166 | 165 |
const LengthMap &_length; |
| 167 | 166 |
|
| ... | ... |
@@ -177,24 +176,27 @@ |
| 177 | 176 |
int _cycle_size; |
| 178 | 177 |
Node _cycle_node; |
| 179 | 178 |
|
| 180 | 179 |
Path *_cycle_path; |
| 181 | 180 |
bool _local_path; |
| 182 | 181 |
|
| 183 | 182 |
// Node map for storing path data |
| 184 | 183 |
PathDataNodeMap _data; |
| 185 | 184 |
// The processed nodes in the last round |
| 186 | 185 |
std::vector<Node> _process; |
| 187 | 186 |
|
| 188 | 187 |
Tolerance _tolerance; |
| 188 |
|
|
| 189 |
// Infinite constant |
|
| 190 |
const LargeValue INF; |
|
| 189 | 191 |
|
| 190 | 192 |
public: |
| 191 | 193 |
|
| 192 | 194 |
/// \name Named Template Parameters |
| 193 | 195 |
/// @{
|
| 194 | 196 |
|
| 195 | 197 |
template <typename T> |
| 196 | 198 |
struct SetLargeValueTraits : public Traits {
|
| 197 | 199 |
typedef T LargeValue; |
| 198 | 200 |
typedef lemon::Tolerance<T> Tolerance; |
| 199 | 201 |
}; |
| 200 | 202 |
|
| ... | ... |
@@ -232,25 +234,28 @@ |
| 232 | 234 |
public: |
| 233 | 235 |
|
| 234 | 236 |
/// \brief Constructor. |
| 235 | 237 |
/// |
| 236 | 238 |
/// The constructor of the class. |
| 237 | 239 |
/// |
| 238 | 240 |
/// \param digraph The digraph the algorithm runs on. |
| 239 | 241 |
/// \param length The lengths (costs) of the arcs. |
| 240 | 242 |
Karp( const Digraph &digraph, |
| 241 | 243 |
const LengthMap &length ) : |
| 242 | 244 |
_gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph), |
| 243 | 245 |
_cycle_length(0), _cycle_size(1), _cycle_node(INVALID), |
| 244 |
_cycle_path(NULL), _local_path(false), _data(digraph) |
|
| 246 |
_cycle_path(NULL), _local_path(false), _data(digraph), |
|
| 247 |
INF(std::numeric_limits<LargeValue>::has_infinity ? |
|
| 248 |
std::numeric_limits<LargeValue>::infinity() : |
|
| 249 |
std::numeric_limits<LargeValue>::max()) |
|
| 245 | 250 |
{}
|
| 246 | 251 |
|
| 247 | 252 |
/// Destructor. |
| 248 | 253 |
~Karp() {
|
| 249 | 254 |
if (_local_path) delete _cycle_path; |
| 250 | 255 |
} |
| 251 | 256 |
|
| 252 | 257 |
/// \brief Set the path structure for storing the found cycle. |
| 253 | 258 |
/// |
| 254 | 259 |
/// This function sets an external path structure for storing the |
| 255 | 260 |
/// found cycle. |
| 256 | 261 |
/// |
| ... | ... |
@@ -449,100 +454,97 @@ |
| 449 | 454 |
} |
| 450 | 455 |
} |
| 451 | 456 |
} |
| 452 | 457 |
|
| 453 | 458 |
// Initialize path data for the current component |
| 454 | 459 |
bool initComponent(int comp) {
|
| 455 | 460 |
_nodes = &(_comp_nodes[comp]); |
| 456 | 461 |
int n = _nodes->size(); |
| 457 | 462 |
if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
|
| 458 | 463 |
return false; |
| 459 | 464 |
} |
| 460 | 465 |
for (int i = 0; i < n; ++i) {
|
| 461 |
_data[(*_nodes)[i]].resize(n + 1); |
|
| 466 |
_data[(*_nodes)[i]].resize(n + 1, PathData(INF)); |
|
| 462 | 467 |
} |
| 463 | 468 |
return true; |
| 464 | 469 |
} |
| 465 | 470 |
|
| 466 | 471 |
// Process all rounds of computing path data for the current component. |
| 467 | 472 |
// _data[v][k] is the length of a shortest directed walk from the root |
| 468 | 473 |
// node to node v containing exactly k arcs. |
| 469 | 474 |
void processRounds() {
|
| 470 | 475 |
Node start = (*_nodes)[0]; |
| 471 |
_data[start][0] = PathData( |
|
| 476 |
_data[start][0] = PathData(0); |
|
| 472 | 477 |
_process.clear(); |
| 473 | 478 |
_process.push_back(start); |
| 474 | 479 |
|
| 475 | 480 |
int k, n = _nodes->size(); |
| 476 | 481 |
for (k = 1; k <= n && int(_process.size()) < n; ++k) {
|
| 477 | 482 |
processNextBuildRound(k); |
| 478 | 483 |
} |
| 479 | 484 |
for ( ; k <= n; ++k) {
|
| 480 | 485 |
processNextFullRound(k); |
| 481 | 486 |
} |
| 482 | 487 |
} |
| 483 | 488 |
|
| 484 | 489 |
// Process one round and rebuild _process |
| 485 | 490 |
void processNextBuildRound(int k) {
|
| 486 | 491 |
std::vector<Node> next; |
| 487 | 492 |
Node u, v; |
| 488 | 493 |
Arc e; |
| 489 | 494 |
LargeValue d; |
| 490 | 495 |
for (int i = 0; i < int(_process.size()); ++i) {
|
| 491 | 496 |
u = _process[i]; |
| 492 | 497 |
for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
|
| 493 | 498 |
e = _out_arcs[u][j]; |
| 494 | 499 |
v = _gr.target(e); |
| 495 | 500 |
d = _data[u][k-1].dist + _length[e]; |
| 496 |
if (!_data[v][k].found) {
|
|
| 497 |
next.push_back(v); |
|
| 498 |
_data[v][k] = PathData(true, _data[u][k-1].dist + _length[e], e); |
|
| 499 |
} |
|
| 500 |
else if (_tolerance.less(d, _data[v][k].dist)) {
|
|
| 501 |
_data[v][k] = PathData(true, d, e); |
|
| 501 |
if (_tolerance.less(d, _data[v][k].dist)) {
|
|
| 502 |
if (_data[v][k].dist == INF) next.push_back(v); |
|
| 503 |
_data[v][k] = PathData(d, e); |
|
| 502 | 504 |
} |
| 503 | 505 |
} |
| 504 | 506 |
} |
| 505 | 507 |
_process.swap(next); |
| 506 | 508 |
} |
| 507 | 509 |
|
| 508 | 510 |
// Process one round using _nodes instead of _process |
| 509 | 511 |
void processNextFullRound(int k) {
|
| 510 | 512 |
Node u, v; |
| 511 | 513 |
Arc e; |
| 512 | 514 |
LargeValue d; |
| 513 | 515 |
for (int i = 0; i < int(_nodes->size()); ++i) {
|
| 514 | 516 |
u = (*_nodes)[i]; |
| 515 | 517 |
for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
|
| 516 | 518 |
e = _out_arcs[u][j]; |
| 517 | 519 |
v = _gr.target(e); |
| 518 | 520 |
d = _data[u][k-1].dist + _length[e]; |
| 519 |
if (!_data[v][k].found || _tolerance.less(d, _data[v][k].dist)) {
|
|
| 520 |
_data[v][k] = PathData(true, d, e); |
|
| 521 |
if (_tolerance.less(d, _data[v][k].dist)) {
|
|
| 522 |
_data[v][k] = PathData(d, e); |
|
| 521 | 523 |
} |
| 522 | 524 |
} |
| 523 | 525 |
} |
| 524 | 526 |
} |
| 525 | 527 |
|
| 526 | 528 |
// Update the minimum cycle mean |
| 527 | 529 |
void updateMinMean() {
|
| 528 | 530 |
int n = _nodes->size(); |
| 529 | 531 |
for (int i = 0; i < n; ++i) {
|
| 530 | 532 |
Node u = (*_nodes)[i]; |
| 531 |
if ( |
|
| 533 |
if (_data[u][n].dist == INF) continue; |
|
| 532 | 534 |
LargeValue length, max_length = 0; |
| 533 | 535 |
int size, max_size = 1; |
| 534 | 536 |
bool found_curr = false; |
| 535 | 537 |
for (int k = 0; k < n; ++k) {
|
| 536 |
if ( |
|
| 538 |
if (_data[u][k].dist == INF) continue; |
|
| 537 | 539 |
length = _data[u][n].dist - _data[u][k].dist; |
| 538 | 540 |
size = n - k; |
| 539 | 541 |
if (!found_curr || length * max_size > max_length * size) {
|
| 540 | 542 |
found_curr = true; |
| 541 | 543 |
max_length = length; |
| 542 | 544 |
max_size = size; |
| 543 | 545 |
} |
| 544 | 546 |
} |
| 545 | 547 |
if ( found_curr && (_cycle_node == INVALID || |
| 546 | 548 |
max_length * _cycle_size < _cycle_length * max_size) ) {
|
| 547 | 549 |
_cycle_length = max_length; |
| 548 | 550 |
_cycle_size = max_size; |
0 comments (0 inline)