gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 4 0
merge default
4 files changed with 18 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -141,768 +141,774 @@
141 141
    }
142 142
  }
143 143

	
144 144
  void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
145 145
                                     ExprIterator e) {
146 146

	
147 147
    std::vector<int> indexes;
148 148
    std::vector<Value> values;
149 149

	
150 150
    indexes.push_back(0);
151 151
    values.push_back(0);
152 152

	
153 153
    for(ExprIterator it = b; it != e; ++it) {
154 154
      indexes.push_back(it->first);
155 155
      values.push_back(it->second);
156 156
    }
157 157

	
158 158
    glp_set_mat_col(lp, ix, values.size() - 1,
159 159
                    &indexes.front(), &values.front());
160 160
  }
161 161

	
162 162
  void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
163 163
    int length = glp_get_mat_col(lp, ix, 0, 0);
164 164

	
165 165
    std::vector<int> indexes(length + 1);
166 166
    std::vector<Value> values(length + 1);
167 167

	
168 168
    glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
169 169

	
170 170
    for (int i = 1; i  <= length; ++i) {
171 171
      *b = std::make_pair(indexes[i], values[i]);
172 172
      ++b;
173 173
    }
174 174
  }
175 175

	
176 176
  void GlpkBase::_setCoeff(int ix, int jx, Value value) {
177 177

	
178 178
    if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
179 179

	
180 180
      int length = glp_get_mat_row(lp, ix, 0, 0);
181 181

	
182 182
      std::vector<int> indexes(length + 2);
183 183
      std::vector<Value> values(length + 2);
184 184

	
185 185
      glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
186 186

	
187 187
      //The following code does not suppose that the elements of the
188 188
      //array indexes are sorted
189 189
      bool found = false;
190 190
      for (int i = 1; i  <= length; ++i) {
191 191
        if (indexes[i] == jx) {
192 192
          found = true;
193 193
          values[i] = value;
194 194
          break;
195 195
        }
196 196
      }
197 197
      if (!found) {
198 198
        ++length;
199 199
        indexes[length] = jx;
200 200
        values[length] = value;
201 201
      }
202 202

	
203 203
      glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
204 204

	
205 205
    } else {
206 206

	
207 207
      int length = glp_get_mat_col(lp, jx, 0, 0);
208 208

	
209 209
      std::vector<int> indexes(length + 2);
210 210
      std::vector<Value> values(length + 2);
211 211

	
212 212
      glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
213 213

	
214 214
      //The following code does not suppose that the elements of the
215 215
      //array indexes are sorted
216 216
      bool found = false;
217 217
      for (int i = 1; i <= length; ++i) {
218 218
        if (indexes[i] == ix) {
219 219
          found = true;
220 220
          values[i] = value;
221 221
          break;
222 222
        }
223 223
      }
224 224
      if (!found) {
225 225
        ++length;
226 226
        indexes[length] = ix;
227 227
        values[length] = value;
228 228
      }
229 229

	
230 230
      glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
231 231
    }
232 232

	
233 233
  }
234 234

	
235 235
  GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
236 236

	
237 237
    int length = glp_get_mat_row(lp, ix, 0, 0);
238 238

	
239 239
    std::vector<int> indexes(length + 1);
240 240
    std::vector<Value> values(length + 1);
241 241

	
242 242
    glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
243 243

	
244 244
    for (int i = 1; i  <= length; ++i) {
245 245
      if (indexes[i] == jx) {
246 246
        return values[i];
247 247
      }
248 248
    }
249 249

	
250 250
    return 0;
251 251
  }
252 252

	
253 253
  void GlpkBase::_setColLowerBound(int i, Value lo) {
254 254
    LEMON_ASSERT(lo != INF, "Invalid bound");
255 255

	
256 256
    int b = glp_get_col_type(lp, i);
257 257
    double up = glp_get_col_ub(lp, i);
258 258
    if (lo == -INF) {
259 259
      switch (b) {
260 260
      case GLP_FR:
261 261
      case GLP_LO:
262 262
        glp_set_col_bnds(lp, i, GLP_FR, lo, up);
263 263
        break;
264 264
      case GLP_UP:
265 265
        break;
266 266
      case GLP_DB:
267 267
      case GLP_FX:
268 268
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
269 269
        break;
270 270
      default:
271 271
        break;
272 272
      }
273 273
    } else {
274 274
      switch (b) {
275 275
      case GLP_FR:
276 276
      case GLP_LO:
277 277
        glp_set_col_bnds(lp, i, GLP_LO, lo, up);
278 278
        break;
279 279
      case GLP_UP:
280 280
      case GLP_DB:
281 281
      case GLP_FX:
282 282
        if (lo == up)
283 283
          glp_set_col_bnds(lp, i, GLP_FX, lo, up);
284 284
        else
285 285
          glp_set_col_bnds(lp, i, GLP_DB, lo, up);
286 286
        break;
287 287
      default:
288 288
        break;
289 289
      }
290 290
    }
291 291
  }
