test/mip_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 655 6ac5d9ae1d3d
parent 484 08d495d48089
child 584 0fec6a017ead
child 587 9db62975c32b
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

- Real types are supported by appropriate inicialization.
- A feature of the XTI spanning tree structure is removed to ensure
numerical stability (could cause problems using integer types).
The node potentials are updated always on the lower subtree,
in order to prevent overflow problems.
The former method isn't notably faster during to our tests.
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@481
     5
 * Copyright (C) 2003-2008
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
deba@481
    22
#ifdef HAVE_CONFIG_H
deba@481
    23
#include <lemon/config.h>
deba@481
    24
#endif
deba@481
    25
deba@481
    26
#ifdef HAVE_CPLEX
alpar@484
    27
#include <lemon/cplex.h>
deba@481
    28
#endif
deba@481
    29
deba@481
    30
#ifdef HAVE_GLPK
alpar@484
    31
#include <lemon/glpk.h>
deba@481
    32
#endif
deba@481
    33
deba@481
    34
deba@481
    35
using namespace lemon;
deba@481
    36
deba@482
    37
void solveAndCheck(MipSolver& mip, MipSolver::ProblemType stat,
deba@481
    38
                   double exp_opt) {
deba@481
    39
  using std::string;
deba@481
    40
deba@482
    41
  mip.solve();
deba@481
    42
  //int decimal,sign;
deba@481
    43
  std::ostringstream buf;
deba@482
    44
  buf << "Type should be: " << int(stat)<<" and it is "<<int(mip.type());
deba@481
    45
deba@481
    46
deba@481
    47
  //  itoa(stat,buf1, 10);
deba@482
    48
  check(mip.type()==stat, buf.str());
deba@481
    49
deba@482
    50
  if (stat ==  MipSolver::OPTIMAL) {
deba@481
    51
    std::ostringstream sbuf;
deba@481
    52
    buf << "Wrong optimal value: the right optimum is " << exp_opt;
deba@482
    53
    check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str());
deba@481
    54
    //+ecvt(exp_opt,2)
deba@481
    55
  }
deba@481
    56
}
deba@481
    57
deba@482
    58
void aTest(MipSolver& mip)
deba@481
    59
{
deba@481
    60
 //The following example is very simple
deba@481
    61
deba@481
    62
deba@482
    63
  typedef MipSolver::Row Row;
deba@482
    64
  typedef MipSolver::Col Col;
deba@481
    65
deba@481
    66
deba@481
    67
deba@481
    68
  Col x1 = mip.addCol();
deba@481
    69
  Col x2 = mip.addCol();
deba@481
    70
deba@481
    71
deba@481
    72
  //Objective function
deba@481
    73
  mip.obj(x1);
deba@481
    74
deba@481
    75
  mip.max();
deba@481
    76
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@481
    83
  mip.addRow(2*x1+x2 <=2);
deba@481
    84
  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@481
    89
  //Maximization of x1
deba@481
    90
  //over the triangle with vertices (0,0),(4/5,2/5),(0,2)
deba@481
    91
  double expected_opt=4.0/5.0;
deba@482
    92
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
    93
deba@481
    94
  //Restrict x2 to integer
deba@482
    95
  mip.colType(x2,MipSolver::INTEGER);
deba@481
    96
  expected_opt=1.0/2.0;
deba@482
    97
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
    98
deba@481
    99
deba@481
   100
  //Restrict both to integer
deba@482
   101
  mip.colType(x1,MipSolver::INTEGER);
deba@481
   102
  expected_opt=0;
deba@482
   103
  solveAndCheck(mip, MipSolver::OPTIMAL, expected_opt);
deba@481
   104
deba@481
   105
deba@481
   106
deba@481
   107
}
deba@481
   108
deba@481
   109
deba@481
   110
int main()
deba@481
   111
{
deba@481
   112
deba@481
   113
#ifdef HAVE_GLPK
deba@482
   114
  {
alpar@485
   115
    GlpkMip mip1;
deba@482
   116
    aTest(mip1);
deba@482
   117
  }
deba@481
   118
#endif
deba@481
   119
deba@481
   120
#ifdef HAVE_CPLEX
deba@482
   121
  try {
alpar@485
   122
    CplexMip mip2;
deba@482
   123
    aTest(mip2);
deba@482
   124
  } catch (CplexEnv::LicenseError& error) {
deba@482
   125
#ifdef LEMON_FORCE_CPLEX_CHECK
deba@482
   126
    check(false, error.what());
deba@482
   127
#else
deba@482
   128
    std::cerr << error.what() << std::endl;
deba@482
   129
    std::cerr << "Cplex license check failed, lp check skipped" << std::endl;
deba@482
   130
#endif
deba@482
   131
  }
deba@481
   132
#endif
deba@481
   133
deba@481
   134
  return 0;
deba@481
   135
deba@481
   136
}