gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Clarify type names in NetworkSimplex (#353) This patch clarifies the misleading effects of the renamings in [f3bc4e9b5f3a].
0 1 0
default
1 file changed with 11 insertions and 7 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
... ...
@@ -125,337 +125,341 @@
125 125
    /// implementations that significantly affect the running time
126 126
    /// of the algorithm.
127 127
    /// By default, \ref BLOCK_SEARCH "Block Search" is used, which
128 128
    /// proved to be the most efficient and the most robust on various
129 129
    /// test inputs.
130 130
    /// However, another pivot rule can be selected using the \ref run()
131 131
    /// function with the proper parameter.
132 132
    enum PivotRule {
133 133

	
134 134
      /// The \e First \e Eligible pivot rule.
135 135
      /// The next eligible arc is selected in a wraparound fashion
136 136
      /// in every iteration.
137 137
      FIRST_ELIGIBLE,
138 138

	
139 139
      /// The \e Best \e Eligible pivot rule.
140 140
      /// The best eligible arc is selected in every iteration.
141 141
      BEST_ELIGIBLE,
142 142

	
143 143
      /// The \e Block \e Search pivot rule.
144 144
      /// A specified number of arcs are examined in every iteration
145 145
      /// in a wraparound fashion and the best eligible arc is selected
146 146
      /// from this block.
147 147
      BLOCK_SEARCH,
148 148

	
149 149
      /// The \e Candidate \e List pivot rule.
150 150
      /// In a major iteration a candidate list is built from eligible arcs
151 151
      /// in a wraparound fashion and in the following minor iterations
152 152
      /// the best eligible arc is selected from this list.
153 153
      CANDIDATE_LIST,
154 154

	
155 155
      /// The \e Altering \e Candidate \e List pivot rule.
156 156
      /// It is a modified version of the Candidate List method.
157 157
      /// It keeps only the several best eligible arcs from the former
158 158
      /// candidate list and extends this list in every iteration.
159 159
      ALTERING_LIST
160 160
    };
161 161
    
162 162
  private:
163 163

	
164 164
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
165 165

	
166 166
    typedef std::vector<int> IntVector;
167 167
    typedef std::vector<Value> ValueVector;
168 168
    typedef std::vector<Cost> CostVector;
169 169
    typedef std::vector<char> BoolVector;
170 170
    // Note: vector<char> is used instead of vector<bool> for efficiency reasons
171 171

	
172 172
    // State constants for arcs
173
    enum ArcStateEnum {
173
    enum ArcState {
174 174
      STATE_UPPER = -1,
175 175
      STATE_TREE  =  0,
176 176
      STATE_LOWER =  1
177 177
    };
178 178

	
179
    typedef std::vector<signed char> StateVector;
180
    // Note: vector<signed char> is used instead of vector<ArcState> for
181
    // efficiency reasons
182

	
179 183
  private:
180 184

	
181 185
    // Data related to the underlying digraph
182 186
    const GR &_graph;
183 187
    int _node_num;
184 188
    int _arc_num;
185 189
    int _all_arc_num;
186 190
    int _search_arc_num;
187 191

	
188 192
    // Parameters of the problem
189 193
    bool _have_lower;
190 194
    SupplyType _stype;
191 195
    Value _sum_supply;
192 196

	
193 197
    // Data structures for storing the digraph
194 198
    IntNodeMap _node_id;
195 199
    IntArcMap _arc_id;
196 200
    IntVector _source;
197 201
    IntVector _target;
198 202
    bool _arc_mixing;
199 203

	
200 204
    // Node and arc data
201 205
    ValueVector _lower;
202 206
    ValueVector _upper;
203 207
    ValueVector _cap;
204 208
    CostVector _cost;
205 209
    ValueVector _supply;
206 210
    ValueVector _flow;
207 211
    CostVector _pi;
208 212

	
209 213
    // Data for storing the spanning tree structure
210 214
    IntVector _parent;
211 215
    IntVector _pred;
212 216
    IntVector _thread;
213 217
    IntVector _rev_thread;
214 218
    IntVector _succ_num;
215 219
    IntVector _last_succ;
216 220
    IntVector _dirty_revs;
217 221
    BoolVector _forward;
218
    BoolVector _state;
222
    StateVector _state;
219 223
    int _root;
220 224

	
221 225
    // Temporary data used in the current pivot iteration
222 226
    int in_arc, join, u_in, v_in, u_out, v_out;
223 227
    int first, second, right, last;
224 228
    int stem, par_stem, new_stem;
225 229
    Value delta;
226 230
    
227 231
    const Value MAX;
228 232

	
229 233
  public:
230 234
  
231 235
    /// \brief Constant for infinite upper bounds (capacities).
232 236
    ///
233 237
    /// Constant for infinite upper bounds (capacities).
234 238
    /// It is \c std::numeric_limits<Value>::infinity() if available,
235 239
    /// \c std::numeric_limits<Value>::max() otherwise.
236 240
    const Value INF;
237 241

	
238 242
  private:
239 243

	
240 244
    // Implementation of the First Eligible pivot rule
241 245
    class FirstEligiblePivotRule
242 246
    {
243 247
    private:
244 248

	
245 249
      // References to the NetworkSimplex class
246 250
      const IntVector  &_source;
247 251
      const IntVector  &_target;
248 252
      const CostVector &_cost;
249
      const BoolVector &_state;
253
      const StateVector &_state;
250 254
      const CostVector &_pi;
251 255
      int &_in_arc;
252 256
      int _search_arc_num;
253 257

	
254 258
      // Pivot rule data
255 259
      int _next_arc;
256 260

	
257 261
    public:
258 262

	
259 263
      // Constructor
260 264
      FirstEligiblePivotRule(NetworkSimplex &ns) :
261 265
        _source(ns._source), _target(ns._target),
262 266
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
263 267
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
264 268
        _next_arc(0)
265 269
      {}
266 270

	
267 271
      // Find next entering arc
268 272
      bool findEnteringArc() {
269 273
        Cost c;
270 274
        for (int e = _next_arc; e != _search_arc_num; ++e) {
271 275
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
272 276
          if (c < 0) {
273 277
            _in_arc = e;
274 278
            _next_arc = e + 1;
275 279
            return true;
276 280
          }
277 281
        }
278 282
        for (int e = 0; e != _next_arc; ++e) {
279 283
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
280 284
          if (c < 0) {
281 285
            _in_arc = e;
282 286
            _next_arc = e + 1;
283 287
            return true;
284 288
          }
285 289
        }
286 290
        return false;
287 291
      }
288 292

	
289 293
    }; //class FirstEligiblePivotRule
290 294

	
291 295

	
292 296
    // Implementation of the Best Eligible pivot rule
293 297
    class BestEligiblePivotRule
294 298
    {
295 299
    private:
296 300

	
297 301
      // References to the NetworkSimplex class
298 302
      const IntVector  &_source;
299 303
      const IntVector  &_target;
300 304
      const CostVector &_cost;
301
      const BoolVector &_state;
305
      const StateVector &_state;
302 306
      const CostVector &_pi;
303 307
      int &_in_arc;
304 308
      int _search_arc_num;
305 309

	
306 310
    public:
307 311

	
308 312
      // Constructor
309 313
      BestEligiblePivotRule(NetworkSimplex &ns) :
310 314
        _source(ns._source), _target(ns._target),
311 315
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
312 316
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num)
313 317
      {}
314 318

	
315 319
      // Find next entering arc
316 320
      bool findEnteringArc() {
317 321
        Cost c, min = 0;
318 322
        for (int e = 0; e != _search_arc_num; ++e) {
319 323
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
320 324
          if (c < min) {
321 325
            min = c;
322 326
            _in_arc = e;
323 327
          }
324 328
        }
325 329
        return min < 0;
326 330
      }
327 331

	
328 332
    }; //class BestEligiblePivotRule
329 333

	
330 334

	
331 335
    // Implementation of the Block Search pivot rule
332 336
    class BlockSearchPivotRule
333 337
    {
334 338
    private:
335 339

	
336 340
      // References to the NetworkSimplex class
337 341
      const IntVector  &_source;
338 342
      const IntVector  &_target;
339 343
      const CostVector &_cost;
340
      const BoolVector &_state;
344
      const StateVector &_state;
341 345
      const CostVector &_pi;
342 346
      int &_in_arc;
343 347
      int _search_arc_num;
344 348

	
345 349
      // Pivot rule data
346 350
      int _block_size;
347 351
      int _next_arc;
348 352

	
349 353
    public:
350 354

	
351 355
      // Constructor
352 356
      BlockSearchPivotRule(NetworkSimplex &ns) :
353 357
        _source(ns._source), _target(ns._target),
354 358
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
355 359
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
356 360
        _next_arc(0)
357 361
      {
358 362
        // The main parameters of the pivot rule
359 363
        const double BLOCK_SIZE_FACTOR = 1.0;
360 364
        const int MIN_BLOCK_SIZE = 10;
361 365

	
362 366
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
363 367
                                    std::sqrt(double(_search_arc_num))),
364 368
                                MIN_BLOCK_SIZE );
365 369
      }