292 292

	
293 293
  GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
294 294
    int b = glp_get_col_type(lp, i);
295 295
    switch (b) {
296 296
    case GLP_LO:
297 297
    case GLP_DB:
298 298
    case GLP_FX:
299 299
      return glp_get_col_lb(lp, i);
300 300
    default:
301 301
      return -INF;
302 302
    }
303 303
  }
304 304

	
305 305
  void GlpkBase::_setColUpperBound(int i, Value up) {
306 306
    LEMON_ASSERT(up != -INF, "Invalid bound");
307 307

	
308 308
    int b = glp_get_col_type(lp, i);
309 309
    double lo = glp_get_col_lb(lp, i);
310 310
    if (up == INF) {
311 311
      switch (b) {
312 312
      case GLP_FR:
313 313
      case GLP_LO:
314 314
        break;
315 315
      case GLP_UP:
316 316
        glp_set_col_bnds(lp, i, GLP_FR, lo, up);
317 317
        break;
318 318
      case GLP_DB:
319 319
      case GLP_FX:
320 320
        glp_set_col_bnds(lp, i, GLP_LO, lo, up);
321 321
        break;
322 322
      default:
323 323
        break;
324 324
      }
325 325
    } else {
326 326
      switch (b) {
327 327
      case GLP_FR:
328 328
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
329 329
        break;
330 330
      case GLP_UP:
331 331
        glp_set_col_bnds(lp, i, GLP_UP, lo, up);
332 332
        break;
333 333
      case GLP_LO:
334 334
      case GLP_DB:
335 335
      case GLP_FX:
336 336
        if (lo == up)
337 337
          glp_set_col_bnds(lp, i, GLP_FX, lo, up);
338 338
        else
339 339
          glp_set_col_bnds(lp, i, GLP_DB, lo, up);
340 340
        break;
341 341
      default:
342 342
        break;
343 343
      }
344 344
    }
345 345

	
346 346
  }
347 347

	
348 348
  GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
349 349
    int b = glp_get_col_type(lp, i);
350 350
      switch (b) {
351 351
      case GLP_UP:
352 352
      case GLP_DB:
353 353
      case GLP_FX:
354 354
        return glp_get_col_ub(lp, i);
355 355
      default:
356 356
        return INF;
357 357
      }
358 358
  }
359 359

	
360 360
  void GlpkBase::_setRowLowerBound(int i, Value lo) {
361 361
    LEMON_ASSERT(lo != INF, "Invalid bound");
362 362

	
363 363
    int b = glp_get_row_type(lp, i);
364 364
    double up = glp_get_row_ub(lp, i);
365 365
    if (lo == -INF) {
366 366
      switch (b) {
367 367
      case GLP_FR:
368 368
      case GLP_LO:
369 369
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
370 370
        break;
371 371
      case GLP_UP:
372 372
        break;
373 373
      case GLP_DB:
374 374
      case GLP_FX:
375 375
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
376 376
        break;
377 377
      default:
378 378
        break;
379 379
      }
380 380
    } else {
381 381
      switch (b) {
382 382
      case GLP_FR:
383 383
      case GLP_LO:
384 384
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
385 385
        break;
386 386
      case GLP_UP:
387 387
      case GLP_DB:
388 388
      case GLP_FX:
389 389
        if (lo == up)
390 390
          glp_set_row_bnds(lp, i, GLP_FX, lo, up);
391 391
        else
392 392
          glp_set_row_bnds(lp, i, GLP_DB, lo, up);
393 393
        break;
394 394
      default:
395 395
        break;
396 396
      }
397 397
    }
398 398

	
399 399
  }
400 400

	
401 401
  GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
402 402
    int b = glp_get_row_type(lp, i);
403 403
    switch (b) {
404 404
    case GLP_LO:
405 405
    case GLP_DB:
406 406
    case GLP_FX:
407 407
      return glp_get_row_lb(lp, i);
408 408
    default:
409 409
      return -INF;
410 410
    }
411 411
  }
