lemon/mip_glpk.cc
author Balazs Dezso <deba@inf.elte.hu>
Tue, 02 Dec 2008 21:40:33 +0100
changeset 458 7afc121e0689
permissions -rw-r--r--
Port LP and MIP solvers from SVN -r3509 (#44)
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@458
     5
 * Copyright (C) 2003-2008
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
///\file
deba@458
    20
///\brief Implementation of the LEMON-GLPK mip solver interface.
deba@458
    21
deba@458
    22
#include <lemon/mip_glpk.h>
deba@458
    23
deba@458
    24
extern "C" {
deba@458
    25
#include <glpk.h>
deba@458
    26
}
deba@458
    27
deba@458
    28
#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
deba@458
    29
#define LEMON_glp(func) (glp_##func)
deba@458
    30
#define LEMON_lpx(func) (lpx_##func)
deba@458
    31
deba@458
    32
#define LEMON_GLP(def) (GLP_##def)
deba@458
    33
#define LEMON_LPX(def) (LPX_##def)
deba@458
    34
deba@458
    35
#else
deba@458
    36
deba@458
    37
#define LEMON_glp(func) (lpx_##func)
deba@458
    38
#define LEMON_lpx(func) (lpx_##func)
deba@458
    39
deba@458
    40
#define LEMON_GLP(def) (LPX_##def)
deba@458
    41
#define LEMON_LPX(def) (LPX_##def)
deba@458
    42
deba@458
    43
#endif
deba@458
    44
deba@458
    45
namespace lemon {
deba@458
    46
deba@458
    47
  MipGlpk::MipGlpk() {
deba@458
    48
#if !(GLP_MAJOR_VERSION > 4 || \
deba@458
    49
      (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15))
deba@458
    50
    LEMON_lpx(set_class)(lp,LEMON_GLP(MIP));
deba@458
    51
#endif
deba@458
    52
  }
deba@458
    53
deba@458
    54
  void MipGlpk::_colType(int i, MipGlpk::ColTypes col_type){
deba@458
    55
    switch (col_type){
deba@458
    56
      case INT:
deba@458
    57
        LEMON_glp(set_col_kind)(lp,i,LEMON_GLP(IV));
deba@458
    58
        break;
deba@458
    59
      case REAL:
deba@458
    60
        LEMON_glp(set_col_kind)(lp,i,LEMON_GLP(CV));
deba@458
    61
        break;
deba@458
    62
    default:;
deba@458
    63
        //FIXME problem
deba@458
    64
    }
deba@458
    65
  }
deba@458
    66
deba@458
    67
  MipGlpk::ColTypes MipGlpk::_colType(int i) const {
deba@458
    68
    switch (LEMON_glp(get_col_kind)(lp,i)){
deba@458
    69
    case LEMON_GLP(IV):
deba@458
    70
      return INT;//Or binary
deba@458
    71
    case LEMON_GLP(CV):
deba@458
    72
      return REAL;
deba@458
    73
    default:
deba@458
    74
      return REAL;//Error!
deba@458
    75
    }
deba@458
    76
deba@458
    77
  }
deba@458
    78
deba@458
    79
  LpGlpk::SolveExitStatus MipGlpk::_solve() {
deba@458
    80
    int result = LEMON_lpx(simplex)(lp);
deba@458
    81
deba@458
    82
    // hack: mip does not contain integer variable
deba@458
    83
#if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION == 16
deba@458
    84
    int tmp = -1;
deba@458
    85
    if (LEMON_glp(get_num_int(lp)) == 0) {
deba@458
    86
      tmp = LEMON_lpx(add_cols)(lp, 1);
deba@458
    87
      LEMON_glp(set_col_bnds)(lp, tmp, LEMON_GLP(FX), 0.0, 0.0);
deba@458
    88
      LEMON_glp(set_col_kind)(lp, tmp, LEMON_GLP(IV));
deba@458
    89
    }
deba@458
    90
#endif
deba@458
    91
deba@458
    92
    if (LEMON_lpx(get_status)(lp)==LEMON_LPX(OPT)) {
deba@458
    93
      //Maybe we could try the routine lpx_intopt(lp), a revised
deba@458
    94
      //version of lpx_integer
deba@458
    95
deba@458
    96
      result = LEMON_lpx(integer)(lp);
deba@458
    97
      switch (result){
deba@458
    98
      case LEMON_LPX(E_OK):
deba@458
    99
        solved = true;
deba@458
   100
        break;
deba@458
   101
      default:
deba@458
   102
        solved = false;
deba@458
   103
      }
deba@458
   104
    } else {
deba@458
   105
      solved = false;
deba@458
   106
    }
deba@458
   107
#if GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION == 16
deba@458
   108
    if (tmp != -1) {
deba@458
   109
      int tmpa[2];
deba@458
   110
      tmpa[1] = tmp;
deba@458
   111
      LEMON_lpx(del_cols)(lp, 1, tmpa);
deba@458
   112
    }
deba@458
   113
#endif
deba@458
   114
    return solved ? SOLVED : UNSOLVED;
deba@458
   115
  }
deba@458
   116
deba@458
   117
deba@458
   118
  LpGlpk::SolutionStatus MipGlpk::_getMipStatus() const {
deba@458
   119
deba@458
   120
    if (LEMON_lpx(get_status)(lp)==LEMON_LPX(OPT)){
deba@458
   121
      //Meg kell nezni: ha az LP is infinite, akkor ez is, ha az is
deba@458
   122
      //infeasible, akkor ez is, de ez lehet maskepp is infeasible.
deba@458
   123
      int stat= LEMON_lpx(mip_status)(lp);
deba@458
   124
deba@458
   125
      switch (stat) {
deba@458
   126
      case LEMON_LPX(I_UNDEF)://Undefined (no solve has been run yet)
deba@458
   127
        return UNDEFINED;
deba@458
   128
      case LEMON_LPX(I_NOFEAS)://There is no feasible integral solution
deba@458
   129
        return INFEASIBLE;
deba@458
   130
        //     case LEMON_LPX(UNBND)://Unbounded
deba@458
   131
        //       return INFINITE;
deba@458
   132
      case LEMON_LPX(I_FEAS)://Feasible
deba@458
   133
        return FEASIBLE;
deba@458
   134
      case LEMON_LPX(I_OPT)://Feasible
deba@458
   135
        return OPTIMAL;
deba@458
   136
      default:
deba@458
   137
        return UNDEFINED; //to avoid gcc warning
deba@458
   138
      //FIXME error
deba@458
   139
      }
deba@458
   140
    }
deba@458
   141
    else
deba@458
   142
      return UNDEFINED; //Maybe we could refine this: what does the LP
deba@458
   143
                        //relaxation look like
deba@458
   144
deba@458
   145
  }
deba@458
   146
deba@458
   147
  MipGlpk::Value MipGlpk::_getPrimal(int i) const {
deba@458
   148
    return LEMON_glp(mip_col_val)(lp,i);
deba@458
   149
  }
deba@458
   150
deba@458
   151
  MipGlpk::Value MipGlpk::_getPrimalValue() const {
deba@458
   152
    return LEMON_glp(mip_obj_val)(lp);
deba@458
   153
  }
deba@458
   154
} //END OF NAMESPACE LEMON