366 370

	
367 371
      // Find next entering arc
368 372
      bool findEnteringArc() {
369 373
        Cost c, min = 0;
370 374
        int cnt = _block_size;
371 375
        int e;
372 376
        for (e = _next_arc; e != _search_arc_num; ++e) {
373 377
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
374 378
          if (c < min) {
375 379
            min = c;
376 380
            _in_arc = e;
377 381
          }
378 382
          if (--cnt == 0) {
379 383
            if (min < 0) goto search_end;
380 384
            cnt = _block_size;
381 385
          }
382 386
        }
383 387
        for (e = 0; e != _next_arc; ++e) {
384 388
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
385 389
          if (c < min) {
386 390
            min = c;
387 391
            _in_arc = e;
388 392
          }
389 393
          if (--cnt == 0) {
390 394
            if (min < 0) goto search_end;
391 395
            cnt = _block_size;
392 396
          }
393 397
        }
394 398
        if (min >= 0) return false;
395 399

	
396 400
      search_end:
397 401
        _next_arc = e;
398 402
        return true;
399 403
      }
400 404

	
401 405
    }; //class BlockSearchPivotRule
402 406

	
403 407

	
404 408
    // Implementation of the Candidate List pivot rule
405 409
    class CandidateListPivotRule
406 410
    {
407 411
    private:
408 412

	
409 413
      // References to the NetworkSimplex class
410 414
      const IntVector  &_source;
411 415
      const IntVector  &_target;
412 416
      const CostVector &_cost;
413
      const BoolVector &_state;
417
      const StateVector &_state;
414 418
      const CostVector &_pi;
415 419
      int &_in_arc;
416 420
      int _search_arc_num;
417 421

	
418 422
      // Pivot rule data
419 423
      IntVector _candidates;
420 424
      int _list_length, _minor_limit;
421 425
      int _curr_length, _minor_count;
422 426
      int _next_arc;
423 427

	
424 428
    public:
425 429

	
426 430
      /// Constructor
427 431
      CandidateListPivotRule(NetworkSimplex &ns) :
428 432
        _source(ns._source), _target(ns._target),
429 433
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
430 434
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
431 435
        _next_arc(0)
432 436
      {
433 437
        // The main parameters of the pivot rule
434 438
        const double LIST_LENGTH_FACTOR = 0.25;
435 439
        const int MIN_LIST_LENGTH = 10;
436 440
        const double MINOR_LIMIT_FACTOR = 0.1;
437 441
        const int MIN_MINOR_LIMIT = 3;
438 442

	
439 443
        _list_length = std::max( int(LIST_LENGTH_FACTOR *
440 444
                                     std::sqrt(double(_search_arc_num))),
441 445
                                 MIN_LIST_LENGTH );
442 446
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
443 447
                                 MIN_MINOR_LIMIT );
444 448
        _curr_length = _minor_count = 0;
445 449
        _candidates.resize(_list_length);
446 450
      }