412 412

	
413 413
  void GlpkBase::_setRowUpperBound(int i, Value up) {
414 414
    LEMON_ASSERT(up != -INF, "Invalid bound");
415 415

	
416 416
    int b = glp_get_row_type(lp, i);
417 417
    double lo = glp_get_row_lb(lp, i);
418 418
    if (up == INF) {
419 419
      switch (b) {
420 420
      case GLP_FR:
421 421
      case GLP_LO:
422 422
        break;
423 423
      case GLP_UP:
424 424
        glp_set_row_bnds(lp, i, GLP_FR, lo, up);
425 425
        break;
426 426
      case GLP_DB:
427 427
      case GLP_FX:
428 428
        glp_set_row_bnds(lp, i, GLP_LO, lo, up);
429 429
        break;
430 430
      default:
431 431
        break;
432 432
      }
433 433
    } else {
434 434
      switch (b) {
435 435
      case GLP_FR:
436 436
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
437 437
        break;
438 438
      case GLP_UP:
439 439
        glp_set_row_bnds(lp, i, GLP_UP, lo, up);
440 440
        break;
441 441
      case GLP_LO:
442 442
      case GLP_DB:
443 443
      case GLP_FX:
444 444
        if (lo == up)
445 445
          glp_set_row_bnds(lp, i, GLP_FX, lo, up);
446 446
        else
447 447
          glp_set_row_bnds(lp, i, GLP_DB, lo, up);
448 448
        break;
449 449
      default:
450 450
        break;
451 451
      }
452 452
    }
453 453
  }
454 454

	
455 455
  GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
456 456
    int b = glp_get_row_type(lp, i);
457 457
    switch (b) {
458 458
    case GLP_UP:
459 459
    case GLP_DB:
460 460
    case GLP_FX:
461 461
      return glp_get_row_ub(lp, i);
462 462
    default:
463 463
      return INF;
464 464
    }
465 465
  }
466 466

	
467 467
  void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
468 468
    for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
469 469
      glp_set_obj_coef(lp, i, 0.0);
470 470
    }
471 471
    for (ExprIterator it = b; it != e; ++it) {
472 472
      glp_set_obj_coef(lp, it->first, it->second);
473 473
    }
474 474
  }
475 475

	
476 476
  void GlpkBase::_getObjCoeffs(InsertIterator b) const {
477 477
    for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
478 478
      Value val = glp_get_obj_coef(lp, i);
479 479
      if (val != 0.0) {
480 480
        *b = std::make_pair(i, val);
481 481
        ++b;
482 482
      }
483 483
    }
484 484
  }
485 485

	
486 486
  void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
487 487
    //i = 0 means the constant term (shift)
488 488
    glp_set_obj_coef(lp, i, obj_coef);
489 489
  }
490 490

	
491 491
  GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
492 492
    //i = 0 means the constant term (shift)
493 493
    return glp_get_obj_coef(lp, i);
494 494
  }
495 495

	
496 496
  void GlpkBase::_setSense(GlpkBase::Sense sense) {
497 497
    switch (sense) {
498 498
    case MIN:
499 499
      glp_set_obj_dir(lp, GLP_MIN);
500 500
      break;
501 501
    case MAX:
502 502
      glp_set_obj_dir(lp, GLP_MAX);
503 503
      break;
504 504
    }
505 505
  }
506 506

	
507 507
  GlpkBase::Sense GlpkBase::_getSense() const {
508 508
    switch(glp_get_obj_dir(lp)) {
509 509
    case GLP_MIN:
510 510
      return MIN;
511 511
    case GLP_MAX:
512 512
      return MAX;
513 513
    default:
514 514
      LEMON_ASSERT(false, "Wrong sense");
515 515
      return GlpkBase::Sense();
516 516
    }
517 517
  }
518 518

	
519 519
  void GlpkBase::_clear() {
520 520
    glp_erase_prob(lp);
521 521
    rows.clear();
522 522
    cols.clear();
523 523
  }
524 524

	
525
  void GlpkBase::freeEnv() {
526
    glp_free_env();
527
  }
528

	
529
  GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
530

	
525 531
  // GlpkLp members
526 532

	
527 533
  GlpkLp::GlpkLp()
528 534
    : LpBase(), GlpkBase(), LpSolver() {
529 535
    messageLevel(MESSAGE_NO_OUTPUT);
530 536
  }
531 537

	
532 538
  GlpkLp::GlpkLp(const GlpkLp& other)
533 539
    : LpBase(other), GlpkBase(other), LpSolver(other) {
534 540
    messageLevel(MESSAGE_NO_OUTPUT);
535 541
  }
536 542

	
537 543
  GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
538 544
  GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
539 545

	
540 546
  const char* GlpkLp::_solverName() const { return "GlpkLp"; }
541 547

	
542 548
  void GlpkLp::_clear_temporals() {
543 549
    _primal_ray.clear();
544 550
    _dual_ray.clear();
545 551
  }
546 552

	
547 553
  GlpkLp::SolveExitStatus GlpkLp::_solve() {
548 554
    return solvePrimal();
549 555
  }
