SCIP++ refs/heads/main
 
Loading...
Searching...
No Matches
model.hpp
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <filesystem>
6#include <functional>
7#include <optional>
8#include <scip/scip.h>
9#include <string>
10#include <type_traits>
11#include <vector>
12
13#include "scippp/constant_coefficient.hpp"
14#include "scippp/lin_expr.hpp"
15#include "scippp/lin_ineq.hpp"
16#include "scippp/param.hpp"
17#include "scippp/solution.hpp"
18#include "scippp/statistics.hpp"
19#include "scippp/var.hpp"
20#include "scippp/var_type.hpp"
21
23namespace scippp {
24
26enum class Sense {
28 MAXIMIZE = SCIP_OBJSENSE_MAXIMIZE,
30 MINIMIZE = SCIP_OBJSENSE_MINIMIZE
31};
32
39class Model {
41 Scip* m_scip;
43 bool m_weCreatedANewScipObject { false };
45 std::vector<Var> m_vars {};
47 std::vector<SCIP_Cons*> m_cons {};
49 SCIP_Retcode m_lastReturnCode;
51 std::function<void(SCIP_Retcode)> m_scipCallWrapper;
52
53public:
64 explicit Model(const std::string& name, SCIP* scip = nullptr, bool includeDefaultPlugins = true);
65
71
77 [[nodiscard]] SCIP_Retcode getLastReturnCode() const;
78
84 void setScipCallWrapper(std::function<void(SCIP_Retcode)> wrapper);
85
97 const std::string& name,
98 SCIP_Real coeff = 0.0,
100 std::optional<SCIP_Real> lb = 0.0,
101 std::optional<SCIP_Real> ub = 1.0);
102
116 template <typename CoeffType = ConstantCoefficient>
117 std::vector<Var> addVars(
118 const std::string& prefix,
119 size_t numVars,
120 const CoeffType& coeffs = COEFF_ZERO,
122 std::optional<SCIP_Real> lb = 0.0,
123 std::optional<SCIP_Real> ub = 1.0)
124 {
125 std::vector<Var> result;
126 result.reserve(numVars);
127 for (size_t index { 0 }; index < numVars; index++) {
128 result.push_back(addVar(prefix + std::to_string(index), coeffs[index], varType, lb, ub));
129 }
130 return result;
131 }
132
150 template <size_t NumVars, typename CoeffType = ConstantCoefficient>
151 std::array<Var, NumVars> addVars(
152 const std::string& prefix,
153 const CoeffType& coeffs = COEFF_ZERO,
155 std::optional<SCIP_Real> lb = 0.0,
156 std::optional<SCIP_Real> ub = 1.0)
157 {
158 std::array<Var, NumVars> result;
159 auto vec { addVars(prefix, NumVars, coeffs, varType, lb, ub) };
160 std::copy_n(std::make_move_iterator(vec.begin()), NumVars, result.begin());
161 return result;
162 }
163
170 void addConstr(const LinIneq& ineq, const std::string& name);
171
177 [[nodiscard]] SCIP_Real infinity() const;
178
184 [[nodiscard]] SCIP_Real epsilon() const;
185
192 [[nodiscard]] SCIP_Real round(SCIP_Real value) const;
193
200 [[nodiscard]] bool isZero(SCIP_Real value) const;
201
206 void solve();
207
213 void setObjsense(Sense objsense);
214
220 [[nodiscard]] SCIP_Status getStatus() const;
221
230 template <typename T>
231 [[nodiscard]] T getSolvingStatistic(const statistics::Statistic<T>& statistic) const
232 {
233 return statistic(m_scip);
234 }
235
241 [[nodiscard]] int getNSols() const;
242
248 [[nodiscard]] Solution getBestSol() const;
249
256 [[deprecated("use getSolvingStatistic with statistics::PRIMALBOUND instead")]] //
257 [[nodiscard]] double
259
271 template <typename T, typename PT>
272 void setParam(params::Param<PT> parameter, T value)
273 {
274 auto ptValue { static_cast<PT>(value) };
275 const auto* cName { parameter.scipName.data() };
276 if constexpr (std::is_same_v<PT, int>) {
277 m_scipCallWrapper(SCIPsetIntParam(m_scip, cName, ptValue));
278 } else if constexpr (std::is_same_v<PT, double>) {
279 m_scipCallWrapper(SCIPsetRealParam(m_scip, cName, ptValue));
280 } else if constexpr (std::is_same_v<PT, char>) {
281 m_scipCallWrapper(SCIPsetCharParam(m_scip, cName, value));
282 } else if constexpr (std::is_same_v<PT, bool>) {
283 m_scipCallWrapper(SCIPsetBoolParam(m_scip, cName, value));
284 } else if constexpr (std::is_same_v<PT, SCIP_Longint>) {
285 m_scipCallWrapper(SCIPsetLongintParam(m_scip, cName, value));
286 } else if constexpr (std::is_same_v<PT, std::string>) {
287 m_scipCallWrapper(SCIPsetStringParam(m_scip, cName, value.c_str()));
288 } else {
289 // make this not compile
290 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html#workarounds
291 static_assert(sizeof(T) == 0);
292 }
293 }
294
305 void writeOrigProblem(const std::filesystem::directory_entry& filename, bool genericNames = false) const;
306
315 void writeOrigProblem(const std::string& extension, bool genericNames = false) const;
316
325 [[deprecated(R"(Use this to access the raw SCIP object.
326 That is only required for use-cases not supported by SCIP++.
327 Consider adding the feature you are using to SCIP++!)")]] [[nodiscard]] Scip*
328 scip() const;
329};
330}
Represents a linear inequality: lhs <= expr <= rhs.
Definition lin_ineq.hpp:16
A SCIP optimization model.
Definition model.hpp:39
void setObjsense(Sense objsense)
Set objective goal.
std::vector< Var > addVars(const std::string &prefix, size_t numVars, const CoeffType &coeffs=COEFF_ZERO, VarType varType=VarType::CONTINUOUS, std::optional< SCIP_Real > lb=0.0, std::optional< SCIP_Real > ub=1.0)
Adds multiple variables to the model.
Definition model.hpp:117
void writeOrigProblem(const std::filesystem::directory_entry &filename, bool genericNames=false) const
Writes original problem to file.
std::array< Var, NumVars > addVars(const std::string &prefix, const CoeffType &coeffs=COEFF_ZERO, VarType varType=VarType::CONTINUOUS, std::optional< SCIP_Real > lb=0.0, std::optional< SCIP_Real > ub=1.0)
Adds multiple variables to the model.
Definition model.hpp:151
Scip * scip() const
Returns a pointer to the underlying SCIP object.
Model(const std::string &name, SCIP *scip=nullptr, bool includeDefaultPlugins=true)
Creates an empty problem and sets the optimization goal to Sense::MINIMIZE.
void setScipCallWrapper(std::function< void(SCIP_Retcode)> wrapper)
Replace the current wrapper for every call to SCIP's C API.
void writeOrigProblem(const std::string &extension, bool genericNames=false) const
Writes original problem to standard output.
SCIP_Retcode getLastReturnCode() const
Gets the return code of the last call to SCIP's C API when the default call wrapper is used.
T getSolvingStatistic(const statistics::Statistic< T > &statistic) const
Query statistics about the solving process.
Definition model.hpp:231
SCIP_Real infinity() const
Infinity according the SCIP config.
bool isZero(SCIP_Real value) const
Checks, if value is in range epsilon of 0.0.
void addConstr(const LinIneq &ineq, const std::string &name)
Adds a constraint to the model.
SCIP_Real epsilon() const
Value treated as zero.
~Model()
Releases the variables and constraints.
Var & addVar(const std::string &name, SCIP_Real coeff=0.0, VarType varType=VarType::CONTINUOUS, std::optional< SCIP_Real > lb=0.0, std::optional< SCIP_Real > ub=1.0)
Adds a variable to the model.
void setParam(params::Param< PT > parameter, T value)
Sets a parameter.
Definition model.hpp:272
SCIP_Status getStatus() const
Returns the solution status.
double getPrimalbound() const
Returns the objective value of best solution.
int getNSols() const
Returns the number of feasible primal solutions stored in the solution storage.
SCIP_Real round(SCIP_Real value) const
Rounds value to the nearest integer with epsilon tolerance.
void solve()
Solve the model.
Solution getBestSol() const
Returns the best feasible primal solution found so far or best solution candidate.
C++ wrapper for SCIP.
Sense
Optimization goal.
Definition model.hpp:26
@ MINIMIZE
Minimize.
@ MAXIMIZE
Maximize.
static constexpr ConstantCoefficient COEFF_ZERO
An object which index operator always returns 0.
VarType
Type of a variable.
Definition var_type.hpp:11
@ CONTINUOUS
Continuous variable.
Wrapper for a SCIP solution.
Definition solution.hpp:13
Wrapper for a SCIP variable.
Definition var.hpp:17
Stores the argument type and string representation of a parameter.
Definition param.hpp:14
std::string_view scipName
Original name of the parameter in SCIP.
Definition param.hpp:16
Storage for a function pointer.