diff options
| author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-08-07 14:19:14 -0400 |
|---|---|---|
| committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2013-02-12 06:49:39 -0500 |
| commit | a4ff45bfbaef292ee1106b759c7ae80213b03cd4 (patch) | |
| tree | a13c4046ce6be77257bdd028fbc2896a6af161e3 /native/src | |
| parent | 673f367fc5835ebce3357dfebee9c0e414e5c09b (diff) | |
Add CPLEX integration
This patch introduces a concrete subclass of Solution that implements the actual
solving of linear programs by means of invoking the CPLEX Concert Technology API.
The project can still be compiled on systems that do not have CPLEX installed.
Diffstat (limited to 'native/src')
| -rw-r--r-- | native/src/linprog/cplex.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/native/src/linprog/cplex.cpp b/native/src/linprog/cplex.cpp new file mode 100644 index 0000000..b5565d4 --- /dev/null +++ b/native/src/linprog/cplex.cpp | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | #define IL_STD // required by CPLEX when using STL classes. | ||
| 2 | |||
| 3 | #include <ilcplex/ilocplex.h> | ||
| 4 | |||
| 5 | #include "cpu_time.h" | ||
| 6 | |||
| 7 | #include "linprog/cplex.h" | ||
| 8 | |||
| 9 | class CPLEXSolution : public Solution | ||
| 10 | { | ||
| 11 | private: | ||
| 12 | IloEnv ilo_env; | ||
| 13 | IloEnv& get_env() | ||
| 14 | { | ||
| 15 | return ilo_env; | ||
| 16 | } | ||
| 17 | |||
| 18 | IloNumArray cplex_values; | ||
| 19 | |||
| 20 | const LinearProgram &linprog; | ||
| 21 | |||
| 22 | bool solved; | ||
| 23 | |||
| 24 | void solve_model(unsigned int max_num_vars, | ||
| 25 | double var_lb, double var_ub); | ||
| 26 | |||
| 27 | IloObjective make_objective(const IloNumVarArray& vars); | ||
| 28 | IloRangeArray make_constraints(const IloNumVarArray& vars); | ||
| 29 | |||
| 30 | IloRange make_constraint(const IloNumVarArray &vars, | ||
| 31 | const LinearExpression *exp, double bound, | ||
| 32 | bool is_exact_bound); | ||
| 33 | |||
| 34 | public: | ||
| 35 | CPLEXSolution(const LinearProgram &lp, unsigned int max_num_vars, | ||
| 36 | double var_lb = 0.0, double var_ub = 1.0); | ||
| 37 | ~CPLEXSolution(); | ||
| 38 | |||
| 39 | double get_value(unsigned int var) const | ||
| 40 | { | ||
| 41 | return cplex_values[var]; | ||
| 42 | } | ||
| 43 | |||
| 44 | bool is_solved() const | ||
| 45 | { | ||
| 46 | return solved; | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | |||
| 50 | CPLEXSolution::CPLEXSolution(const LinearProgram& lp, unsigned int max_num_vars, | ||
| 51 | double var_lb, double var_ub) | ||
| 52 | : ilo_env(), | ||
| 53 | cplex_values(get_env(), max_num_vars), | ||
| 54 | linprog(lp), | ||
| 55 | solved(false) | ||
| 56 | { | ||
| 57 | get_env().setNormalizer(IloFalse); | ||
| 58 | get_env().setOut(get_env().getNullStream()); | ||
| 59 | |||
| 60 | if (max_num_vars > 0) | ||
| 61 | solve_model(max_num_vars, var_lb, var_ub); | ||
| 62 | else | ||
| 63 | // Trivial case: no variables. | ||
| 64 | solved = true; | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | void CPLEXSolution::solve_model(unsigned int max_num_vars, | ||
| 69 | double var_lb, double var_ub) | ||
| 70 | { | ||
| 71 | try | ||
| 72 | { | ||
| 73 | IloNumVarArray cplex_vars = IloNumVarArray(get_env(), max_num_vars, | ||
| 74 | var_lb, var_ub); | ||
| 75 | |||
| 76 | IloObjective objective = make_objective(cplex_vars); | ||
| 77 | IloRangeArray constraints = make_constraints(cplex_vars); | ||
| 78 | |||
| 79 | IloModel model = IloModel(get_env()); | ||
| 80 | |||
| 81 | model.add(objective); | ||
| 82 | model.add(constraints); | ||
| 83 | |||
| 84 | |||
| 85 | IloCplex cplex = IloCplex(model); | ||
| 86 | |||
| 87 | cplex.solve(); | ||
| 88 | |||
| 89 | cplex.getValues(cplex_vars, cplex_values); | ||
| 90 | solved = true; | ||
| 91 | |||
| 92 | } catch (IloException &ex) | ||
| 93 | { | ||
| 94 | // Improve me: we should export some kind of error info. | ||
| 95 | std::cerr << "CPLEX failed: " << ex << std::endl; | ||
| 96 | solved = false; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | IloObjective CPLEXSolution::make_objective(const IloNumVarArray &vars) | ||
| 101 | { | ||
| 102 | const LinearExpression *obj = linprog.get_objective(); | ||
| 103 | |||
| 104 | IloObjective goal = IloObjective(get_env(), 0, IloObjective::Maximize); | ||
| 105 | IloNumArray coeffs = IloNumArray(get_env(), vars.getSize()); | ||
| 106 | |||
| 107 | assert((int) obj->get_terms().size() <= coeffs.getSize()); | ||
| 108 | |||
| 109 | coeffs.add(vars.getSize(), 0); | ||
| 110 | |||
| 111 | // Set coefficient for each variable in the objective function. | ||
| 112 | foreach(obj->get_terms(), term) | ||
| 113 | { | ||
| 114 | double coefficient = term->first; | ||
| 115 | unsigned int var_idx = term->second; | ||
| 116 | coeffs[var_idx] = coefficient; | ||
| 117 | } | ||
| 118 | |||
| 119 | goal.setLinearCoefs(vars, coeffs); | ||
| 120 | |||
| 121 | return goal; | ||
| 122 | } | ||
| 123 | |||
| 124 | IloRangeArray CPLEXSolution::make_constraints(const IloNumVarArray &vars) | ||
| 125 | { | ||
| 126 | IloRangeArray constraints(get_env()); | ||
| 127 | |||
| 128 | foreach (linprog.get_equalities(), exp) | ||
| 129 | constraints.add(make_constraint(vars, exp->first, exp->second, true)); | ||
| 130 | |||
| 131 | foreach (linprog.get_inequalities(), exp) | ||
| 132 | constraints.add(make_constraint(vars, exp->first, exp->second, false)); | ||
| 133 | |||
| 134 | return constraints; | ||
| 135 | } | ||
| 136 | |||
| 137 | IloRange CPLEXSolution::make_constraint(const IloNumVarArray &vars, | ||
| 138 | const LinearExpression *exp, double bound, | ||
| 139 | bool is_exact_bound) | ||
| 140 | { | ||
| 141 | IloRange r = IloRange(get_env(), -IloInfinity, bound); | ||
| 142 | |||
| 143 | if (is_exact_bound) | ||
| 144 | r.setLB(bound); | ||
| 145 | |||
| 146 | foreach (exp->get_terms(), term) | ||
| 147 | r.setLinearCoef(vars[term->second], term->first); | ||
| 148 | |||
| 149 | return r; | ||
| 150 | } | ||
| 151 | |||
| 152 | CPLEXSolution::~CPLEXSolution() | ||
| 153 | { | ||
| 154 | get_env().end(); | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
| 158 | Solution *cplex_solve(const LinearProgram& lp, unsigned int max_num_vars) | ||
| 159 | { | ||
| 160 | CPLEXSolution *sol = new CPLEXSolution(lp, max_num_vars); | ||
| 161 | if (sol->is_solved()) | ||
| 162 | return sol; | ||
| 163 | else | ||
| 164 | { | ||
| 165 | delete sol; | ||
| 166 | return NULL; | ||
| 167 | } | ||
| 168 | } | ||