550 556

	
551 557
  GlpkLp::SolveExitStatus GlpkLp::solvePrimal() {
552 558
    _clear_temporals();
553 559

	
554 560
    glp_smcp smcp;
555 561
    glp_init_smcp(&smcp);
556 562

	
557 563
    switch (_message_level) {
558 564
    case MESSAGE_NO_OUTPUT:
559 565
      smcp.msg_lev = GLP_MSG_OFF;
560 566
      break;
561 567
    case MESSAGE_ERROR_MESSAGE:
562 568
      smcp.msg_lev = GLP_MSG_ERR;
563 569
      break;
564 570
    case MESSAGE_NORMAL_OUTPUT:
565 571
      smcp.msg_lev = GLP_MSG_ON;
566 572
      break;
567 573
    case MESSAGE_FULL_OUTPUT:
568 574
      smcp.msg_lev = GLP_MSG_ALL;
569 575
      break;
570 576
    }
571 577

	
572 578
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
573 579
    return SOLVED;
574 580
  }
575 581

	
576 582
  GlpkLp::SolveExitStatus GlpkLp::solveDual() {
577 583
    _clear_temporals();
578 584

	
579 585
    glp_smcp smcp;
580 586
    glp_init_smcp(&smcp);
581 587

	
582 588
    switch (_message_level) {
583 589
    case MESSAGE_NO_OUTPUT:
584 590
      smcp.msg_lev = GLP_MSG_OFF;
585 591
      break;
586 592
    case MESSAGE_ERROR_MESSAGE:
587 593
      smcp.msg_lev = GLP_MSG_ERR;
588 594
      break;
589 595
    case MESSAGE_NORMAL_OUTPUT:
590 596
      smcp.msg_lev = GLP_MSG_ON;
591 597
      break;
592 598
    case MESSAGE_FULL_OUTPUT:
593 599
      smcp.msg_lev = GLP_MSG_ALL;
594 600
      break;
595 601
    }
596 602
    smcp.meth = GLP_DUAL;
597 603

	
598 604
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
599 605
    return SOLVED;
600 606
  }
601 607

	
602 608
  GlpkLp::Value GlpkLp::_getPrimal(int i) const {
603 609
    return glp_get_col_prim(lp, i);
604 610
  }
605 611

	
606 612
  GlpkLp::Value GlpkLp::_getDual(int i) const {
607 613
    return glp_get_row_dual(lp, i);
608 614
  }
609 615

	
610 616
  GlpkLp::Value GlpkLp::_getPrimalValue() const {
611 617
    return glp_get_obj_val(lp);
612 618
  }
613 619

	
614 620
  GlpkLp::VarStatus GlpkLp::_getColStatus(int i) const {
615 621
    switch (glp_get_col_stat(lp, i)) {
616 622
    case GLP_BS:
617 623
      return BASIC;
618 624
    case GLP_UP:
619 625
      return UPPER;
620 626
    case GLP_LO:
621 627
      return LOWER;
622 628
    case GLP_NF:
623 629
      return FREE;
624 630
    case GLP_NS:
625 631
      return FIXED;
626 632
    default:
627 633
      LEMON_ASSERT(false, "Wrong column status");
628 634
      return GlpkLp::VarStatus();
629 635
    }
630 636
  }
631 637

	
632 638
  GlpkLp::VarStatus GlpkLp::_getRowStatus(int i) const {
633 639
    switch (glp_get_row_stat(lp, i)) {
634 640
    case GLP_BS:
635 641
      return BASIC;
636 642
    case GLP_UP:
637 643
      return UPPER;
638 644
    case GLP_LO:
639 645
      return LOWER;
640 646
    case GLP_NF:
641 647
      return FREE;
642 648
    case GLP_NS:
643 649
      return FIXED;
644 650
    default:
645 651
      LEMON_ASSERT(false, "Wrong row status");
646 652
      return GlpkLp::VarStatus();
647 653
    }
648 654
  }
649 655

	
650 656
  GlpkLp::Value GlpkLp::_getPrimalRay(int i) const {
651 657
    if (_primal_ray.empty()) {
652 658
      int row_num = glp_get_num_rows(lp);
653 659
      int col_num = glp_get_num_cols(lp);
654 660

	
655 661
      _primal_ray.resize(col_num + 1, 0.0);
656 662

	
657 663
      int index = glp_get_unbnd_ray(lp);
658 664
      if (index != 0) {
659 665
        // The primal ray is found in primal simplex second phase
660 666
        LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
661 667
                      glp_get_col_stat(lp, index - row_num)) != GLP_BS,
662 668
                     "Wrong primal ray");
663 669

	
664 670
        bool negate = glp_get_obj_dir(lp) == GLP_MAX;
665 671

	
666 672
        if (index > row_num) {
667 673
          _primal_ray[index - row_num] = 1.0;
668 674
          if (glp_get_col_dual(lp, index - row_num) > 0) {
669 675
            negate = !negate;
670 676
          }
671 677
        } else {
672 678
          if (glp_get_row_dual(lp, index) > 0) {
673 679
            negate = !negate;
674 680
          }
675 681
        }
676 682

	
677 683
        std::vector<int> ray_indexes(row_num + 1);
678 684
        std::vector<Value> ray_values(row_num + 1);
679 685
        int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
680 686
                                          &ray_values.front());
