test/mip_test.cc
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 891 bb70ad62c95f
parent 631 d21b38647e53
child 1105 62dba6c90f35
permissions -rw-r--r--
Fix critical bug in preflow (#372)

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