gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Automatic GLPK env deallocation (#213)
0 4 0
default
4 files changed with 14 insertions and 10 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -481,96 +481,98 @@
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 525
  void GlpkBase::freeEnv() {
526 526
    glp_free_env();
527 527
  }
528 528

	
529
  GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
530

	
529 531
  // GlpkLp members
530 532

	
531 533
  GlpkLp::GlpkLp()
532 534
    : LpBase(), GlpkBase(), LpSolver() {
533 535
    messageLevel(MESSAGE_NO_OUTPUT);
534 536
  }
535 537

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

	
541 543
  GlpkLp* GlpkLp::_newSolver() const { return new GlpkLp; }
542 544
  GlpkLp* GlpkLp::_cloneSolver() const { return new GlpkLp(*this); }
543 545

	
544 546
  const char* GlpkLp::_solverName() const { return "GlpkLp"; }
545 547

	
546 548
  void GlpkLp::_clear_temporals() {
547 549
    _primal_ray.clear();
548 550
    _dual_ray.clear();
549 551
  }
550 552

	
551 553
  GlpkLp::SolveExitStatus GlpkLp::_solve() {
552 554
    return solvePrimal();
553 555
  }
554 556

	
555 557
  GlpkLp::SolveExitStatus GlpkLp::solvePrimal() {
556 558
    _clear_temporals();
557 559

	
558 560
    glp_smcp smcp;
559 561
    glp_init_smcp(&smcp);
560 562

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

	
576 578
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
Ignore white space 6 line context
... ...
@@ -55,106 +55,110 @@
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
    /// \brief Deallocates the globally allocated memory of GLPK.
106

	
107
    /// Deallocates the globally allocated memory of GLPK.  \note
108
    /// Usually, it do not have to be called, because the GLPK use
109
    /// only a small amount of global memory, and it is deallocated
110
    /// automatically at the end of program.
111
    static void freeEnv();
112

	
113 117
    ///Pointer to the underlying GLPK data structure.
114 118
    LPX *lpx() {return lp;}
115 119
    ///Const pointer to the underlying GLPK data structure.
116 120
    const LPX *lpx() const {return lp;}
117 121

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

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

	
124 128
  };
125 129

	
126 130
  /// \brief Interface for the GLPK LP solver
127 131
  ///
128 132
  /// This class implements an interface for the GLPK LP solver.
129 133
  ///\ingroup lp_group
130 134
  class GlpkLp : public GlpkBase, public LpSolver {
131 135
  public:
132 136

	
133 137
    ///\e
134 138
    GlpkLp();
135 139
    ///\e
136 140
    GlpkLp(const GlpkLp&);
137 141

	
138 142
  private:
139 143

	
140 144
    mutable std::vector<double> _primal_ray;
141 145
    mutable std::vector<double> _dual_ray;
142 146

	
143 147
    void _clear_temporals();
144 148

	
145 149
  protected:
146 150

	
147 151
    virtual GlpkLp* _cloneSolver() const;
148 152
    virtual GlpkLp* _newSolver() const;
149 153

	
150 154
    virtual const char* _solverName() const;
151 155

	
152 156
    virtual SolveExitStatus _solve();
153 157
    virtual Value _getPrimal(int i) const;
154 158
    virtual Value _getDual(int i) const;
155 159

	
156 160
    virtual Value _getPrimalValue() const;
157 161

	
158 162
    virtual VarStatus _getColStatus(int i) const;
159 163
    virtual VarStatus _getRowStatus(int i) const;
160 164

	
Ignore white space 96 line context
... ...
@@ -321,84 +321,83 @@
321 321
        "The upper bound for the first row should be 1.");
322 322
  e = clp->row(upright);
323 323
  check(e[x1] == 1, "The first coefficient should 1.");
324 324
  check(e[x2] == 1, "The second coefficient should 1.");
325 325

	
326 326
  de = clp->col(x1);
327 327
  check(de[upright] == 1, "The first coefficient should 1.");
328 328

	
329 329
  delete clp;
330 330

	
331 331
  //Maximization of x1+x2
332 332
  //over the triangle with vertices (0,0) (0,1) (1,0)
333 333
  double expected_opt=1;
334 334
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
335 335

	
336 336
  //Minimization
337 337
  lp.sense(lp.MIN);
338 338
  expected_opt=0;
339 339
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
340 340

	
341 341
  //Vertex (-1,0) instead of (0,0)
342 342
  lp.colLowerBound(x1, -LpSolver::INF);
343 343
  expected_opt=-1;
344 344
  solveAndCheck(lp, LpSolver::OPTIMAL, expected_opt);
345 345

	
346 346
  //Erase one constraint and return to maximization
347 347
  lp.erase(upright);
348 348
  lp.sense(lp.MAX);
349 349
  expected_opt=LpSolver::INF;
350 350
  solveAndCheck(lp, LpSolver::UNBOUNDED, expected_opt);
351 351

	
352 352
  //Infeasibilty
353 353
  lp.addRow(x1+x2 <=-2);
354 354
  solveAndCheck(lp, LpSolver::INFEASIBLE, expected_opt);
355 355

	
356 356
}
357 357

	
358 358
int main()
359 359
{
360 360
  LpSkeleton lp_skel;
361 361
  lpTest(lp_skel);
362 362

	
363 363
#ifdef HAVE_GLPK
364 364
  {
365 365
    GlpkLp lp_glpk1,lp_glpk2;
366 366
    lpTest(lp_glpk1);
367 367
    aTest(lp_glpk2);
368 368
  }
369
  GlpkLp::freeEnv();
370 369
#endif
371 370

	
372 371
#ifdef HAVE_CPLEX
373 372
  try {
374 373
    CplexLp lp_cplex1,lp_cplex2;
375 374
    lpTest(lp_cplex1);
376 375
    aTest(lp_cplex2);
377 376
  } catch (CplexEnv::LicenseError& error) {
378 377
#ifdef LEMON_FORCE_CPLEX_CHECK
379 378
    check(false, error.what());
380 379
#else
381 380
    std::cerr << error.what() << std::endl;
382 381
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
383 382
#endif
384 383
  }
385 384
#endif
386 385

	
387 386
#ifdef HAVE_SOPLEX
388 387
  {
389 388
    SoplexLp lp_soplex1,lp_soplex2;
390 389
    lpTest(lp_soplex1);
391 390
    aTest(lp_soplex2);
392 391
  }
393 392
#endif
394 393

	
395 394
#ifdef HAVE_CLP
396 395
  {
397 396
    ClpLp lp_clp1,lp_clp2;
398 397
    lpTest(lp_clp1);
399 398
    aTest(lp_clp2);
400 399
  }
401 400
#endif
402 401

	
403 402
  return 0;
404 403
}
Ignore white space 6 line context
... ...
@@ -70,68 +70,67 @@
70 70

	
71 71

	
72 72
  //Objective function