681 687

	
682 688
        for (int i = 1; i <= ray_length; ++i) {
683 689
          if (ray_indexes[i] > row_num) {
684 690
            _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
685 691
          }
686 692
        }
687 693

	
688 694
        if (negate) {
689 695
          for (int i = 1; i <= col_num; ++i) {
690 696
            _primal_ray[i] = - _primal_ray[i];
691 697
          }
692 698
        }
693 699
      } else {
694 700
        for (int i = 1; i <= col_num; ++i) {
695 701
          _primal_ray[i] = glp_get_col_prim(lp, i);
696 702
        }
697 703
      }
698 704
    }
699 705
    return _primal_ray[i];
700 706
  }
701 707

	
702 708
  GlpkLp::Value GlpkLp::_getDualRay(int i) const {
703 709
    if (_dual_ray.empty()) {
704 710
      int row_num = glp_get_num_rows(lp);
705 711

	
706 712
      _dual_ray.resize(row_num + 1, 0.0);
707 713

	
708 714
      int index = glp_get_unbnd_ray(lp);
709 715
      if (index != 0) {
710 716
        // The dual ray is found in dual simplex second phase
711 717
        LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
712 718
                      glp_get_col_stat(lp, index - row_num)) == GLP_BS,
713 719

	
714 720
                     "Wrong dual ray");
715 721

	
716 722
        int idx;
717 723
        bool negate = false;
718 724

	
719 725
        if (index > row_num) {
720 726
          idx = glp_get_col_bind(lp, index - row_num);
721 727
          if (glp_get_col_prim(lp, index - row_num) >
722 728
              glp_get_col_ub(lp, index - row_num)) {
723 729
            negate = true;
724 730
          }
725 731
        } else {
726 732
          idx = glp_get_row_bind(lp, index);
727 733
          if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
728 734
            negate = true;
729 735
          }
730 736
        }
731 737

	
732 738
        _dual_ray[idx] = negate ?  - 1.0 : 1.0;
733 739

	
734 740
        glp_btran(lp, &_dual_ray.front());
735 741
      } else {
736 742
        double eps = 1e-7;
737 743
        // The dual ray is found in primal simplex first phase
738 744
        // We assume that the glpk minimizes the slack to get feasible solution
739 745
        for (int i = 1; i <= row_num; ++i) {
740 746
          int index = glp_get_bhead(lp, i);
741 747
          if (index <= row_num) {
742 748
            double res = glp_get_row_prim(lp, index);
743 749
            if (res > glp_get_row_ub(lp, index) + eps) {
744 750
              _dual_ray[i] = -1;
745 751
            } else if (res < glp_get_row_lb(lp, index) - eps) {
746 752
              _dual_ray[i] = 1;
747 753
            } else {
748 754
              _dual_ray[i] = 0;
749 755
            }
750 756
            _dual_ray[i] *= glp_get_rii(lp, index);
751 757
          } else {
752 758
            double res = glp_get_col_prim(lp, index - row_num);
753 759
            if (res > glp_get_col_ub(lp, index - row_num) + eps) {
754 760
              _dual_ray[i] = -1;
755 761
            } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
756 762
              _dual_ray[i] = 1;
757 763
            } else {
758 764
              _dual_ray[i] = 0;
759 765
            }
760 766
            _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
761 767
          }
762 768
        }
763 769

	
764 770
        glp_btran(lp, &_dual_ray.front());
765 771

	
766 772
        for (int i = 1; i <= row_num; ++i) {
767 773
          _dual_ray[i] /= glp_get_rii(lp, i);
768 774
        }
769 775
      }
770 776
    }
771 777
    return _dual_ray[i];
772 778
  }
773 779

	
774 780
  GlpkLp::ProblemType GlpkLp::_getPrimalType() const {
775 781
    if (glp_get_status(lp) == GLP_OPT)
776 782
      return OPTIMAL;
777 783
    switch (glp_get_prim_stat(lp)) {
778 784
    case GLP_UNDEF:
779 785
      return UNDEFINED;
780 786
    case GLP_FEAS:
781 787
    case GLP_INFEAS:
782 788
      if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
783 789
        return UNBOUNDED;
784 790
      } else {
785 791
        return UNDEFINED;
786 792
      }
787 793
    case GLP_NOFEAS:
788 794
      return INFEASIBLE;
789 795
    default:
790 796
      LEMON_ASSERT(false, "Wrong primal type");
791 797
      return  GlpkLp::ProblemType();
792 798
    }
