-
Notifications
You must be signed in to change notification settings - Fork 0
/
mipsolver.cpp
117 lines (96 loc) · 3.14 KB
/
mipsolver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "mipsolver.h"
#include "solution.h"
#include "solution_verifier.h"
#include "instance.h"
#include "users.h"
#include "lib/util.h"
#include <stdexcept>
#include <algorithm>
ILOSTLBEGIN
template<typename ProbT>
MIPSolver<ProbT>::MIPSolver() : m_time_limit(0), m_threads(0), m_bab_nodes(0)
{
formulation = make_unique<NullFormulation<ProbT> >();
}
template<typename ProbT>
MIPSolver<ProbT>::~MIPSolver()
{
cplex.end();
model.end();
env.end();
}
template<typename ProbT>
typename MIPSolver<ProbT>::Status MIPSolver<ProbT>::run(const Instance<ProbT>& inst, Solution<ProbT>& sol)
{
initCplex();
MIP_OUT(DBG) << "init CPLEX" << std::endl;
try {
formulation->createDecisionVariables(env, inst);
MIP_OUT(DBG) << "created decision variables" << std::endl;
formulation->addConstraints(env, model, inst);
MIP_OUT(DBG) << "created constraints" << std::endl;
formulation->addObjectiveFunction(env, model, inst);
MIP_OUT(DBG) << "created objective function" << std::endl;
cplex = IloCplex(model);
if (m_threads != 0)
cplex.setParam(IloCplex::Param::Threads, m_threads);
if (m_time_limit != 0)
cplex.setParam(IloCplex::Param::TimeLimit, m_time_limit);
formulation->addUserCallbacks(env, model, cplex, inst);
#ifndef USER_MIP
cplex.setOut(env.getNullStream());
cplex.setWarning(env.getNullStream());
cplex.setError(env.getNullStream());
#endif
// cplex.setParam(IloCplex::Param::MIP::Limits::Nodes, 1); // Stop after root node.
MIP_OUT(DBG) << "calling CPLEX solve ..." << std::endl;
cplex.solve();
MIP_OUT(DBG) << "CPLEX finished." << std::endl;
IloAlgorithm::Status stat = cplex.getStatus();
m_bab_nodes = (int)cplex.getNnodes();
MIP_OUT(DBG) << "CPLEX status: " << stat << std::endl;
if (stat == IloAlgorithm::Optimal || stat == IloAlgorithm::Feasible) {
formulation->extractSolution(cplex, inst, sol);
MIP_OUT(TRACE) << "Solution: \n" << sol << std::endl;
MIP_OUT(DBG) << "Objective value: " << cplex.getObjValue() << std::endl;
MIP_OUT(DBG) << "Lower Bound: " << cplex.getBestObjValue() << std::endl;
MIP_OUT(DBG) << "Branch-and-Bound nodes: " << m_bab_nodes << std::endl;
if (stat == IloAlgorithm::Optimal) {
sol.db = (int)cplex.getObjValue();
return Optimal;
} else {
sol.db = (int)cplex.getBestObjValue();
return Feasible;
}
} else if (stat == IloAlgorithm::Infeasible) {
throw std::runtime_error("Intance is infeasible");
} else {
MIP_OUT(FATAL) << "No feasible solution exits" << std::endl;
return Aborted;
}
} catch(IloException& e) {
throw std::runtime_error(e.getMessage());
} catch(...) {
throw std::runtime_error("Unknown exception");
}
}
template<typename ProbT>
void MIPSolver<ProbT>::initCplex()
{
try {
env = IloEnv();
model = IloModel(env);
} catch(IloException& e) {
throw std::runtime_error(e.getMessage());
} catch(...) {
throw std::runtime_error("Unknown exception");
}
}
// Instantiate all required MIP solver classes
template class MIPSolver<BP>;
template class MIPSolver<MLBP>;
template class MIPSolver<CCMLBP>;
template class MIPSolver<MLBPCC>;
template class MIPSolver<MLBPPO>;
template class MIPSolver<MLBPTW>;
template class MIPSolver<MLBPFC>;