diff --git a/src/solver/modeler/api/CMakeLists.txt b/src/solver/modeler/api/CMakeLists.txt index 049c2dfa8e..41789ae9cb 100644 --- a/src/solver/modeler/api/CMakeLists.txt +++ b/src/solver/modeler/api/CMakeLists.txt @@ -1,4 +1,4 @@ -set(PROJ optim_api) +set(PROJ modeler_api) set(SRC_API include/antares/solver/modeler/api/mipVariable.h @@ -14,6 +14,7 @@ set(SRC_API include/antares/solver/modeler/api/linearProblemBuilder.h linearProblemData.cpp + linearProblemBuilder.cpp ) add_library(${PROJ} ${SRC_API}) diff --git a/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblem.h b/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblem.h index b997242ec7..38006291e0 100644 --- a/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblem.h +++ b/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblem.h @@ -47,10 +47,12 @@ class ILinearProblem /// Create a integer variable virtual IMipVariable* addIntVariable(double lb, double ub, const std::string& name) = 0; virtual IMipVariable* getVariable(const std::string& name) const = 0; + virtual int variableCount() const = 0; /// Add a bounded constraint to the problem virtual IMipConstraint* addConstraint(double lb, double ub, const std::string& name) = 0; virtual IMipConstraint* getConstraint(const std::string& name) const = 0; + virtual int constraintCount() const = 0; /// Set the objective coefficient for a given variable virtual void setObjectiveCoefficient(IMipVariable* var, double coefficient) = 0; diff --git a/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemBuilder.h b/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemBuilder.h index b4131d4f6b..c5b4419113 100644 --- a/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemBuilder.h +++ b/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemBuilder.h @@ -24,7 +24,6 @@ #include #include "linearProblemFiller.h" -#include "mipSolution.h" namespace Antares::Solver::Modeler::Api { @@ -32,9 +31,11 @@ namespace Antares::Solver::Modeler::Api class LinearProblemBuilder { public: - virtual void LinearProblemBuilder(std::vector fillers) = 0; - virtual void build(LinearProblemData* data) = 0; - virtual MipSolution* solve() = 0; + explicit LinearProblemBuilder(const std::vector& fillers); + void build(ILinearProblem& pb, LinearProblemData& data); + +private: + const std::vector& fillers_; }; } // namespace Antares::Solver::Modeler::Api diff --git a/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemFiller.h b/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemFiller.h index b337dea247..aad1fa3ce6 100644 --- a/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemFiller.h +++ b/src/solver/modeler/api/include/antares/solver/modeler/api/linearProblemFiller.h @@ -21,6 +21,8 @@ #pragma once +#include + #include #include @@ -30,9 +32,10 @@ namespace Antares::Solver::Modeler::Api class LinearProblemFiller { public: - virtual void addVariables(LinearProblem* problem, LinearProblemData* data) = 0; - virtual void addConstraints(LinearProblem* problem, LinearProblemData* data) = 0; - virtual void addObjectiveCoefficients(LinearProblem* problem, LinearProblemData* data) = 0; + virtual void addVariables(ILinearProblem& pb, LinearProblemData& data) = 0; + virtual void addConstraints(ILinearProblem& pb, LinearProblemData& data) = 0; + virtual void addObjective(ILinearProblem& pb, LinearProblemData& data) = 0; + virtual ~LinearProblemFiller() = default; }; } // namespace Antares::Solver::Modeler::Api diff --git a/src/solver/modeler/api/linearProblemBuilder.cpp b/src/solver/modeler/api/linearProblemBuilder.cpp new file mode 100644 index 0000000000..f9d6103152 --- /dev/null +++ b/src/solver/modeler/api/linearProblemBuilder.cpp @@ -0,0 +1,21 @@ +#include +#include + +#include + +namespace Antares::Solver::Modeler::Api +{ + +LinearProblemBuilder::LinearProblemBuilder(const std::vector& fillers): + fillers_(fillers) +{ +} + +void LinearProblemBuilder::build(ILinearProblem& pb, LinearProblemData& data) +{ + std::ranges::for_each(fillers_, [&](const auto& filler) { filler->addVariables(pb, data); }); + std::ranges::for_each(fillers_, [&](const auto& filler) { filler->addConstraints(pb, data); }); + std::ranges::for_each(fillers_, [&](const auto& filler) { filler->addObjective(pb, data); }); +} + +} // namespace Antares::Solver::Modeler::Api diff --git a/src/solver/modeler/ortoolsImpl/CMakeLists.txt b/src/solver/modeler/ortoolsImpl/CMakeLists.txt index ef94b552cc..309fb67fa8 100644 --- a/src/solver/modeler/ortoolsImpl/CMakeLists.txt +++ b/src/solver/modeler/ortoolsImpl/CMakeLists.txt @@ -23,7 +23,7 @@ add_library(Antares::${PROJ} ALIAS ${PROJ}) target_link_libraries(${PROJ} PUBLIC - Antares::optim_api + Antares::modeler_api Antares::logs Antares::solverUtils ortools::ortools diff --git a/src/solver/modeler/ortoolsImpl/include/antares/solver/modeler/ortoolsImpl/linearProblem.h b/src/solver/modeler/ortoolsImpl/include/antares/solver/modeler/ortoolsImpl/linearProblem.h index 6a34ccfcc5..d4e6e52c02 100644 --- a/src/solver/modeler/ortoolsImpl/include/antares/solver/modeler/ortoolsImpl/linearProblem.h +++ b/src/solver/modeler/ortoolsImpl/include/antares/solver/modeler/ortoolsImpl/linearProblem.h @@ -44,11 +44,12 @@ class OrtoolsLinearProblem final: public Api::ILinearProblem OrtoolsMipVariable* addNumVariable(double lb, double ub, const std::string& name) override; OrtoolsMipVariable* addIntVariable(double lb, double ub, const std::string& name) override; - OrtoolsMipVariable* getVariable(const std::string& name) const override; + int variableCount() const override; OrtoolsMipConstraint* addConstraint(double lb, double ub, const std::string& name) override; OrtoolsMipConstraint* getConstraint(const std::string& name) const override; + int constraintCount() const override; void setObjectiveCoefficient(Api::IMipVariable* var, double coefficient) override; double getObjectiveCoefficient(const Api::IMipVariable* var) const override; diff --git a/src/solver/modeler/ortoolsImpl/linearProblem.cpp b/src/solver/modeler/ortoolsImpl/linearProblem.cpp index 7c6593fa52..1d8bf981bc 100644 --- a/src/solver/modeler/ortoolsImpl/linearProblem.cpp +++ b/src/solver/modeler/ortoolsImpl/linearProblem.cpp @@ -93,6 +93,11 @@ OrtoolsMipVariable* OrtoolsLinearProblem::getVariable(const std::string& name) c return variables_.at(name).get(); } +int OrtoolsLinearProblem::variableCount() const +{ + return mpSolver_->NumVariables(); +} + OrtoolsMipConstraint* OrtoolsLinearProblem::addConstraint(double lb, double ub, const std::string& name) @@ -120,6 +125,11 @@ OrtoolsMipConstraint* OrtoolsLinearProblem::getConstraint(const std::string& nam return constraints_.at(name).get(); } +int OrtoolsLinearProblem::constraintCount() const +{ + return mpSolver_->NumConstraints(); +} + static const operations_research::MPVariable* getMpVar(const Api::IMipVariable* var) { diff --git a/src/tests/src/solver/modeler/api/CMakeLists.txt b/src/tests/src/solver/modeler/api/CMakeLists.txt index 0299f3ec0b..ae048140aa 100644 --- a/src/tests/src/solver/modeler/api/CMakeLists.txt +++ b/src/tests/src/solver/modeler/api/CMakeLists.txt @@ -1,6 +1,12 @@ -set(EXECUTABLE_NAME tests-modeler-api-ortools) -add_executable(${EXECUTABLE_NAME} testApiOrtoolsLinearProblem.cpp) +set(EXECUTABLE_NAME unit-tests-for-modeler-api) +add_executable(${EXECUTABLE_NAME}) +target_sources(${EXECUTABLE_NAME} + PRIVATE + test_main.cpp + testModelerLinearProblemWithOrtools.cpp + testModelerLPbuilder.cpp +) target_include_directories(${EXECUTABLE_NAME} PRIVATE "${src_solver_optimisation}" @@ -12,9 +18,7 @@ target_link_libraries(${EXECUTABLE_NAME} Antares::modeler-ortools-impl ) -# Storing tests-ts-numbers under the folder Unit-tests in the IDE set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) +add_test(NAME ${EXECUTABLE_NAME} COMMAND ${EXECUTABLE_NAME}) +set_property(TEST ${EXECUTABLE_NAME} PROPERTY LABELS unit) -add_test(NAME test-modeler-api-ortools COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-modeler-api-ortools PROPERTY LABELS unit) diff --git a/src/tests/src/solver/modeler/api/mock-fillers/OneConstraintFiller.h b/src/tests/src/solver/modeler/api/mock-fillers/OneConstraintFiller.h new file mode 100644 index 0000000000..cb1f9db3e9 --- /dev/null +++ b/src/tests/src/solver/modeler/api/mock-fillers/OneConstraintFiller.h @@ -0,0 +1,30 @@ +#pragma once + +#include "antares/solver/modeler/api/linearProblemFiller.h" + +namespace Antares::Solver::Modeler::Api +{ + +class OneConstraintFiller: public LinearProblemFiller +{ +public: + explicit OneConstraintFiller() = default; + void addVariables(ILinearProblem& pb, LinearProblemData& data) override; + void addConstraints(ILinearProblem& pb, LinearProblemData& data) override; + void addObjective(ILinearProblem& pb, LinearProblemData& data) override; +}; + +void OneConstraintFiller::addVariables(ILinearProblem& pb, LinearProblemData& data) +{ +} + +void OneConstraintFiller::addConstraints(ILinearProblem& pb, LinearProblemData& data) +{ + pb.addConstraint(1, 2, "constraint-by-OneConstraintFiller"); +} + +void OneConstraintFiller::addObjective(ILinearProblem& pb, LinearProblemData& data) +{ +} + +} // namespace Antares::Solver::Modeler::Api diff --git a/src/tests/src/solver/modeler/api/mock-fillers/OneVarFiller.h b/src/tests/src/solver/modeler/api/mock-fillers/OneVarFiller.h new file mode 100644 index 0000000000..5d2ba08b55 --- /dev/null +++ b/src/tests/src/solver/modeler/api/mock-fillers/OneVarFiller.h @@ -0,0 +1,35 @@ +#pragma once + +#include "antares/solver/modeler/api/linearProblemFiller.h" + +namespace Antares::Solver::Modeler::Api +{ + +class OneVarFiller: public LinearProblemFiller +{ +public: + explicit OneVarFiller() = default; + void addVariables(ILinearProblem& pb, LinearProblemData& data) override; + void addConstraints(ILinearProblem& pb, LinearProblemData& data) override; + void addObjective(ILinearProblem& pb, LinearProblemData& data) override; + +private: + std::string added_var_name_ = "var-by-OneVarFiller"; +}; + +void OneVarFiller::addVariables(ILinearProblem& pb, LinearProblemData& data) +{ + pb.addNumVariable(0, 1, added_var_name_); +} + +void OneVarFiller::addConstraints(ILinearProblem& pb, LinearProblemData& data) +{ +} + +void OneVarFiller::addObjective(ILinearProblem& pb, LinearProblemData& data) +{ + auto* var = pb.getVariable(added_var_name_); + pb.setObjectiveCoefficient(var, 1); +} + +} // namespace Antares::Solver::Modeler::Api diff --git a/src/tests/src/solver/modeler/api/mock-fillers/TwoVarsTwoConstraintsFiller.h b/src/tests/src/solver/modeler/api/mock-fillers/TwoVarsTwoConstraintsFiller.h new file mode 100644 index 0000000000..e8671644df --- /dev/null +++ b/src/tests/src/solver/modeler/api/mock-fillers/TwoVarsTwoConstraintsFiller.h @@ -0,0 +1,33 @@ +#pragma once + +#include "antares/solver/modeler/api/linearProblemFiller.h" + +namespace Antares::Solver::Modeler::Api +{ + +class TwoVarsTwoConstraintsFiller: public LinearProblemFiller +{ +public: + explicit TwoVarsTwoConstraintsFiller() = default; + void addVariables(ILinearProblem& pb, LinearProblemData& data) override; + void addConstraints(ILinearProblem& pb, LinearProblemData& data) override; + void addObjective(ILinearProblem& pb, LinearProblemData& data) override; +}; + +void TwoVarsTwoConstraintsFiller::addVariables(ILinearProblem& pb, LinearProblemData& data) +{ + pb.addNumVariable(0, 1, "var-1-by-TwoVarsTwoConstraintsFiller"); + pb.addNumVariable(0, 3, "var-2-by-TwoVarsTwoConstraintsFiller"); +} + +void TwoVarsTwoConstraintsFiller::addConstraints(ILinearProblem& pb, LinearProblemData& data) +{ + pb.addConstraint(1, 2, "constr-1-by-TwoVarsTwoConstraintsFiller"); + pb.addConstraint(1, 3, "constr-2-by-TwoVarsTwoConstraintsFiller"); +} + +void TwoVarsTwoConstraintsFiller::addObjective(ILinearProblem& pb, LinearProblemData& data) +{ +} + +} // namespace Antares::Solver::Modeler::Api diff --git a/src/tests/src/solver/modeler/api/testModelerLPbuilder.cpp b/src/tests/src/solver/modeler/api/testModelerLPbuilder.cpp new file mode 100644 index 0000000000..ccdccf251a --- /dev/null +++ b/src/tests/src/solver/modeler/api/testModelerLPbuilder.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2007-2024, RTE (https://www.rte-france.com) + * See AUTHORS.txt + * SPDX-License-Identifier: MPL-2.0 + * This file is part of Antares-Simulator, + * Adequacy and Performance assessment for interconnected energy networks. + * + * Antares_Simulator is free software: you can redistribute it and/or modify + * it under the terms of the Mozilla Public Licence 2.0 as published by + * the Mozilla Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Antares_Simulator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Mozilla Public Licence 2.0 for more details. + * + * You should have received a copy of the Mozilla Public Licence 2.0 + * along with Antares_Simulator. If not, see . + */ +#define WIN32_LEAN_AND_MEAN + +#include + +#include +#include + +#include "mock-fillers/OneConstraintFiller.h" +#include "mock-fillers/OneVarFiller.h" +#include "mock-fillers/TwoVarsTwoConstraintsFiller.h" + +using namespace Antares::Solver::Modeler::Api; +using namespace Antares::Solver::Modeler::OrtoolsImpl; + +struct Fixture +{ + Fixture() + { + pb = std::make_unique(false, "sirius"); + } + + std::vector fillers; + LinearProblemData LP_Data; + std::unique_ptr pb; +}; + +BOOST_AUTO_TEST_SUITE(tests_on_linear_problem_builder) + +BOOST_FIXTURE_TEST_CASE(no_filler_given_to_builder___nothing_built, Fixture) +{ + LinearProblemBuilder lpBuilder(fillers); + lpBuilder.build(*pb, LP_Data); + + BOOST_CHECK_EQUAL(pb->variableCount(), 0); + BOOST_CHECK_EQUAL(pb->constraintCount(), 0); +} + +BOOST_FIXTURE_TEST_CASE(one_var_filler___the_var_is_built, Fixture) +{ + auto oneVarFiller = std::make_unique(); + fillers = {oneVarFiller.get()}; + + LinearProblemBuilder lpBuilder(fillers); + lpBuilder.build(*pb, LP_Data); + + BOOST_CHECK_EQUAL(pb->variableCount(), 1); + BOOST_CHECK_EQUAL(pb->constraintCount(), 0); + auto* var = pb->getVariable("var-by-OneVarFiller"); + BOOST_CHECK(var); + BOOST_CHECK_EQUAL(pb->getObjectiveCoefficient(var), 1); +} + +BOOST_FIXTURE_TEST_CASE(one_constraint_filler___the_constraint_is_built, Fixture) +{ + auto oneConstrFiller = std::make_unique(); + fillers = {oneConstrFiller.get()}; + + LinearProblemBuilder lpBuilder(fillers); + lpBuilder.build(*pb, LP_Data); + + BOOST_CHECK_EQUAL(pb->variableCount(), 0); + BOOST_CHECK_EQUAL(pb->constraintCount(), 1); + BOOST_CHECK(pb->getConstraint("constraint-by-OneConstraintFiller")); +} + +BOOST_FIXTURE_TEST_CASE(two_fillers_given_to_builder___all_is_built, Fixture) +{ + auto oneVarFiller = std::make_unique(); + auto oneConstrFiller = std::make_unique(); + + fillers = {oneVarFiller.get(), oneConstrFiller.get()}; + + LinearProblemBuilder lpBuilder(fillers); + lpBuilder.build(*pb, LP_Data); + + BOOST_CHECK_EQUAL(pb->constraintCount(), 1); + BOOST_CHECK(pb->getConstraint("constraint-by-OneConstraintFiller")); + BOOST_CHECK_EQUAL(pb->variableCount(), 1); +} + +BOOST_FIXTURE_TEST_CASE(three_fillers_given_to_builder___3_vars_3_constr_are_built, Fixture) +{ + auto oneVarFiller = std::make_unique(); + auto oneConstrFiller = std::make_unique(); + auto twoVarsTwoConstrFiller = std::make_unique(); + fillers = {oneVarFiller.get(), oneConstrFiller.get(), twoVarsTwoConstrFiller.get()}; + + LinearProblemBuilder lpBuilder(fillers); + lpBuilder.build(*pb, LP_Data); + + BOOST_CHECK_EQUAL(pb->variableCount(), 3); + BOOST_CHECK_EQUAL(pb->constraintCount(), 3); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/solver/modeler/api/testApiOrtoolsLinearProblem.cpp b/src/tests/src/solver/modeler/api/testModelerLinearProblemWithOrtools.cpp similarity index 99% rename from src/tests/src/solver/modeler/api/testApiOrtoolsLinearProblem.cpp rename to src/tests/src/solver/modeler/api/testModelerLinearProblemWithOrtools.cpp index 06bbcb6669..7c1f8f84e3 100644 --- a/src/tests/src/solver/modeler/api/testApiOrtoolsLinearProblem.cpp +++ b/src/tests/src/solver/modeler/api/testModelerLinearProblemWithOrtools.cpp @@ -18,7 +18,6 @@ * You should have received a copy of the Mozilla Public Licence 2.0 * along with Antares_Simulator. If not, see . */ -#define BOOST_TEST_MODULE test modeler api ortools #define WIN32_LEAN_AND_MEAN diff --git a/src/tests/src/solver/modeler/api/test_main.cpp b/src/tests/src/solver/modeler/api/test_main.cpp new file mode 100644 index 0000000000..0d5864e717 --- /dev/null +++ b/src/tests/src/solver/modeler/api/test_main.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2007-2024, RTE (https://www.rte-france.com) + * See AUTHORS.txt + * SPDX-License-Identifier: MPL-2.0 + * This file is part of Antares-Simulator, + * Adequacy and Performance assessment for interconnected energy networks. + * + * Antares_Simulator is free software: you can redistribute it and/or modify + * it under the terms of the Mozilla Public Licence 2.0 as published by + * the Mozilla Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Antares_Simulator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Mozilla Public Licence 2.0 for more details. + * + * You should have received a copy of the Mozilla Public Licence 2.0 + * along with Antares_Simulator. If not, see . + */ + +#define BOOST_TEST_MODULE test modeler api + +#define WIN32_LEAN_AND_MEAN + +#include