793 799
  }
794 800

	
795 801
  GlpkLp::ProblemType GlpkLp::_getDualType() const {
796 802
    if (glp_get_status(lp) == GLP_OPT)
797 803
      return OPTIMAL;
798 804
    switch (glp_get_dual_stat(lp)) {
799 805
    case GLP_UNDEF:
800 806
      return UNDEFINED;
801 807
    case GLP_FEAS:
802 808
    case GLP_INFEAS:
803 809
      if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
804 810
        return UNBOUNDED;
805 811
      } else {
806 812
        return UNDEFINED;
807 813
      }
808 814
    case GLP_NOFEAS:
809 815
      return INFEASIBLE;
810 816
    default:
811 817
      LEMON_ASSERT(false, "Wrong primal type");
812 818
      return  GlpkLp::ProblemType();
813 819
    }
814 820
  }
815 821

	
816 822
  void GlpkLp::presolver(bool b) {
817 823
    lpx_set_int_parm(lp, LPX_K_PRESOL, b ? 1 : 0);
818 824
  }
819 825

	
820 826
  void GlpkLp::messageLevel(MessageLevel m) {
821 827
    _message_level = m;
822 828
  }
823 829

	
824 830
  // GlpkMip members
825 831

	
826 832
  GlpkMip::GlpkMip()
827 833
    : LpBase(), GlpkBase(), MipSolver() {
828 834
    messageLevel(MESSAGE_NO_OUTPUT);
829 835
  }
830 836

	
831 837
  GlpkMip::GlpkMip(const GlpkMip& other)
832 838
    : LpBase(), GlpkBase(other), MipSolver() {
833 839
    messageLevel(MESSAGE_NO_OUTPUT);
834 840
  }
835 841

	
836 842
  void GlpkMip::_setColType(int i, GlpkMip::ColTypes col_type) {
837 843
    switch (col_type) {
838 844
    case INTEGER:
839 845
      glp_set_col_kind(lp, i, GLP_IV);
840 846
      break;
841 847
    case REAL:
842 848
      glp_set_col_kind(lp, i, GLP_CV);
843 849
      break;
844 850
    }
845 851
  }
846 852

	
847 853
  GlpkMip::ColTypes GlpkMip::_getColType(int i) const {
848 854
    switch (glp_get_col_kind(lp, i)) {
849 855
    case GLP_IV:
850 856
    case GLP_BV:
851 857
      return INTEGER;
852 858
    default:
853 859
      return REAL;
854 860
    }
855 861

	
856 862
  }
857 863

	
858 864
  GlpkMip::SolveExitStatus GlpkMip::_solve() {
859 865
    glp_smcp smcp;
860 866
    glp_init_smcp(&smcp);
861 867

	
862 868
    switch (_message_level) {
863 869
    case MESSAGE_NO_OUTPUT:
864 870
      smcp.msg_lev = GLP_MSG_OFF;
865 871
      break;
866 872
    case MESSAGE_ERROR_MESSAGE:
867 873
      smcp.msg_lev = GLP_MSG_ERR;
868 874
      break;
869 875
    case MESSAGE_NORMAL_OUTPUT:
870 876
      smcp.msg_lev = GLP_MSG_ON;
871 877
      break;
872 878
    case MESSAGE_FULL_OUTPUT:
873 879
      smcp.msg_lev = GLP_MSG_ALL;
874 880
      break;
875 881
    }
876 882
    smcp.meth = GLP_DUAL;
877 883

	
878 884
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
879 885
    if (glp_get_status(lp) != GLP_OPT) return SOLVED;
880 886

	
881 887
    glp_iocp iocp;
882 888
    glp_init_iocp(&iocp);
883 889

	
884 890
    switch (_message_level) {
885 891
    case MESSAGE_NO_OUTPUT:
886 892
      iocp.msg_lev = GLP_MSG_OFF;
887 893
      break;
888 894
    case MESSAGE_ERROR_MESSAGE:
889 895
      iocp.msg_lev = GLP_MSG_ERR;
890 896
      break;
891 897
    case MESSAGE_NORMAL_OUTPUT:
892 898
      iocp.msg_lev = GLP_MSG_ON;
893 899
      break;
894 900
    case MESSAGE_FULL_OUTPUT:
895 901
      iocp.msg_lev = GLP_MSG_ALL;
896 902
      break;
897 903
    }
898 904

	
899 905
    if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
900 906
    return SOLVED;
901 907
  }
