From dc8f1c568b26dc2cc58807298019b16527ee61dc Mon Sep 17 00:00:00 2001 From: Joshua Morris Date: Mon, 31 Jul 2023 08:38:09 +1000 Subject: [PATCH 1/5] make the upper and lower bounds in addVar optional --- include/scippp/model.hpp | 9 +++++---- source/model.cpp | 6 +++--- test/test_var.cpp | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/scippp/model.hpp b/include/scippp/model.hpp index a92bf02f..1d821867 100644 --- a/include/scippp/model.hpp +++ b/include/scippp/model.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -94,8 +95,8 @@ class Model { const std::string& name, SCIP_Real coeff = 0.0, VarType varType = VarType::CONTINUOUS, - SCIP_Real lb = 0.0, - SCIP_Real ub = 1.0); + std::optional lb = 0.0, + std::optional ub = 1.0); /** * Adds multiple variables to the model. @@ -116,8 +117,8 @@ class Model { size_t numVars, const CoeffType& coeffs = COEFF_ZERO, VarType varType = VarType::CONTINUOUS, - SCIP_Real lb = 0.0, - SCIP_Real ub = 1.0) + std::optional lb = 0.0, + std::optional ub = 1.0) { std::vector result; result.reserve(numVars); diff --git a/source/model.cpp b/source/model.cpp index 5c861ad4..a015134b 100644 --- a/source/model.cpp +++ b/source/model.cpp @@ -6,15 +6,15 @@ namespace scippp { -Var& Model::addVar(const std::string& name, SCIP_Real coeff, VarType varType, SCIP_Real lb, SCIP_Real ub) +Var& Model::addVar(const std::string& name, SCIP_Real coeff, VarType varType, std::optional lb, std::optional ub) { SCIP_VAR* var { nullptr }; m_scipCallWrapper(SCIPcreateVarBasic( m_scip, /* SCIP environment */ &var, /* reference to the variable */ name.c_str(), /* name of the variable */ - lb, /* lower bound of the variable */ - ub, /* upper bound of the variable */ + lb != std::nullopt ? lb.value() : -SCIPinfinity(m_scip), /* lower bound of the variable */ + ub != std::nullopt ? ub.value() : SCIPinfinity(m_scip), /* upper bound of the variable */ coeff, /* obj. coefficient. */ static_cast(varType) /* variable is binary */ )); diff --git a/test/test_var.cpp b/test/test_var.cpp index b60536d5..66c2f6b1 100644 --- a/test/test_var.cpp +++ b/test/test_var.cpp @@ -1,4 +1,5 @@ #include +#include #include "scippp/model.hpp" #include "scippp/parameters.hpp" @@ -11,7 +12,7 @@ BOOST_AUTO_TEST_SUITE(Var) BOOST_AUTO_TEST_CASE(GetSolVal, *boost::unit_test::tolerance(1e-3)) { Model model("Simple"); - auto x1 = model.addVar("x_1", 1); + auto x1 = model.addVar("x_1", 1, VarType::CONTINUOUS, 0.0, std::nullopt); auto x2 = model.addVar("x_2", 1); model.addConstr(x1 + x2 >= 1, "capacity"); model.addConstr(x1 == x2, "equal"); From d18bf8f9593f7d7698c13c490fdc3ad1646c2907 Mon Sep 17 00:00:00 2001 From: Ivo Hedtke Date: Wed, 9 Aug 2023 15:26:31 +0200 Subject: [PATCH 2/5] Extend std::optional to all addVar(s) methods --- include/scippp/model.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/scippp/model.hpp b/include/scippp/model.hpp index 1d821867..43b75376 100644 --- a/include/scippp/model.hpp +++ b/include/scippp/model.hpp @@ -87,16 +87,16 @@ class Model { * @param name of the variable when the model is written. * @param coeff Coefficient in the objective function. * @param varType variable type. - * @param lb lower bound. - * @param ub upper bound. + * @param lb lower bound. \c std::nullopt is interpreted as -infinity. + * @param ub upper bound. \c std::nullopt is interpreted as infinity. * @return Reference to the newly created variable. */ Var& addVar( const std::string& name, SCIP_Real coeff = 0.0, VarType varType = VarType::CONTINUOUS, - std::optional lb = 0.0, - std::optional ub = 1.0); + std::optional lb = 0.0, + std::optional ub = 1.0); /** * Adds multiple variables to the model. @@ -107,8 +107,8 @@ class Model { * @param numVars number of variables to create. * @param coeffs Object holding the coefficients for the objective function. * @param varType variable type. - * @param lb lower bound. - * @param ub upper bound. + * @param lb lower bound. \c std::nullopt is interpreted as -infinity. + * @param ub upper bound. \c std::nullopt is interpreted as infinity. * @return Vector of variables. */ template @@ -117,8 +117,8 @@ class Model { size_t numVars, const CoeffType& coeffs = COEFF_ZERO, VarType varType = VarType::CONTINUOUS, - std::optional lb = 0.0, - std::optional ub = 1.0) + std::optional lb = 0.0, + std::optional ub = 1.0) { std::vector result; result.reserve(numVars); @@ -150,8 +150,8 @@ class Model { const std::string& prefix, const CoeffType& coeffs = COEFF_ZERO, VarType varType = VarType::CONTINUOUS, - SCIP_Real lb = 0.0, - SCIP_Real ub = 1.0) + std::optional lb = 0.0, + std::optional ub = 1.0) { std::array result; auto vec { addVars(prefix, NumVars, coeffs, varType, lb, ub) }; From b459a6191f971b128c0fa643fcb7fec5768edc0f Mon Sep 17 00:00:00 2001 From: Ivo Hedtke Date: Wed, 9 Aug 2023 15:27:17 +0200 Subject: [PATCH 3/5] Revert change of testcase GetSolVal --- test/test_var.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/test_var.cpp b/test/test_var.cpp index 66c2f6b1..41cd008f 100644 --- a/test/test_var.cpp +++ b/test/test_var.cpp @@ -1,8 +1,6 @@ #include -#include #include "scippp/model.hpp" -#include "scippp/parameters.hpp" using namespace scippp; using namespace std; @@ -12,7 +10,7 @@ BOOST_AUTO_TEST_SUITE(Var) BOOST_AUTO_TEST_CASE(GetSolVal, *boost::unit_test::tolerance(1e-3)) { Model model("Simple"); - auto x1 = model.addVar("x_1", 1, VarType::CONTINUOUS, 0.0, std::nullopt); + auto x1 = model.addVar("x_1", 1); auto x2 = model.addVar("x_2", 1); model.addConstr(x1 + x2 >= 1, "capacity"); model.addConstr(x1 == x2, "equal"); From 1d65cf2d46bd35c0cc78a85f6ae2a9a6daa26908 Mon Sep 17 00:00:00 2001 From: Ivo Hedtke Date: Wed, 9 Aug 2023 15:28:02 +0200 Subject: [PATCH 4/5] Add test cases for nullopt lower and upper bounds --- test/test_add_var.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 test/test_add_var.cpp diff --git a/test/test_add_var.cpp b/test/test_add_var.cpp new file mode 100644 index 00000000..9839e2fb --- /dev/null +++ b/test/test_add_var.cpp @@ -0,0 +1,78 @@ +#include + +#include "scippp/model.hpp" + +using namespace scippp; +using namespace std; + +BOOST_AUTO_TEST_SUITE(AddVar) + +// lb nullopt ub value lNuD +// lb nullopt ub nullopt lNuN +// lb value ub value GetSolVal +// lb value ub nullopt lDuN + +const SCIP_Real LB_DEFAULT { 0.0 }; +const SCIP_Real UB_DEFAULT { 1.0 }; + +BOOST_AUTO_TEST_CASE(lDuN, *boost::unit_test::tolerance(1e-3)) +{ + Model m1("Simple"); + auto x1 = m1.addVar("x_1", 1, VarType::CONTINUOUS, LB_DEFAULT, nullopt); + auto x2 = m1.addVar("x_2", 1); + m1.addConstr(x1 + x2 <= 1, "line"); + m1.setObjsense(Sense::MINIMIZE); + m1.solve(); + BOOST_REQUIRE(m1.getNSols() > 0); + BOOST_TEST(m1.getPrimalbound() == 0); + + Model m2("Simple"); + x1 = m2.addVar("x_1", 1, VarType::CONTINUOUS, LB_DEFAULT, nullopt); + x2 = m2.addVar("x_2", 1); + m2.addConstr(x1 + x2 >= 1, "line"); + m2.setObjsense(Sense::MAXIMIZE); + m2.solve(); + BOOST_TEST(m2.getStatus() == SCIP_STATUS_UNBOUNDED); +} + +BOOST_AUTO_TEST_CASE(lNuD, *boost::unit_test::tolerance(1e-3)) +{ + Model m1("Simple"); + auto x1 = m1.addVar("x_1", 1, VarType::CONTINUOUS, nullopt, UB_DEFAULT); + auto x2 = m1.addVar("x_2", 1); + m1.addConstr(x1 + x2 <= 1, "line"); + m1.setObjsense(Sense::MINIMIZE); + m1.solve(); + BOOST_TEST(m1.getStatus() == SCIP_STATUS_UNBOUNDED); + + Model m2("Simple"); + x1 = m2.addVar("x_1", 1, VarType::CONTINUOUS, nullopt, UB_DEFAULT); + x2 = m2.addVar("x_2", 1); + m2.addConstr(x1 + x2 <= 1, "line"); + m2.setObjsense(Sense::MAXIMIZE); + m2.solve(); + BOOST_REQUIRE(m2.getNSols() > 0); + BOOST_TEST(m2.getPrimalbound() == 1); +} + +BOOST_AUTO_TEST_CASE(lNuN, *boost::unit_test::tolerance(1e-3)) +{ + Model m1("Simple"); + auto x1 = m1.addVar("x_1", 1, VarType::CONTINUOUS, nullopt, nullopt); + auto x2 = m1.addVar("x_2", 1); + m1.addConstr(x1 + x2 <= 1, "line"); + m1.setObjsense(Sense::MINIMIZE); + m1.solve(); + BOOST_TEST(m1.getStatus() == SCIP_STATUS_UNBOUNDED); + + Model m2("Simple"); + x1 = m2.addVar("x_1", 1, VarType::CONTINUOUS, nullopt, nullopt); + x2 = m2.addVar("x_2", 1); + m2.addConstr(x1 + x2 <= 1, "line"); + m2.setObjsense(Sense::MAXIMIZE); + m2.solve(); + BOOST_REQUIRE(m2.getNSols() > 0); + BOOST_TEST(m2.getPrimalbound() == 1); +} + +BOOST_AUTO_TEST_SUITE_END() From 8c176f7893aa0b05024f08e4f314a336da08ab0b Mon Sep 17 00:00:00 2001 From: Ivo Hedtke Date: Wed, 9 Aug 2023 15:32:16 +0200 Subject: [PATCH 5/5] Replace double by SCIP_Real in model.cpp --- source/model.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/model.cpp b/source/model.cpp index a015134b..5f06d078 100644 --- a/source/model.cpp +++ b/source/model.cpp @@ -6,7 +6,12 @@ namespace scippp { -Var& Model::addVar(const std::string& name, SCIP_Real coeff, VarType varType, std::optional lb, std::optional ub) +Var& Model::addVar( + const std::string& name, + SCIP_Real coeff, + VarType varType, + std::optional lb, + std::optional ub) { SCIP_VAR* var { nullptr }; m_scipCallWrapper(SCIPcreateVarBasic(