From 2d77d8721ba8bd3d02c3b04d4cc7ad2435c42579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Mar=C3=A9chal?= <45510813+JasonMarechal25@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:07:36 +0200 Subject: [PATCH] [ANT-2206] Parse yaml (#2433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Parse user models described as CPP - Expect to read one library per content - Only accept yaml content as std::string - Output object is Antares::Solver::ModelParser::Library - CMake : remove WITH_YAMLCPP (always ON) --------- Co-authored-by: Florian Omnès --- src/CMakeLists.txt | 3 - src/solver/CMakeLists.txt | 30 +- src/solver/expressions/CMakeLists.txt | 11 +- src/solver/modelParser/CMakeLists.txt | 27 + src/solver/modelParser/encoders.hxx | 167 ++++++ .../antares/solver/modelParser/model.h | 91 +++ .../antares/solver/modelParser/parser.h | 36 ++ src/solver/modelParser/parser.cpp | 38 ++ src/tests/src/libs/antares/CMakeLists.txt | 4 +- src/tests/src/solver/CMakeLists.txt | 9 +- .../src/solver/expressions/CMakeLists.txt | 4 +- .../src/solver/modelParser/CMakeLists.txt | 23 + .../solver/modelParser/testModelParser.cpp | 521 ++++++++++++++++++ src/vcpkg.json | 7 +- 14 files changed, 938 insertions(+), 33 deletions(-) create mode 100644 src/solver/modelParser/CMakeLists.txt create mode 100644 src/solver/modelParser/encoders.hxx create mode 100644 src/solver/modelParser/include/antares/solver/modelParser/model.h create mode 100644 src/solver/modelParser/include/antares/solver/modelParser/parser.h create mode 100644 src/solver/modelParser/parser.cpp create mode 100644 src/tests/src/solver/modelParser/CMakeLists.txt create mode 100644 src/tests/src/solver/modelParser/testModelParser.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 43358fa472..e93c5fcd58 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,9 +186,6 @@ message(STATUS "Build OR-Tools: ${BUILD_ORTOOLS}") option(WITH_ANTLR4 "With antlr4" OFF) message(STATUS "With antlr4: ${WITH_ANTLR4}") -option(WITH_YAMLCPP "With yaml-cpp" OFF) -message(STATUS "With yaml-cpp: ${WITH_YAMLCPP}") - option(BUILD_MERSENNE_TWISTER_PYBIND11 "Build pybind11 bindings for Mersenne-Twister" OFF) if (${BUILD_MERSENNE_TWISTER_PYBIND11}) find_package(pybind11 REQUIRED) diff --git a/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt index 28b51b11bd..d579606350 100644 --- a/src/solver/CMakeLists.txt +++ b/src/solver/CMakeLists.txt @@ -9,19 +9,20 @@ endif (MSVC) add_subdirectory(application) add_subdirectory(constraints-builder) +add_subdirectory(expressions) add_subdirectory(hydro) add_subdirectory(infeasible-problem-analysis) +add_subdirectory(libModelObject) add_subdirectory(lps) add_subdirectory(misc) +add_subdirectory(modelParser) +add_subdirectory(modeler) add_subdirectory(optimisation) add_subdirectory(signal-handling) add_subdirectory(simulation) add_subdirectory(ts-generator) add_subdirectory(utils) add_subdirectory(variable) -add_subdirectory(modeler) -add_subdirectory(expressions) -add_subdirectory(libModelObject) # # Resource file for Windows @@ -56,25 +57,26 @@ add_library(solver-lib INTERFACE add_executable(antares-solver main.cpp ${SRCS} + modelParser/encoders.hxx ) set_target_properties(antares-solver PROPERTIES OUTPUT_NAME ${exec_name}) set(ANTARES_SOLVER_LIBS - Antares::args_helper - Antares::date - Antares::benchmarking - Antares::result_writer - Antares::sys - Antares::infoCollection - Antares::checks - Antares::misc + Antares::args_helper + Antares::date + Antares::benchmarking + Antares::result_writer + Antares::sys + Antares::infoCollection + Antares::checks + Antares::misc Antares::optimization-options Antares::signal-handling Antares::locale - yuni-static-uuid - yuni-static-core - ${CMAKE_THREADS_LIBS_INIT} + yuni-static-uuid + yuni-static-core + ${CMAKE_THREADS_LIBS_INIT} ) set(ANTARES_SOLVER_LIBS ${ANTARES_SOLVER_LIBS} diff --git a/src/solver/expressions/CMakeLists.txt b/src/solver/expressions/CMakeLists.txt index df56047769..5f30a6779d 100644 --- a/src/solver/expressions/CMakeLists.txt +++ b/src/solver/expressions/CMakeLists.txt @@ -68,26 +68,27 @@ set(SRC_Expressions ) source_group("expressions" FILES ${SRC_Expressions}) -add_library(antares-solver-expressions +add_library(solver-expressions ${SRC_Expressions}) +add_library(Antares::solver-expressions ALIAS solver-expressions) -target_include_directories(antares-solver-expressions +target_include_directories(solver-expressions PUBLIC $ ) -target_link_libraries(antares-solver-expressions +target_link_libraries(solver-expressions PUBLIC Antares::logs Boost::headers ) -add_library(antares-solver-expressions-iterators +add_library(solver-expressions-iterators iterators/pre-order.cpp include/antares/solver/expressions/iterators/pre-order.h ) -target_link_libraries(antares-solver-expressions-iterators PRIVATE antares-solver-expressions) +target_link_libraries(solver-expressions-iterators PRIVATE solver-expressions) install(DIRECTORY include/antares DESTINATION "include" diff --git a/src/solver/modelParser/CMakeLists.txt b/src/solver/modelParser/CMakeLists.txt new file mode 100644 index 0000000000..efc5baca38 --- /dev/null +++ b/src/solver/modelParser/CMakeLists.txt @@ -0,0 +1,27 @@ +find_package(yaml-cpp REQUIRED) + +set(SOURCES + parser.cpp + #encoders.hxx + include/antares/solver/modelParser/parser.h +) + +# Create the library +add_library(modelParser STATIC ${SOURCES}) +add_library(Antares::modelParser ALIAS modelParser) + +# Specify include directories +target_include_directories(modelParser + PUBLIC + $ +) + +# Link dependencies (if any) +target_link_libraries(modelParser + PRIVATE + yaml-cpp +) + +install(DIRECTORY include/antares + DESTINATION "include" +) \ No newline at end of file diff --git a/src/solver/modelParser/encoders.hxx b/src/solver/modelParser/encoders.hxx new file mode 100644 index 0000000000..61e22e9bc9 --- /dev/null +++ b/src/solver/modelParser/encoders.hxx @@ -0,0 +1,167 @@ + +/* + * 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 . + */ + +#pragma once + +#include "antares/solver/modelParser/model.h" + +#include "yaml-cpp/yaml.h" + +// Implement convert specializations +namespace YAML +{ +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::Parameter& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.name = node["name"].as(); + rhs.time_dependent = node["time-dependent"].as(); + rhs.scenario_dependent = node["scenario-dependent"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::Variable& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.name = node["name"].as(); + rhs.lower_bound = node["lower-bound"].as(); + rhs.upper_bound = node["upper-bound"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::Port& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.name = node["name"].as(); + rhs.type = node["type"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::PortFieldDefinition& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.port = node["port"].as(); + rhs.field = node["field"].as(); + rhs.definition = node["definition"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::Constraint& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.name = node["name"].as(); + rhs.expression = node["expression"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::Model& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.id = node["id"].as(); + rhs.description = node["description"].as(); + rhs.parameters = node["parameters"] + .as>(); + rhs.variables = node["variables"].as>(); + rhs.ports = node["ports"].as>(); + rhs.port_field_definitions = node["port-field-definitions"] + .as>(); + rhs.constraints = node["constraints"] + .as>(); + rhs.objective = node["objective"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::PortType& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.id = node["id"].as(); + rhs.description = node["description"].as(); + for (const auto& field: node["fields"]) + { + rhs.fields.push_back(field["name"].as()); + } + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelParser::Library& rhs) + { + rhs.id = node["id"].as(); + rhs.description = node["description"].as(); + rhs.port_types = node["port-types"] + .as>(); + rhs.models = node["models"].as>(); + return true; + } +}; +} // namespace YAML diff --git a/src/solver/modelParser/include/antares/solver/modelParser/model.h b/src/solver/modelParser/include/antares/solver/modelParser/model.h new file mode 100644 index 0000000000..44b15584f5 --- /dev/null +++ b/src/solver/modelParser/include/antares/solver/modelParser/model.h @@ -0,0 +1,91 @@ + +/* + * 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 . + */ + +#pragma once +#include +#include + +namespace Antares::Solver::ModelParser +{ +// Define structures +struct Parameter +{ + std::string name; + bool time_dependent; + bool scenario_dependent; +}; + +struct Variable +{ + std::string name; + double lower_bound; + double upper_bound; +}; + +struct Port +{ + std::string name; + std::string type; +}; + +struct PortFieldDefinition +{ + std::string port; + std::string field; + std::string definition; +}; + +struct Constraint +{ + std::string name; + std::string expression; +}; + +struct Model +{ + std::string id; + std::string description; + std::vector parameters; + std::vector variables; + std::vector ports; + std::vector port_field_definitions; + std::vector constraints; + std::string objective; +}; + +struct PortType +{ + std::string id; + std::string description; + // Small optimization: we only need the name of the fields + // No need for an intermediate struct "field" with just a string "name" member + std::vector fields; +}; + +struct Library +{ + std::string id; + std::string description; + std::vector port_types; + std::vector models; +}; +} // namespace Antares::Solver::ModelParser diff --git a/src/solver/modelParser/include/antares/solver/modelParser/parser.h b/src/solver/modelParser/include/antares/solver/modelParser/parser.h new file mode 100644 index 0000000000..1447af9f2b --- /dev/null +++ b/src/solver/modelParser/include/antares/solver/modelParser/parser.h @@ -0,0 +1,36 @@ + +/* + * 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 . + */ + +#pragma once +#include "antares/solver/modelParser/model.h" + +namespace Antares::Solver::ModelParser +{ +class Parser +{ +public: + Parser() = default; + ~Parser() = default; + + Library parse(const std::string& content); +}; +} // namespace Antares::Solver::ModelParser diff --git a/src/solver/modelParser/parser.cpp b/src/solver/modelParser/parser.cpp new file mode 100644 index 0000000000..f4c1f9e515 --- /dev/null +++ b/src/solver/modelParser/parser.cpp @@ -0,0 +1,38 @@ +/* + * 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 . + */ + +#include "antares/solver/modelParser/parser.h" + +#include "antares/solver/modelParser/model.h" + +#include "encoders.hxx" + +namespace Antares::Solver::ModelParser +{ +Library Parser::parse(const std::string& content) +{ + YAML::Node root = YAML::Load(content); + + Library library = root["library"].as(); + + return library; +} +} // namespace Antares::Solver::ModelParser diff --git a/src/tests/src/libs/antares/CMakeLists.txt b/src/tests/src/libs/antares/CMakeLists.txt index 875ff5e374..654f897b0a 100644 --- a/src/tests/src/libs/antares/CMakeLists.txt +++ b/src/tests/src/libs/antares/CMakeLists.txt @@ -4,9 +4,7 @@ add_subdirectory(study) add_subdirectory(benchmarking) add_subdirectory(inifile) -if(WITH_YAMLCPP) - add_subdirectory(yaml-parser) -endif() +add_subdirectory(yaml-parser) if(WITH_ANTLR4) add_subdirectory(antlr4-interface) diff --git a/src/tests/src/solver/CMakeLists.txt b/src/tests/src/solver/CMakeLists.txt index bf920cb80b..2152a8e1bf 100644 --- a/src/tests/src/solver/CMakeLists.txt +++ b/src/tests/src/solver/CMakeLists.txt @@ -1,7 +1,8 @@ -add_subdirectory(simulation) -add_subdirectory(optimisation) -add_subdirectory(utils) +add_subdirectory(expressions) add_subdirectory(infeasible-problem-analysis) add_subdirectory(lps) +add_subdirectory(modelParser) add_subdirectory(modeler) -add_subdirectory(expressions) +add_subdirectory(optimisation) +add_subdirectory(simulation) +add_subdirectory(utils) diff --git a/src/tests/src/solver/expressions/CMakeLists.txt b/src/tests/src/solver/expressions/CMakeLists.txt index 319e961a8d..4eeca6d0fe 100644 --- a/src/tests/src/solver/expressions/CMakeLists.txt +++ b/src/tests/src/solver/expressions/CMakeLists.txt @@ -19,8 +19,8 @@ target_sources(${EXECUTABLE_NAME} target_link_libraries(${EXECUTABLE_NAME} PRIVATE Boost::unit_test_framework - antares-solver-expressions - antares-solver-expressions-iterators + solver-expressions + solver-expressions-iterators ) # Storing tests-ts-numbers under the folder Unit-tests in the IDE diff --git a/src/tests/src/solver/modelParser/CMakeLists.txt b/src/tests/src/solver/modelParser/CMakeLists.txt new file mode 100644 index 0000000000..11123853b0 --- /dev/null +++ b/src/tests/src/solver/modelParser/CMakeLists.txt @@ -0,0 +1,23 @@ +# Add source files +set(SOURCE_FILES + testModelParser.cpp +) + +# Add executable +add_executable(TestModelParser ${SOURCE_FILES}) + +# Link libraries +target_link_libraries(TestModelParser + PRIVATE + Boost::unit_test_framework + Antares::modelParser +) + +# Storing test-toybox under the folder Unit-tests in the IDE +set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) + +# Add the test +add_test(NAME TestModelParser COMMAND TestModelParser) + +# Set test properties +set_property(TEST TestModelParser PROPERTY LABELS unit) \ No newline at end of file diff --git a/src/tests/src/solver/modelParser/testModelParser.cpp b/src/tests/src/solver/modelParser/testModelParser.cpp new file mode 100644 index 0000000000..dff40144fb --- /dev/null +++ b/src/tests/src/solver/modelParser/testModelParser.cpp @@ -0,0 +1,521 @@ +/* + * 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 modelParser + +#define WIN32_LEAN_AND_MEAN + +#include + +#include "antares/solver/modelParser/parser.h" + +using namespace std::string_literals; + +// Test empty library +BOOST_AUTO_TEST_CASE(test_empty_library) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "" + description: "" + port-types: [] + models: [] + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_CHECK(libraryObj.id.empty()); + BOOST_CHECK(libraryObj.description.empty()); + BOOST_CHECK(libraryObj.port_types.empty()); + BOOST_CHECK(libraryObj.models.empty()); +} + +// Test library with id and description +BOOST_AUTO_TEST_CASE(test_library_id_description) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "test_id" + description: "test_description" + port-types: [] + models: [] + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_CHECK_EQUAL(libraryObj.id, "test_id"); + BOOST_CHECK_EQUAL(libraryObj.description, "test_description"); + BOOST_CHECK(libraryObj.port_types.empty()); + BOOST_CHECK(libraryObj.models.empty()); +} + +// Test library with port types +BOOST_AUTO_TEST_CASE(test_library_port_types) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: + - id: "porttype_id" + description: "porttype_description" + fields: + - name: "port_name" + models: [] + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.port_types.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.port_types[0].id, "porttype_id"); + BOOST_CHECK_EQUAL(libraryObj.port_types[0].description, "porttype_description"); + BOOST_REQUIRE_EQUAL(libraryObj.port_types[0].fields.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.port_types[0].fields[0], "port_name"); +} + +// Test library with multiple port types +BOOST_AUTO_TEST_CASE(test_library_multiple_port_types) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: + - id: "porttype_id1" + description: "porttype_description1" + fields: + - name: "port_name1" + - id: "porttype_id2" + description: "porttype_description2" + fields: + - name: "port_name2" + models: [] + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.port_types.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.port_types[0].id, "porttype_id1"); + BOOST_CHECK_EQUAL(libraryObj.port_types[0].description, "porttype_description1"); + BOOST_REQUIRE_EQUAL(libraryObj.port_types[0].fields.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.port_types[0].fields[0], "port_name1"); + BOOST_CHECK_EQUAL(libraryObj.port_types[1].id, "porttype_id2"); + BOOST_CHECK_EQUAL(libraryObj.port_types[1].description, "porttype_description2"); + BOOST_REQUIRE_EQUAL(libraryObj.port_types[1].fields.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.port_types[1].fields[0], "port_name2"); +} + +// Test library with models +BOOST_AUTO_TEST_CASE(test_library_models) +{ + Antares::Solver::ModelParser::Parser parser; + const std::string library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].id, "model_id"); + BOOST_CHECK_EQUAL(libraryObj.models[0].description, "model_description"); + auto& model = libraryObj.models[0]; + BOOST_CHECK(model.parameters.empty()); + BOOST_CHECK(model.variables.empty()); + BOOST_CHECK(model.ports.empty()); + BOOST_CHECK(model.port_field_definitions.empty()); + BOOST_CHECK(model.constraints.empty()); + BOOST_CHECK_EQUAL(libraryObj.models[0].objective, "objective"); +} + +// Test library with multiple models +BOOST_AUTO_TEST_CASE(test_library_multiple_models) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id1" + description: "model_description1" + parameters: [] + variables: [] + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective1" + - id: "model_id2" + description: "model_description2" + parameters: [] + variables: [] + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective2" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.models[0].id, "model_id1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].description, "model_description1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].objective, "objective1"); + BOOST_CHECK_EQUAL(libraryObj.models[1].id, "model_id2"); + BOOST_CHECK_EQUAL(libraryObj.models[1].description, "model_description2"); + BOOST_CHECK_EQUAL(libraryObj.models[1].objective, "objective2"); +} + +// Test library with one model containing parameters +BOOST_AUTO_TEST_CASE(test_library_model_parameters) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: + - name: "param_name" + time-dependent: false + scenario-dependent: false + variables: [] + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].parameters.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[0].name, "param_name"); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[0].time_dependent, false); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[0].scenario_dependent, false); +} + +// Test library with one model containing multiple parameters +BOOST_AUTO_TEST_CASE(test_library_model_multiple_parameters) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: + - name: "param_name1" + time-dependent: false + scenario-dependent: false + - name: "param_name2" + time-dependent: true + scenario-dependent: true + variables: [] + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].parameters.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[0].name, "param_name1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[0].time_dependent, false); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[0].scenario_dependent, false); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[1].name, "param_name2"); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[1].time_dependent, true); + BOOST_CHECK_EQUAL(libraryObj.models[0].parameters[1].scenario_dependent, true); +} + +// Test library with one model containing variables +BOOST_AUTO_TEST_CASE(test_library_model_variables) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: + - name: "var_name" + lower-bound: 0 + upper-bound: 1 + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].variables.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[0].name, "var_name"); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[0].lower_bound, 0); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[0].upper_bound, 1); +} + +// Test library with one model containing multiple variables +BOOST_AUTO_TEST_CASE(test_library_model_multiple_variables) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: + - name: "var_name1" + lower-bound: 0 + upper-bound: 1 + - name: "var_name2" + lower-bound: -1 + upper-bound: 2 + ports: [] + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].variables.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[0].name, "var_name1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[0].lower_bound, 0); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[0].upper_bound, 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[1].name, "var_name2"); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[1].lower_bound, -1); + BOOST_CHECK_EQUAL(libraryObj.models[0].variables[1].upper_bound, 2); +} + +// Test library with one model containing ports +BOOST_AUTO_TEST_CASE(test_library_model_ports) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: + - name: "port_name" + type: "port_type" + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].ports.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].ports[0].name, "port_name"); + BOOST_CHECK_EQUAL(libraryObj.models[0].ports[0].type, "port_type"); +} + +// Test library with one model containing multiple ports +BOOST_AUTO_TEST_CASE(test_library_model_multiple_ports) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: + - name: "port_name1" + type: "port_type1" + - name: "port_name2" + type: "port_type2" + port-field-definitions: [] + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].ports.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.models[0].ports[0].name, "port_name1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].ports[0].type, "port_type1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].ports[1].name, "port_name2"); + BOOST_CHECK_EQUAL(libraryObj.models[0].ports[1].type, "port_type2"); +} + +// Test library with one model containing port field definitions +BOOST_AUTO_TEST_CASE(test_library_model_port_field_definitions) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: [] + port-field-definitions: + - port: "port_name" + field: "field_name" + definition: "definition" + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].port_field_definitions.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[0].port, "port_name"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[0].field, "field_name"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[0].definition, "definition"); +} + +// Test library with one model containing multiple port field definitions +BOOST_AUTO_TEST_CASE(test_library_model_multiple_port_field_definitions) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: [] + port-field-definitions: + - port: "port_name1" + field: "field_name1" + definition: "definition1" + - port: "port_name2" + field: "field_name2" + definition: "definition2" + constraints: [] + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].port_field_definitions.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[0].port, "port_name1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[0].field, "field_name1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[0].definition, "definition1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[1].port, "port_name2"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[1].field, "field_name2"); + BOOST_CHECK_EQUAL(libraryObj.models[0].port_field_definitions[1].definition, "definition2"); +} + +// Test library with one model containing constraints +BOOST_AUTO_TEST_CASE(test_library_model_constraints) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: [] + port-field-definitions: [] + constraints: + - name: "constraint_name" + expression: "expression" + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].constraints.size(), 1); + BOOST_CHECK_EQUAL(libraryObj.models[0].constraints[0].name, "constraint_name"); + BOOST_CHECK_EQUAL(libraryObj.models[0].constraints[0].expression, "expression"); +} + +// Test library with one model containing multiple constraints +BOOST_AUTO_TEST_CASE(test_library_model_multiple_constraints) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: + - id: "model_id" + description: "model_description" + parameters: [] + variables: [] + ports: [] + port-field-definitions: [] + constraints: + - name: "constraint_name1" + expression: "expression1" + - name: "constraint_name2" + expression: "expression2" + objective: "objective" + )"s; + Antares::Solver::ModelParser::Library libraryObj = parser.parse(library); + BOOST_REQUIRE_EQUAL(libraryObj.models.size(), 1); + BOOST_REQUIRE_EQUAL(libraryObj.models[0].constraints.size(), 2); + BOOST_CHECK_EQUAL(libraryObj.models[0].constraints[0].name, "constraint_name1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].constraints[0].expression, "expression1"); + BOOST_CHECK_EQUAL(libraryObj.models[0].constraints[1].name, "constraint_name2"); + BOOST_CHECK_EQUAL(libraryObj.models[0].constraints[1].expression, "expression2"); +} + +// Test error when model is not a map +BOOST_AUTO_TEST_CASE(test_error_model_not_map) +{ + Antares::Solver::ModelParser::Parser parser; + const auto library = R"( + library: + id: "lib_id" + description: "lib_description" + port-types: [] + models: "not a map" + )"s; + BOOST_CHECK_THROW(parser.parse(library), std::runtime_error); +} diff --git a/src/vcpkg.json b/src/vcpkg.json index 08acfb9e79..b87c13d7b3 100644 --- a/src/vcpkg.json +++ b/src/vcpkg.json @@ -12,8 +12,8 @@ }, "dependencies": [ { - "name": "sirius-solver", - "version>=": "1.5" + "name": "sirius-solver", + "version>=": "1.5" }, { "name": "wxwidgets", @@ -34,6 +34,9 @@ "features": [ "zlib" ] + }, + { + "name": "yaml-cpp" } ] }