447 451

	
448 452
      /// Find next entering arc
449 453
      bool findEnteringArc() {
450 454
        Cost min, c;
451 455
        int e;
452 456
        if (_curr_length > 0 && _minor_count < _minor_limit) {
453 457
          // Minor iteration: select the best eligible arc from the
454 458
          // current candidate list
455 459
          ++_minor_count;
456 460
          min = 0;
457 461
          for (int i = 0; i < _curr_length; ++i) {
458 462
            e = _candidates[i];
459 463
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
460 464
            if (c < min) {
461 465
              min = c;
... ...
@@ -468,97 +472,97 @@
468 472
          if (min < 0) return true;
469 473
        }
470 474

	
471 475
        // Major iteration: build a new candidate list
472 476
        min = 0;
473 477
        _curr_length = 0;
474 478
        for (e = _next_arc; e != _search_arc_num; ++e) {
475 479
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
476 480
          if (c < 0) {
477 481
            _candidates[_curr_length++] = e;
478 482
            if (c < min) {
479 483
              min = c;
480 484
              _in_arc = e;
481 485
            }
482 486
            if (_curr_length == _list_length) goto search_end;
483 487
          }
484 488
        }
485 489
        for (e = 0; e != _next_arc; ++e) {
486 490
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
487 491
          if (c < 0) {
488 492
            _candidates[_curr_length++] = e;
489 493
            if (c < min) {
490 494
              min = c;
491 495
              _in_arc = e;
492 496
            }
493 497
            if (_curr_length == _list_length) goto search_end;
494 498
          }
495 499
        }
496 500
        if (_curr_length == 0) return false;
497 501
      
498 502
      search_end:        
499 503
        _minor_count = 1;
500 504
        _next_arc = e;
501 505
        return true;
502 506
      }
503 507

	
504 508
    }; //class CandidateListPivotRule
505 509

	
506 510

	
507 511
    // Implementation of the Altering Candidate List pivot rule
508 512
    class AlteringListPivotRule
509 513
    {
510 514
    private:
511 515

	
512 516
      // References to the NetworkSimplex class
513 517
      const IntVector  &_source;
514 518
      const IntVector  &_target;
515 519
      const CostVector &_cost;
516
      const BoolVector &_state;
520
      const StateVector &_state;
517 521
      const CostVector &_pi;
518 522
      int &_in_arc;
519 523
      int _search_arc_num;
520 524

	
521 525
      // Pivot rule data
522 526
      int _block_size, _head_length, _curr_length;
523 527
      int _next_arc;
524 528
      IntVector _candidates;
525 529
      CostVector _cand_cost;
526 530

	
527 531
      // Functor class to compare arcs during sort of the candidate list
528 532
      class SortFunc
529 533
      {
530 534
      private:
531 535
        const CostVector &_map;
532 536
      public:
533 537
        SortFunc(const CostVector &map) : _map(map) {}
534 538
        bool operator()(int left, int right) {
535 539
          return _map[left] > _map[right];
536 540
        }
537 541
      };
538 542

	
539 543
      SortFunc _sort_func;
540 544

	
541 545
    public:
542 546

	
543 547
      // Constructor
544 548
      AlteringListPivotRule(NetworkSimplex &ns) :
545 549
        _source(ns._source), _target(ns._target),
546 550
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
547 551
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
548 552
        _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost)
549 553
      {
550 554
        // The main parameters of the pivot rule
551 555
        const double BLOCK_SIZE_FACTOR = 1.0;
552 556
        const int MIN_BLOCK_SIZE = 10;
553 557
        const double HEAD_LENGTH_FACTOR = 0.1;
554 558
        const int MIN_HEAD_LENGTH = 3;
555 559

	
556 560
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
557 561
                                    std::sqrt(double(_search_arc_num))),
558 562
                                MIN_BLOCK_SIZE );
559 563
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
560 564
                                 MIN_HEAD_LENGTH );
561 565
        _candidates.resize(_head_length + _block_size);
562 566
        _curr_length = 0;
563 567
      }
564 568

	
0 comments (0 inline)