diff --git a/src/solver/expressions/CMakeLists.txt b/src/solver/expressions/CMakeLists.txt index b165529a9c..2e917c4c79 100644 --- a/src/solver/expressions/CMakeLists.txt +++ b/src/solver/expressions/CMakeLists.txt @@ -16,6 +16,7 @@ set(SRC_Expressions visitors/TimeIndexVisitor.cpp visitors/PrintVisitor.cpp visitors/SubstitutionVisitor.cpp + visitors/PortfieldSubstitutionVisitor.cpp visitors/InvalidNode.cpp include/antares/solver/expressions/nodes/SumNode.h @@ -50,6 +51,7 @@ set(SRC_Expressions include/antares/solver/expressions/visitors/TimeIndexVisitor.h include/antares/solver/expressions/visitors/TimeIndex.h include/antares/solver/expressions/visitors/SubstitutionVisitor.h + include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h include/antares/solver/expressions/visitors/InvalidNode.h include/antares/solver/expressions/Registry.hxx @@ -67,6 +69,7 @@ target_include_directories(antares-solver-expressions target_link_libraries(antares-solver-expressions PUBLIC Antares::logs + Boost::headers ) diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h new file mode 100644 index 0000000000..bd4a23cfbb --- /dev/null +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h @@ -0,0 +1,59 @@ +/* +** 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 "antares/solver/expressions/visitors/CloneVisitor.h" + +namespace Antares::Solver::Visitors +{ + +struct KeyHasher +{ + std::size_t operator()(const Nodes::PortFieldNode& n) const; +}; + +/** + * @brief Represents the context for performing substitutions in a syntax tree. + */ +struct PortfieldSubstitutionContext +{ + std::unordered_map portfield; +}; + +/** + * @brief Represents a visitor for substituting portfield nodes in a syntax tree. + */ +class PortfieldSubstitutionVisitor: public CloneVisitor +{ +public: + PortfieldSubstitutionVisitor(Registry& registry, + PortfieldSubstitutionContext& ctx); + + PortfieldSubstitutionContext& ctx_; + std::string name() const override; + +private: + // Only override visit method for PortField, clone the rest + Nodes::Node* visit(const Nodes::PortFieldNode* node) override; +}; +} // namespace Antares::Solver::Visitors diff --git a/src/solver/expressions/visitors/PortfieldSubstitutionVisitor.cpp b/src/solver/expressions/visitors/PortfieldSubstitutionVisitor.cpp new file mode 100644 index 0000000000..8a91361c5a --- /dev/null +++ b/src/solver/expressions/visitors/PortfieldSubstitutionVisitor.cpp @@ -0,0 +1,61 @@ +/* +** 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 + +#include +#include + +namespace Antares::Solver::Visitors +{ + +PortfieldSubstitutionVisitor::PortfieldSubstitutionVisitor(Registry& registry, + PortfieldSubstitutionContext& ctx): + CloneVisitor(registry), + ctx_(ctx) +{ +} + +Nodes::Node* PortfieldSubstitutionVisitor::visit(const Nodes::PortFieldNode* node) +{ + if (auto it = ctx_.portfield.find(*node); it != ctx_.portfield.end()) + { + return it->second; + } + + return CloneVisitor::visit(node); +} + +std::string PortfieldSubstitutionVisitor::name() const +{ + return "PortfieldSubstitutionVisitor"; +} + +std::size_t KeyHasher::operator()(const Nodes::PortFieldNode& n) const +{ + std::size_t seed = 0; + + boost::hash_combine(seed, boost::hash_value(n.getPortName())); + boost::hash_combine(seed, boost::hash_value(n.getFieldName())); + + return seed; +} + +} // namespace Antares::Solver::Visitors diff --git a/src/tests/cucumber/conf.yaml b/src/tests/cucumber/conf.yaml new file mode 100644 index 0000000000..c6149dcba6 --- /dev/null +++ b/src/tests/cucumber/conf.yaml @@ -0,0 +1 @@ +antares-solver : /home/payetvin/Antares_Simulator/_build/solver/antares-solver \ No newline at end of file diff --git a/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp b/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp index 2dba4fbd3d..a13d2392a8 100644 --- a/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp +++ b/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include @@ -87,3 +89,55 @@ BOOST_FIXTURE_TEST_CASE(SubstitutionVisitor_name, Registry) BOOST_CHECK_EQUAL(substitutionVisitor.name(), "SubstitutionVisitor"); } BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(_PortfieldSubstitutionVisitor_) + +class SubstitutionFixture: public Registry +{ +public: + Node* originalExpression() + { + Node* port1 = create("port", "literal"); + Node* port2 = create("another port", "not a literal"); + Node* root = create(port1, port2); + return root; + } + + Node* expectedExpressionAfterSubstitution() + { + Node* node1 = create(10); + Node* port2 = create("another port", "not a literal"); + Node* root = create(node1, port2); + return root; + } + + Node* substitute(Node* original) + { + PortfieldSubstitutionContext ctx; + ctx.portfield.emplace(PortFieldNode("port", "literal"), create(10)); + + PortfieldSubstitutionVisitor sub(*this, ctx); + return sub.dispatch(original); + } +}; + +BOOST_FIXTURE_TEST_CASE(PortfieldSubstitutionVisitor_simple, SubstitutionFixture) + +{ + Node* original = originalExpression(); + Node* substituted = substitute(original); + Node* expected = expectedExpressionAfterSubstitution(); + + CompareVisitor cmp; + BOOST_CHECK(cmp.dispatch(substituted, expected)); +} + +BOOST_FIXTURE_TEST_CASE(PortfieldSubstitutionVisitor_name, Registry) +{ + PortfieldSubstitutionContext ctx; + + PortfieldSubstitutionVisitor substitutionVisitor(*this, ctx); + BOOST_CHECK_EQUAL(substitutionVisitor.name(), "PortfieldSubstitutionVisitor"); +} + +BOOST_AUTO_TEST_SUITE_END()