test/mip_test.cc
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 732 bb70ad62c95f
parent 626 d21b38647e53
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@540
     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@622
    23
#ifdef LEMON_HAVE_CPLEX
alpar@461
    24
#include <lemon/cplex.h>
deba@458
    25
#endif
deba@458
    26
ladanyi@622
    27
#ifdef LEMON_HAVE_GLPK
alpar@461
    28
#include <lemon/glpk.h>
deba@458
    29
#endif
deba@458
    30
ladanyi@622
    31
#ifdef LEMON_HAVE_CBC
deba@559
    32
#include <lemon/cbc.h>
deba@559
    33
#endif
deba@559
    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@694
    53
    sbuf << "Wrong optimal value ("<< mip.solValue()
alpar@694
    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@559
    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@559
    83
  mip.addRow(2 * x1 + x2 <= 2);
deba@559
    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@559
    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@559
    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@559
   107
  //Erase a variable
deba@559
   108
  mip.erase(x2);
deba@559
   109
  mip.rowUpperBound(y2, 8);
deba@559
   110
  expected_opt=1;
deba@559
   111
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@458
   112
deba@458
   113
}
deba@458
   114
deba@559
   115
alpar@528
   116
template<class MIP>
alpar@528
   117
void cloneTest()
alpar@528
   118
{
deba@540
   119
alpar@528
   120
  MIP* mip = new MIP();
alpar@528
   121
  MIP* mipnew = mip->newSolver();
alpar@528
   122
  MIP* mipclone = mip->cloneSolver();
alpar@528
   123
  delete mip;
alpar@528
   124
  delete mipnew;
alpar@528
   125
  delete mipclone;
alpar@528
   126
}
deba@458
   127
deba@458
   128
int main()
deba@458
   129
{
deba@458
   130
ladanyi@622
   131
#ifdef LEMON_HAVE_GLPK
deba@459
   132
  {
alpar@462
   133
    GlpkMip mip1;
deba@459
   134
    aTest(mip1);
alpar@528
   135
    cloneTest<GlpkMip>();
deba@459
   136
  }
deba@458
   137
#endif
deba@458
   138
ladanyi@622
   139
#ifdef LEMON_HAVE_CPLEX
deba@459
   140
  try {
alpar@462
   141
    CplexMip mip2;
deba@459
   142
    aTest(mip2);
deba@540
   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@622
   149
#ifdef LEMON_HAVE_CBC
deba@559
   150
  {
deba@559
   151
    CbcMip mip1;
deba@559
   152
    aTest(mip1);
deba@559
   153
    cloneTest<CbcMip>();
deba@559
   154
  }
deba@559
   155
#endif
deba@559
   156
deba@458
   157
  return 0;
deba@458
   158
deba@458
   159
}