73 73
  mip.obj(x1);
74 74

	
75 75
  mip.max();
76 76

	
77 77

	
78 78
  //Unconstrained optimization
79 79
  mip.solve();
80 80
  //Check it out!
81 81

	
82 82
  //Constraints
83 83
  mip.addRow(2*x1+x2 <=2);
84 84
  mip.addRow(x1-2*x2 <=0);
85 85

	
86 86
  //Nonnegativity of the variable x1
87 87
  mip.colLowerBound(x1, 0);
88 88

	
89 89
  //Maximization of x1
90 90
  //over the triangle with vertices (0,0),(4/5,2/5),(0,2)
91 91
  double expected_opt=4.0/5.0;
92 92
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
93 93

	
94 94
  //Restrict x2 to integer
95 95
  mip.colType(x2,MipSolver::INTEGER);
96 96
  expected_opt=1.0/2.0;
97 97
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
98 98

	
99 99

	
100 100
  //Restrict both to integer
101 101
  mip.colType(x1,MipSolver::INTEGER);
102 102
  expected_opt=0;
103 103
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
104 104

	
105 105

	
106 106

	
107 107
}
108 108

	
109 109

	
110 110
int main()
111 111
{
112 112

	
113 113
#ifdef HAVE_GLPK
114 114
  {
115 115
    GlpkMip mip1;
116 116
    aTest(mip1);
117 117
  }
118
  GlpkLp::freeEnv();
119 118
#endif
120 119

	
121 120
#ifdef HAVE_CPLEX
122 121
  try {
123 122
    CplexMip mip2;
124 123
    aTest(mip2);
125 124
  } catch (CplexEnv::LicenseError& error) {
126 125
#ifdef LEMON_FORCE_CPLEX_CHECK
127 126
    check(false, error.what());
128 127
#else
129 128
    std::cerr << error.what() << std::endl;
130 129
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
131 130
#endif
132 131
  }
133 132
#endif
134 133

	
135 134
  return 0;
136 135

	
137 136
}
0 comments (0 inline)