902 908

	
903 909

	
904 910
  GlpkMip::ProblemType GlpkMip::_getType() const {
905 911
    switch (glp_get_status(lp)) {
906 912
    case GLP_OPT:
907 913
      switch (glp_mip_status(lp)) {
908 914
      case GLP_UNDEF:
Ignore white space 768 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_GLPK_H
20 20
#define LEMON_GLPK_H
21 21

	
22 22
///\file
23 23
///\brief Header of the LEMON-GLPK lp solver interface.
24 24
///\ingroup lp_group
25 25

	
26 26
#include <lemon/lp_base.h>
27 27

	
28 28
// forward declaration
29 29
#ifndef _GLP_PROB
30 30
#define _GLP_PROB
31 31
typedef struct { double _prob; } glp_prob;
32 32
/* LP/MIP problem object */
33 33
#endif
34 34

	
35 35
namespace lemon {
36 36

	
37 37

	
38 38
  /// \brief Base interface for the GLPK LP and MIP solver
39 39
  ///
40 40
  /// This class implements the common interface of the GLPK LP and MIP solver.
41 41
  /// \ingroup lp_group
42 42
  class GlpkBase : virtual public LpBase {
43 43
  protected:
44 44

	
45 45
    typedef glp_prob LPX;
46 46
    glp_prob* lp;
47 47

	
48 48
    GlpkBase();
49 49
    GlpkBase(const GlpkBase&);
50 50
    virtual ~GlpkBase();
51 51

	
52 52
  protected:
53 53

	
54 54
    virtual int _addCol();
55 55
    virtual int _addRow();
56 56

	
57 57
    virtual void _eraseCol(int i);
58 58
    virtual void _eraseRow(int i);
59 59

	
60 60
    virtual void _eraseColId(int i);
61 61
    virtual void _eraseRowId(int i);
62 62

	
63 63
    virtual void _getColName(int col, std::string& name) const;
64 64
    virtual void _setColName(int col, const std::string& name);
65 65
    virtual int _colByName(const std::string& name) const;
66 66

	
67 67
    virtual void _getRowName(int row, std::string& name) const;
68 68
    virtual void _setRowName(int row, const std::string& name);
69 69
    virtual int _rowByName(const std::string& name) const;
70 70

	
71 71
    virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
72 72
    virtual void _getRowCoeffs(int i, InsertIterator b) const;
73 73

	
74 74
    virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
75 75
    virtual void _getColCoeffs(int i, InsertIterator b) const;
76 76

	
77 77
    virtual void _setCoeff(int row, int col, Value value);
78 78
    virtual Value _getCoeff(int row, int col) const;
79 79

	
80 80
    virtual void _setColLowerBound(int i, Value value);
81 81
    virtual Value _getColLowerBound(int i) const;
82 82

	
83 83
    virtual void _setColUpperBound(int i, Value value);
84 84
    virtual Value _getColUpperBound(int i) const;
85 85

	
86 86
    virtual void _setRowLowerBound(int i, Value value);
87 87
    virtual Value _getRowLowerBound(int i) const;
88 88

	
89 89
    virtual void _setRowUpperBound(int i, Value value);
90 90
    virtual Value _getRowUpperBound(int i) const;
91 91

	
92 92
    virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
93 93
    virtual void _getObjCoeffs(InsertIterator b) const;
94 94

	
95 95
    virtual void _setObjCoeff(int i, Value obj_coef);
96 96
    virtual Value _getObjCoeff(int i) const;
97 97

	
98 98
    virtual void _setSense(Sense);
99 99
    virtual Sense _getSense() const;
100 100

	
101 101
    virtual void _clear();
102 102

	
103
  private:
104

	
105
    static void freeEnv();
106

	
107
    struct FreeEnvHelper {
108
      ~FreeEnvHelper() {
109
        freeEnv();
110
      }
111
    };
112
    
113
    static FreeEnvHelper freeEnvHelper;
114
    
103 115
  public:
104 116

	
105 117
    ///Pointer to the underlying GLPK data structure.
106 118
    LPX *lpx() {return lp;}
107 119
    ///Const pointer to the underlying GLPK data structure.
108 120
    const LPX *lpx() const {return lp;}
109 121

	
110 122
    ///Returns the constraint identifier understood by GLPK.
111 123
    int lpxRow(Row r) const { return rows(id(r)); }
112 124

	
113 125
    ///Returns the variable identifier understood by GLPK.
114 126
    int lpxCol(Col c) const { return cols(id(c)); }
115 127

	
116 128
  };
117 129

	
118 130
  /// \brief Interface for the GLPK LP solver
119 131
  ///
120 132
  /// This class implements an interface for the GLPK LP solver.
121 133
  ///\ingroup lp_group
122 134
  class GlpkLp : public LpSolver, public GlpkBase {
123 135
  public:
124 136

	
125 137
    ///\e
126 138
    GlpkLp();
127 139
    ///\e
128 140
    GlpkLp(const GlpkLp&);
129 141

	
130 142
    ///\e
131 143
    virtual GlpkLp* cloneSolver() const;
132 144
    ///\e
133 145
    virtual GlpkLp* newSolver() const;
134 146

	
135 147
  private:
136 148

	
137 149
    mutable std::vector<double> _primal_ray;
138 150
    mutable std::vector<double> _dual_ray;
139 151

	
140 152
    void _clear_temporals();
141 153

	
142 154
  protected:
143 155

	
144 156
    virtual const char* _solverName() const;
145 157

	
146 158
    virtual SolveExitStatus _solve();
147 159
    virtual Value _getPrimal(int i) const;
148 160
    virtual Value _getDual(int i) const;
149 161

	
150 162
    virtual Value _getPrimalValue() const;
151 163

	
152 164
    virtual VarStatus _getColStatus(int i) const;
153 165
    virtual VarStatus _getRowStatus(int i) const;
154 166

	
155 167
    virtual Value _getPrimalRay(int i) const;
156 168
    virtual Value _getDualRay(int i) const;
157 169

	
158 170
    virtual ProblemType _getPrimalType() const;
159 171
    virtual ProblemType _getDualType() const;
160 172

	
161 173
  public:
162 174

	
163 175
    ///Solve with primal simplex
164 176
    SolveExitStatus solvePrimal();
165 177

	
166 178
    ///Solve with dual simplex
167 179
    SolveExitStatus solveDual();
168 180

	
169 181
    ///Turns on or off the presolver
170 182

	
171 183
    ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
172 184
    ///
173 185
    ///The presolver is off by default.
174 186
    void presolver(bool b);
175 187

	
176 188
    ///Enum for \c messageLevel() parameter
177 189
    enum MessageLevel {
178 190
      /// no output (default value)
179 191
      MESSAGE_NO_OUTPUT = 0,
180 192
      /// error messages only
181 193
      MESSAGE_ERROR_MESSAGE = 1,
182 194
      /// normal output
183 195
      MESSAGE_NORMAL_OUTPUT = 2,
184 196
      /// full output (includes informational messages)
185 197
      MESSAGE_FULL_OUTPUT = 3
186 198
    };
187 199

	
188 200
  private:
189 201

	
190 202
    MessageLevel _message_level;
191 203

	
192 204
  public:
193 205

	
194 206
    ///Set the verbosity of the messages
195 207

	
196 208
    ///Set the verbosity of the messages
197 209
    ///
198 210
    ///\param m is the level of the messages output by the solver routines.
199 211
    void messageLevel(MessageLevel m);
200 212
  };
201 213

	
202 214
  /// \brief Interface for the GLPK MIP solver
203 215
  ///
204 216
  /// This class implements an interface for the GLPK MIP solver.
205 217
  ///\ingroup lp_group
206 218
  class GlpkMip : public MipSolver, public GlpkBase {
207 219
  public:
208 220

	
209 221
    ///\e
210 222
    GlpkMip();
211 223
    ///\e
212 224
    GlpkMip(const GlpkMip&);
213 225

	
214 226
    virtual GlpkMip* cloneSolver() const;
215 227
    virtual GlpkMip* newSolver() const;
216 228

	
217 229
  protected:
218 230

	
219 231
    virtual const char* _solverName() const;
220 232

	
221 233
    virtual ColTypes _getColType(int col) const;
222 234
    virtual void _setColType(int col, ColTypes col_type);
223 235

	
224 236
    virtual SolveExitStatus _solve();
225 237
    virtual ProblemType _getType() const;
226 238
    virtual Value _getSol(int i) const;
227 239
    virtual Value _getSolValue() const;
228 240

	
229 241
    ///Enum for \c messageLevel() parameter
230 242
    enum MessageLevel {
231 243
      /// no output (default value)
232 244
      MESSAGE_NO_OUTPUT = 0,
233 245
      /// error messages only
234 246
      MESSAGE_ERROR_MESSAGE = 1,
235 247
      /// normal output
236 248
      MESSAGE_NORMAL_OUTPUT = 2,
237 249
      /// full output (includes informational messages)
238 250
      MESSAGE_FULL_OUTPUT = 3
239 251
    };
240 252

	
241 253
  private:
242 254

	
243 255
    MessageLevel _message_level;
244 256

	
245 257
  public:
246 258

	
247 259
    ///Set the verbosity of the messages
248 260

	
249 261
    ///Set the verbosity of the messages
250 262
    ///
251 263
    ///\param m is the level of the messages output by the solver routines.
252 264
    void messageLevel(MessageLevel m);
253 265
  };
254 266

	
255 267

	
256 268
} //END OF NAMESPACE LEMON
257 269

	
258 270
#endif //LEMON_GLPK_H
259 271

	
0 comments (0 inline)