test/mip_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 1047 ddd3c0d3d9bf
parent 678 d21b38647e53
child 1300 62dba6c90f35
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
deba@481
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@481
     2
 *
deba@481
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@481
     4
 *
deba@598
     5
 * Copyright (C) 2003-2009
deba@481
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@481
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@481
     8
 *
deba@481
     9
 * Permission to use, modify and distribute this software is granted
deba@481
    10
 * provided that this copyright notice appears in all copies. For
deba@481
    11
 * precise terms see the accompanying LICENSE file.
deba@481
    12
 *
deba@481
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@481
    14
 * express or implied, and with no claim as to its suitability for any
deba@481
    15
 * purpose.
deba@481
    16
 *
deba@481
    17
 */
deba@481
    18
deba@481
    19
#include "test_tools.h"
deba@481
    20
deba@481
    21
#include <lemon/config.h>
deba@481
    22
ladanyi@674
    23
#ifdef LEMON_HAVE_CPLEX
alpar@484
    24
#include <lemon/cplex.h>
deba@481
    25
#endif
deba@481
    26
ladanyi@674
    27
#ifdef LEMON_HAVE_GLPK
alpar@484
    28
#include <lemon/glpk.h>
deba@481
    29
#endif
deba@481
    30
ladanyi@674
    31
#ifdef LEMON_HAVE_CBC
deba@614
    32
#include <lemon/cbc.h>
deba@614
    33
#endif
deba@614
    34
deba@481
    35
deba@481
    36
using namespace lemon;
deba@481
    37
deba@482
    38
void solveAndCheck(MipSolver& mip, MipSolver::ProblemType stat,
deba@481
    39
                   double exp_opt) {
deba@481
    40
  using std::string;
deba@481
    41
deba@482
    42
  mip.solve();
deba@481
    43
  //int decimal,sign;
deba@481
    44
  std::ostringstream buf;
deba@482
    45
  buf << "Type should be: " << int(stat)<<" and it is "<<int(mip.type());
deba@481
    46
deba@481
    47
deba@481
    48
  //  itoa(stat,buf1, 10);
deba@482
    49
  check(mip.type()==stat, buf.str());
deba@481
    50
deba@482
    51
  if (stat ==  MipSolver::OPTIMAL) {
deba@481
    52
    std::ostringstream sbuf;
alpar@795
    53
    sbuf << "Wrong optimal value ("<< mip.solValue()
alpar@795
    54
         <<" instead of " << exp_opt << ")";
deba@482
    55
    check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str());
deba@481
    56
    //+ecvt(exp_opt,2)
deba@481
    57
  }
deba@481
    58
}
deba@481
    59
deba@482
    60
void aTest(MipSolver& mip)
deba@481
    61
{
deba@614
    62
  //The following example is very simple
deba@481
    63
deba@481
    64
deba@482
    65
  typedef MipSolver::Row Row;
deba@482
    66
  typedef MipSolver::Col Col;
deba@481
    67
deba@481
    68
deba@481
    69
  Col x1 = mip.addCol();
deba@481
    70
  Col x2 = mip.addCol();
deba@481
    71
deba@481
    72
deba@481
    73
  //Objective function
deba@481
    74
  mip.obj(x1);
deba@481
    75
deba@481
    76
  mip.max();
deba@481
    77
deba@481
    78
  //Unconstrained optimization
deba@481
    79
  mip.solve();
deba@481
    80
  //Check it out!
deba@481
    81
deba@481
    82
  //Constraints
deba@614
    83
  mip.addRow(2 * x1 + x2 <= 2);
deba@614
    84
  Row y2 = mip.addRow(x1 - 2 * x2 <= 0);
deba@481
    85
deba@481
    86
  //Nonnegativity of the variable x1
deba@481
    87
  mip.colLowerBound(x1, 0);
deba@481
    88
deba@614
    89
deba@481
    90
  //Maximization of x1
deba@481
    91
  //over the triangle with vertices (0,0),(4/5,2/5),(0,2)
deba@481
    92
  double expected_opt=4.0/5.0;
deba@482
    93
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
    94
deba@614
    95
deba@481
    96
  //Restrict x2 to integer
deba@482
    97
  mip.colType(x2,MipSolver::INTEGER);
deba@481
    98
  expected_opt=1.0/2.0;
deba@482
    99
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
   100
deba@481
   101
deba@481
   102
  //Restrict both to integer
deba@482
   103
  mip.colType(x1,MipSolver::INTEGER);
deba@481
   104
  expected_opt=0;
deba@482
   105
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
   106
deba@614
   107
  //Erase a variable
deba@614
   108
  mip.erase(x2);
deba@614
   109
  mip.rowUpperBound(y2, 8);
deba@614
   110
  expected_opt=1;
deba@614
   111
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
   112
deba@481
   113
}
deba@481
   114
deba@614
   115
alpar@587
   116
template<class MIP>
alpar@587
   117
void cloneTest()
alpar@587
   118
{
deba@598
   119
alpar@587
   120
  MIP* mip = new MIP();
alpar@587
   121
  MIP* mipnew = mip->newSolver();
alpar@587
   122
  MIP* mipclone = mip->cloneSolver();
alpar@587
   123
  delete mip;
alpar@587
   124
  delete mipnew;
alpar@587
   125
  delete mipclone;
alpar@587
   126
}
deba@481
   127
deba@481
   128
int main()
deba@481
   129
{
deba@481
   130
ladanyi@674
   131
#ifdef LEMON_HAVE_GLPK
deba@482
   132
  {
alpar@485
   133
    GlpkMip mip1;
deba@482
   134
    aTest(mip1);
alpar@587
   135
    cloneTest<GlpkMip>();
deba@482
   136
  }
deba@481
   137
#endif
deba@481
   138
ladanyi@674
   139
#ifdef LEMON_HAVE_CPLEX
deba@482
   140
  try {
alpar@485
   141
    CplexMip mip2;
deba@482
   142
    aTest(mip2);
deba@598
   143
    cloneTest<CplexMip>();
deba@482
   144
  } catch (CplexEnv::LicenseError& error) {
deba@482
   145
    check(false, error.what());
deba@482
   146
  }
deba@481
   147
#endif
deba@481
   148
ladanyi@674
   149
#ifdef LEMON_HAVE_CBC
deba@614
   150
  {
deba@614
   151
    CbcMip mip1;
deba@614
   152
    aTest(mip1);
deba@614
   153
    cloneTest<CbcMip>();
deba@614
   154
  }
deba@614
   155
#endif
deba@614
   156
deba@481
   157
  return 0;
deba@481
   158
deba@481
   159
}