From 8ce6107b7721213fd2cf987ac425bdb7fc143a19 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:46:48 +0200 Subject: [PATCH] Modeler 2.4c: PortFieldSum and substitution (#2415) Co-authored-by: Florian OMNES --- src/solver/expressions/CMakeLists.txt | 13 +++- src/solver/expressions/hashable.cpp | 49 +++++++++++++ .../antares/solver/expressions/hashable.h | 43 ++++++++++++ .../expressions/nodes/ExpressionsNodes.h | 1 + .../nodes/NodesForwardDeclaration.h | 1 + .../solver/expressions/nodes/PortFieldNode.h | 3 +- .../expressions/nodes/PortFieldSumNode.h | 68 ++++++++++++++++++ .../expressions/visitors/AstDOTStyleVisitor.h | 1 + .../expressions/visitors/CloneVisitor.h | 1 + .../expressions/visitors/CompareVisitor.h | 1 + .../solver/expressions/visitors/EvalVisitor.h | 1 + .../expressions/visitors/LinearityVisitor.h | 1 + .../solver/expressions/visitors/NodeVisitor.h | 11 +++ ...sitor.h => PortFieldSubstitutionVisitor.h} | 17 ++--- .../PortFieldSumSubstitutionVisitor.h | 57 +++++++++++++++ .../expressions/visitors/PrintVisitor.h | 1 + .../expressions/visitors/TimeIndexVisitor.h | 1 + .../expressions/nodes/PortFieldNode.cpp | 1 + .../expressions/nodes/PortFieldSumNode.cpp | 41 +++++++++++ .../visitors/AstDOTStyleVisitor.cpp | 9 +++ .../expressions/visitors/CloneVisitor.cpp | 12 +++- .../expressions/visitors/CompareVisitor.cpp | 5 ++ .../expressions/visitors/EvalVisitor.cpp | 5 ++ .../expressions/visitors/LinearityVisitor.cpp | 5 ++ ...r.cpp => PortFieldSubstitutionVisitor.cpp} | 23 ++---- .../PortFieldSumSubstitutionVisitor.cpp | 51 ++++++++++++++ .../expressions/visitors/PrintVisitor.cpp | 5 ++ .../expressions/visitors/TimeIndexVisitor.cpp | 5 ++ .../expressions/test_AstDOTStyleVisitor.cpp | 11 ++- .../expressions/test_CompareVisitor.cpp | 3 +- .../solver/expressions/test_LinearVisitor.cpp | 5 ++ .../expressions/test_PrintAndEvalNodes.cpp | 10 +++ .../expressions/test_SubstitutionVisitor.cpp | 70 +++++++++++++++++-- .../expressions/test_TimeIndexVisitor.cpp | 1 + .../src/solver/expressions/test_nodes.cpp | 13 +++- 35 files changed, 498 insertions(+), 47 deletions(-) create mode 100644 src/solver/expressions/hashable.cpp create mode 100644 src/solver/expressions/include/antares/solver/expressions/hashable.h create mode 100644 src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldSumNode.h rename src/solver/expressions/include/antares/solver/expressions/visitors/{PortfieldSubstitutionVisitor.h => PortFieldSubstitutionVisitor.h} (77%) create mode 100644 src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.h create mode 100644 src/solver/expressions/nodes/PortFieldSumNode.cpp rename src/solver/expressions/visitors/{PortfieldSubstitutionVisitor.cpp => PortFieldSubstitutionVisitor.cpp} (67%) create mode 100644 src/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.cpp diff --git a/src/solver/expressions/CMakeLists.txt b/src/solver/expressions/CMakeLists.txt index 0a222c2d49..df56047769 100644 --- a/src/solver/expressions/CMakeLists.txt +++ b/src/solver/expressions/CMakeLists.txt @@ -3,6 +3,7 @@ project(Expressions) set(SRC_Expressions nodes/PortFieldNode.cpp + nodes/PortFieldSumNode.cpp nodes/ComponentNode.cpp nodes/BinaryNode.cpp nodes/UnaryNode.cpp @@ -16,10 +17,13 @@ set(SRC_Expressions visitors/TimeIndexVisitor.cpp visitors/PrintVisitor.cpp visitors/SubstitutionVisitor.cpp + visitors/PortFieldSubstitutionVisitor.cpp + visitors/PortFieldSumSubstitutionVisitor.cpp visitors/AstDOTStyleVisitor.cpp - visitors/PortfieldSubstitutionVisitor.cpp visitors/InvalidNode.cpp + hashable.cpp + include/antares/solver/expressions/nodes/SumNode.h include/antares/solver/expressions/nodes/BinaryNode.h include/antares/solver/expressions/nodes/ComparisonNode.h @@ -37,6 +41,7 @@ set(SRC_Expressions include/antares/solver/expressions/nodes/NodesForwardDeclaration.h include/antares/solver/expressions/nodes/ParameterNode.h include/antares/solver/expressions/nodes/PortFieldNode.h + include/antares/solver/expressions/nodes/PortFieldSumNode.h include/antares/solver/expressions/nodes/SubtractionNode.h include/antares/solver/expressions/nodes/UnaryNode.h include/antares/solver/expressions/nodes/VariableNode.h @@ -52,12 +57,14 @@ 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/PortFieldSumSubstitutionVisitor.h include/antares/solver/expressions/visitors/AstDOTStyleVisitor.h - include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h include/antares/solver/expressions/visitors/InvalidNode.h include/antares/solver/expressions/Registry.hxx include/antares/solver/expressions/IName.h + include/antares/solver/expressions/hashable.h ) source_group("expressions" FILES ${SRC_Expressions}) @@ -72,7 +79,7 @@ target_link_libraries(antares-solver-expressions PUBLIC Antares::logs Boost::headers - ) +) add_library(antares-solver-expressions-iterators diff --git a/src/solver/expressions/hashable.cpp b/src/solver/expressions/hashable.cpp new file mode 100644 index 0000000000..3757ed4547 --- /dev/null +++ b/src/solver/expressions/hashable.cpp @@ -0,0 +1,49 @@ +/* +** 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 + +namespace Antares::Solver +{ + +Hashable::Hashable(const std::string& s1, const std::string& s2): + s1(s1), + s2(s2) +{ +} + +bool Hashable::operator==(const Hashable& other) const +{ + return s1 == other.s1 && s2 == other.s2; +} + +std::size_t PortFieldHash::operator()(const Hashable& n) const +{ + std::size_t seed = 0; + + boost::hash_combine(seed, boost::hash_value(n.s1)); + boost::hash_combine(seed, boost::hash_value(n.s2)); + + return seed; +} + +} // namespace Antares::Solver diff --git a/src/solver/expressions/include/antares/solver/expressions/hashable.h b/src/solver/expressions/include/antares/solver/expressions/hashable.h new file mode 100644 index 0000000000..1548d6be65 --- /dev/null +++ b/src/solver/expressions/include/antares/solver/expressions/hashable.h @@ -0,0 +1,43 @@ +/* +** 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 + +namespace Antares::Solver +{ +class Hashable +{ +public: + Hashable(const std::string& s1, const std::string& s2); + ~Hashable() = default; + + bool operator==(const Hashable& other) const; + + const std::string& s1; + const std::string& s2; +}; + +struct PortFieldHash +{ + std::size_t operator()(const Hashable& n) const; +}; + +} // namespace Antares::Solver diff --git a/src/solver/expressions/include/antares/solver/expressions/nodes/ExpressionsNodes.h b/src/solver/expressions/include/antares/solver/expressions/nodes/ExpressionsNodes.h index 1652e4003a..7909f5ffb6 100644 --- a/src/solver/expressions/include/antares/solver/expressions/nodes/ExpressionsNodes.h +++ b/src/solver/expressions/include/antares/solver/expressions/nodes/ExpressionsNodes.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/src/solver/expressions/include/antares/solver/expressions/nodes/NodesForwardDeclaration.h b/src/solver/expressions/include/antares/solver/expressions/nodes/NodesForwardDeclaration.h index eb637e1d15..f9124c3d91 100644 --- a/src/solver/expressions/include/antares/solver/expressions/nodes/NodesForwardDeclaration.h +++ b/src/solver/expressions/include/antares/solver/expressions/nodes/NodesForwardDeclaration.h @@ -39,4 +39,5 @@ class ComponentParameterNode; class ParameterNode; class VariableNode; class PortFieldNode; +class PortFieldSumNode; } // namespace Antares::Solver::Nodes diff --git a/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldNode.h b/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldNode.h index 32895d3be5..762f37a1c3 100644 --- a/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldNode.h +++ b/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldNode.h @@ -21,6 +21,7 @@ #pragma once #include +#include #include namespace Antares::Solver::Nodes @@ -28,7 +29,7 @@ namespace Antares::Solver::Nodes /** * @brief Represents a port field node in a syntax tree. */ -class PortFieldNode: public Node +class PortFieldNode: public Node, public Hashable { public: /** diff --git a/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldSumNode.h b/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldSumNode.h new file mode 100644 index 0000000000..eda6372e0f --- /dev/null +++ b/src/solver/expressions/include/antares/solver/expressions/nodes/PortFieldSumNode.h @@ -0,0 +1,68 @@ +/* +** 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 +#include + +namespace Antares::Solver::Nodes +{ +/** + * @brief Represents a port field node where the expression is a sum. + */ +class PortFieldSumNode: public Node, public Hashable +{ +public: + /** + * @brief Constructs a port field sum node with the specified port and field names. + * + * @param port_name The port name. + * @param field_name The field name. + */ + explicit PortFieldSumNode(const std::string& port_name, const std::string& field_name); + + /** + * @brief Retrieves the port name. + * + * @return The port name. + */ + const std::string& getPortName() const; + + /** + * @brief Retrieves the field name. + * + * @return The field name. + */ + const std::string& getFieldName() const; + + bool operator==(const PortFieldSumNode& other) const = default; + + std::string name() const override + { + return "PortFieldSumNode"; + } + +private: + std::string port_name_; + std::string field_name_; +}; +} // namespace Antares::Solver::Nodes diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/AstDOTStyleVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/AstDOTStyleVisitor.h index 8ca2e509c5..a8e4e1ff43 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/AstDOTStyleVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/AstDOTStyleVisitor.h @@ -131,6 +131,7 @@ class AstDOTStyleVisitor: public NodeVisitor void visit(const Nodes::ParameterNode* node, std::ostream& os) override; void visit(const Nodes::LiteralNode* node, std::ostream& os) override; void visit(const Nodes::PortFieldNode* node, std::ostream& os) override; + void visit(const Nodes::PortFieldSumNode* node, std::ostream& os) override; void visit(const Nodes::ComponentVariableNode* node, std::ostream& os) override; void visit(const Nodes::ComponentParameterNode* node, std::ostream& os) override; diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/CloneVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/CloneVisitor.h index 394a1449eb..ff5ac538a2 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/CloneVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/CloneVisitor.h @@ -51,6 +51,7 @@ class CloneVisitor: public NodeVisitor Nodes::Node* visit(const Nodes::ParameterNode* node) override; Nodes::Node* visit(const Nodes::LiteralNode* node) override; Nodes::Node* visit(const Nodes::PortFieldNode* node) override; + Nodes::Node* visit(const Nodes::PortFieldSumNode* node) override; Nodes::Node* visit(const Nodes::ComponentVariableNode* node) override; Nodes::Node* visit(const Nodes::ComponentParameterNode* node) override; diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/CompareVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/CompareVisitor.h index 446d538510..ec19095b02 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/CompareVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/CompareVisitor.h @@ -46,6 +46,7 @@ class CompareVisitor: public NodeVisitor bool visit(const Nodes::ParameterNode* param, const Nodes::Node* other) override; bool visit(const Nodes::LiteralNode* param, const Nodes::Node* other) override; bool visit(const Nodes::PortFieldNode* port_field_node, const Nodes::Node* other) override; + bool visit(const Nodes::PortFieldSumNode* port_field_node, const Nodes::Node* other) override; bool visit(const Nodes::ComponentVariableNode* component_node, const Nodes::Node* other) override; bool visit(const Nodes::ComponentParameterNode* component_node, diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/EvalVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/EvalVisitor.h index 0486197852..5dbc1c06ed 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/EvalVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/EvalVisitor.h @@ -71,6 +71,7 @@ class EvalVisitor: public NodeVisitor double visit(const Nodes::ParameterNode* node) override; double visit(const Nodes::LiteralNode* node) override; double visit(const Nodes::PortFieldNode* node) override; + double visit(const Nodes::PortFieldSumNode* node) override; double visit(const Nodes::ComponentVariableNode* node) override; double visit(const Nodes::ComponentParameterNode* node) override; }; diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/LinearityVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/LinearityVisitor.h index 3baa0abe81..8355d27734 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/LinearityVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/LinearityVisitor.h @@ -46,6 +46,7 @@ class LinearityVisitor: public NodeVisitor LinearStatus visit(const Nodes::ParameterNode* param) override; LinearStatus visit(const Nodes::LiteralNode* lit) override; LinearStatus visit(const Nodes::PortFieldNode* port_field_node) override; + LinearStatus visit(const Nodes::PortFieldSumNode* port_field_node) override; LinearStatus visit(const Nodes::ComponentVariableNode* component_variable_node) override; LinearStatus visit(const Nodes::ComponentParameterNode* component_parameter_node) override; }; diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/NodeVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/NodeVisitor.h index 59001acf75..9b88019376 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/NodeVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/NodeVisitor.h @@ -109,6 +109,7 @@ class NodeVisitor: public IName Nodes::VariableNode, Nodes::LiteralNode, Nodes::PortFieldNode, + Nodes::PortFieldSumNode, Nodes::ComponentVariableNode, Nodes::ComponentParameterNode>(); @@ -239,6 +240,16 @@ class NodeVisitor: public IName */ virtual R visit(const Nodes::PortFieldNode*, Args... args) = 0; + /** + * @brief Visits a PortFieldSumNode. + * + * @param node A pointer to the PortFieldSumNode to be visited. + * @param args Additional arguments to be passed to the visitor's methods. + * + * @return The result of processing the PortFieldSumNode. + */ + virtual R visit(const Nodes::PortFieldSumNode*, Args... args) = 0; + /** * @brief Visits a ComponentVariableNode. * diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSubstitutionVisitor.h similarity index 77% rename from src/solver/expressions/include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h rename to src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSubstitutionVisitor.h index bd4a23cfbb..ce897945ea 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/PortfieldSubstitutionVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSubstitutionVisitor.h @@ -27,29 +27,24 @@ 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 +struct PortFieldSubstitutionContext { - std::unordered_map portfield; + std::unordered_map portfield; }; /** * @brief Represents a visitor for substituting portfield nodes in a syntax tree. */ -class PortfieldSubstitutionVisitor: public CloneVisitor +class PortFieldSubstitutionVisitor: public CloneVisitor { public: - PortfieldSubstitutionVisitor(Registry& registry, - PortfieldSubstitutionContext& ctx); + PortFieldSubstitutionVisitor(Registry& registry, + PortFieldSubstitutionContext& ctx); - PortfieldSubstitutionContext& ctx_; + PortFieldSubstitutionContext& ctx_; std::string name() const override; private: diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.h new file mode 100644 index 0000000000..4444da94e6 --- /dev/null +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.h @@ -0,0 +1,57 @@ +/* +** 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 +{ + +/** + * @brief Represents the context for performing substitutions in a syntax tree. + */ +struct PortFieldSumSubstitutionContext +{ + std::unordered_map, PortFieldHash> + portfieldSum; +}; + +/** + * @brief Represents a visitor for substituting portfield sum nodes in a syntax tree. + */ +class PortFieldSumSubstitutionVisitor: public CloneVisitor +{ +public: + PortFieldSumSubstitutionVisitor(Registry& registry, + PortFieldSumSubstitutionContext& ctx); + + std::string name() const override; + +private: + // Only override visit method for PortFieldSum, clone the rest + Nodes::Node* visit(const Nodes::PortFieldSumNode* node) override; + + Registry& registry_; + PortFieldSumSubstitutionContext& ctx_; +}; +} // namespace Antares::Solver::Visitors diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/PrintVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/PrintVisitor.h index a7b09bc8c0..dfcca80823 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/PrintVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/PrintVisitor.h @@ -45,6 +45,7 @@ class PrintVisitor: public NodeVisitor std::string visit(const Nodes::ParameterNode* node) override; std::string visit(const Nodes::LiteralNode* node) override; std::string visit(const Nodes::PortFieldNode* node) override; + std::string visit(const Nodes::PortFieldSumNode* node) override; std::string visit(const Nodes::ComponentVariableNode* node) override; std::string visit(const Nodes::ComponentParameterNode* node) override; }; diff --git a/src/solver/expressions/include/antares/solver/expressions/visitors/TimeIndexVisitor.h b/src/solver/expressions/include/antares/solver/expressions/visitors/TimeIndexVisitor.h index ebbfd9737a..a52fd45e04 100644 --- a/src/solver/expressions/include/antares/solver/expressions/visitors/TimeIndexVisitor.h +++ b/src/solver/expressions/include/antares/solver/expressions/visitors/TimeIndexVisitor.h @@ -55,6 +55,7 @@ class TimeIndexVisitor: public NodeVisitor TimeIndex visit(const Nodes::ParameterNode* param) override; TimeIndex visit(const Nodes::LiteralNode* lit) override; TimeIndex visit(const Nodes::PortFieldNode* port_field_node) override; + TimeIndex visit(const Nodes::PortFieldSumNode* port_field_node) override; TimeIndex visit(const Nodes::ComponentVariableNode* component_variable_node) override; TimeIndex visit(const Nodes::ComponentParameterNode* component_parameter_node) override; }; diff --git a/src/solver/expressions/nodes/PortFieldNode.cpp b/src/solver/expressions/nodes/PortFieldNode.cpp index 2490977c6e..15ca1ff39c 100644 --- a/src/solver/expressions/nodes/PortFieldNode.cpp +++ b/src/solver/expressions/nodes/PortFieldNode.cpp @@ -23,6 +23,7 @@ namespace Antares::Solver::Nodes { PortFieldNode::PortFieldNode(const std::string& port_name, const std::string& field_name): + Hashable(port_name_, field_name_), port_name_(port_name), field_name_(field_name) { diff --git a/src/solver/expressions/nodes/PortFieldSumNode.cpp b/src/solver/expressions/nodes/PortFieldSumNode.cpp new file mode 100644 index 0000000000..b396ebfbb6 --- /dev/null +++ b/src/solver/expressions/nodes/PortFieldSumNode.cpp @@ -0,0 +1,41 @@ +/* +** 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 + +namespace Antares::Solver::Nodes +{ +PortFieldSumNode::PortFieldSumNode(const std::string& port_name, const std::string& field_name): + Hashable(port_name_, field_name_), + port_name_(port_name), + field_name_(field_name) +{ +} + +const std::string& PortFieldSumNode::getPortName() const +{ + return port_name_; +} + +const std::string& PortFieldSumNode::getFieldName() const +{ + return field_name_; +} +} // namespace Antares::Solver::Nodes diff --git a/src/solver/expressions/visitors/AstDOTStyleVisitor.cpp b/src/solver/expressions/visitors/AstDOTStyleVisitor.cpp index 59ce151f06..fb74a129df 100644 --- a/src/solver/expressions/visitors/AstDOTStyleVisitor.cpp +++ b/src/solver/expressions/visitors/AstDOTStyleVisitor.cpp @@ -155,6 +155,15 @@ void AstDOTStyleVisitor::visit(const Nodes::PortFieldNode* node, std::ostream& o os); } +void AstDOTStyleVisitor::visit(const Nodes::PortFieldSumNode* node, std::ostream& os) +{ + auto id = getNodeID(node); + emitNode(id, + "PFSUM(" + node->getPortName() + "," + node->getFieldName() + ")", + NodeStyle::PortFieldStyle, + os); +} + void AstDOTStyleVisitor::visit(const Nodes::ComponentVariableNode* node, std::ostream& os) { auto id = getNodeID(node); diff --git a/src/solver/expressions/visitors/CloneVisitor.cpp b/src/solver/expressions/visitors/CloneVisitor.cpp index 17875a82a1..7d538c0800 100644 --- a/src/solver/expressions/visitors/CloneVisitor.cpp +++ b/src/solver/expressions/visitors/CloneVisitor.cpp @@ -94,10 +94,16 @@ Nodes::Node* CloneVisitor::visit(const Nodes::LiteralNode* literalNode) return registry_.create(literalNode->value()); } -Nodes::Node* CloneVisitor::visit(const Nodes::PortFieldNode* port_field_node) +Nodes::Node* CloneVisitor::visit(const Nodes::PortFieldNode* portfieldNode) { - return registry_.create(port_field_node->getPortName(), - port_field_node->getFieldName()); + return registry_.create(portfieldNode->getPortName(), + portfieldNode->getFieldName()); +} + +Nodes::Node* CloneVisitor::visit(const Nodes::PortFieldSumNode* portfieldSumNode) +{ + return registry_.create(portfieldSumNode->getPortName(), + portfieldSumNode->getFieldName()); } Nodes::Node* CloneVisitor::visit(const Nodes::ComponentVariableNode* component_variable_node) diff --git a/src/solver/expressions/visitors/CompareVisitor.cpp b/src/solver/expressions/visitors/CompareVisitor.cpp index 2a316fdf59..5fa4a090e6 100644 --- a/src/solver/expressions/visitors/CompareVisitor.cpp +++ b/src/solver/expressions/visitors/CompareVisitor.cpp @@ -134,6 +134,11 @@ bool CompareVisitor::visit(const Nodes::PortFieldNode* node, const Nodes::Node* return compareEqualOperator(node, other); } +bool CompareVisitor::visit(const Nodes::PortFieldSumNode* node, const Nodes::Node* other) +{ + return compareEqualOperator(node, other); +} + bool CompareVisitor::visit(const Nodes::ComponentVariableNode* node, const Nodes::Node* other) { return compareEqualOperator(node, other); diff --git a/src/solver/expressions/visitors/EvalVisitor.cpp b/src/solver/expressions/visitors/EvalVisitor.cpp index 25c7973d90..4d0b45e119 100644 --- a/src/solver/expressions/visitors/EvalVisitor.cpp +++ b/src/solver/expressions/visitors/EvalVisitor.cpp @@ -112,6 +112,11 @@ double EvalVisitor::visit(const Nodes::PortFieldNode* node) throw EvalVisitorNotImplemented(name(), node->name()); } +double EvalVisitor::visit(const Nodes::PortFieldSumNode* node) +{ + throw EvalVisitorNotImplemented(name(), node->name()); +} + double EvalVisitor::visit(const Nodes::ComponentVariableNode* node) { throw EvalVisitorNotImplemented(name(), node->name()); diff --git a/src/solver/expressions/visitors/LinearityVisitor.cpp b/src/solver/expressions/visitors/LinearityVisitor.cpp index 93df95b40c..51fddfaffd 100644 --- a/src/solver/expressions/visitors/LinearityVisitor.cpp +++ b/src/solver/expressions/visitors/LinearityVisitor.cpp @@ -94,6 +94,11 @@ LinearStatus LinearityVisitor::visit(const Nodes::PortFieldNode*) return LinearStatus::CONSTANT; } +LinearStatus LinearityVisitor::visit(const Nodes::PortFieldSumNode*) +{ + return LinearStatus::CONSTANT; +} + LinearStatus LinearityVisitor::visit([[maybe_unused]] const Nodes::ComponentVariableNode*) { return LinearStatus::LINEAR; diff --git a/src/solver/expressions/visitors/PortfieldSubstitutionVisitor.cpp b/src/solver/expressions/visitors/PortFieldSubstitutionVisitor.cpp similarity index 67% rename from src/solver/expressions/visitors/PortfieldSubstitutionVisitor.cpp rename to src/solver/expressions/visitors/PortFieldSubstitutionVisitor.cpp index 8a91361c5a..d7dc95c5f1 100644 --- a/src/solver/expressions/visitors/PortfieldSubstitutionVisitor.cpp +++ b/src/solver/expressions/visitors/PortFieldSubstitutionVisitor.cpp @@ -18,22 +18,21 @@ ** You should have received a copy of the Mozilla Public Licence 2.0 ** along with Antares_Simulator. If not, see . */ -#include #include -#include +#include namespace Antares::Solver::Visitors { -PortfieldSubstitutionVisitor::PortfieldSubstitutionVisitor(Registry& registry, - PortfieldSubstitutionContext& ctx): +PortFieldSubstitutionVisitor::PortFieldSubstitutionVisitor(Registry& registry, + PortFieldSubstitutionContext& ctx): CloneVisitor(registry), ctx_(ctx) { } -Nodes::Node* PortfieldSubstitutionVisitor::visit(const Nodes::PortFieldNode* node) +Nodes::Node* PortFieldSubstitutionVisitor::visit(const Nodes::PortFieldNode* node) { if (auto it = ctx_.portfield.find(*node); it != ctx_.portfield.end()) { @@ -43,19 +42,9 @@ Nodes::Node* PortfieldSubstitutionVisitor::visit(const Nodes::PortFieldNode* nod return CloneVisitor::visit(node); } -std::string PortfieldSubstitutionVisitor::name() const +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; + return "PortFieldSubstitutionVisitor"; } } // namespace Antares::Solver::Visitors diff --git a/src/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.cpp b/src/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.cpp new file mode 100644 index 0000000000..cc984e1a43 --- /dev/null +++ b/src/solver/expressions/visitors/PortFieldSumSubstitutionVisitor.cpp @@ -0,0 +1,51 @@ +/* +** 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 + +namespace Antares::Solver::Visitors +{ + +PortFieldSumSubstitutionVisitor::PortFieldSumSubstitutionVisitor( + Registry& registry, + PortFieldSumSubstitutionContext& ctx): + CloneVisitor(registry), + registry_(registry), + ctx_(ctx) +{ +} + +Nodes::Node* PortFieldSumSubstitutionVisitor::visit(const Nodes::PortFieldSumNode* node) +{ + if (auto it = ctx_.portfieldSum.find(*node); it != ctx_.portfieldSum.end()) + { + return registry_.create(it->second); + } + + return CloneVisitor::visit(node); +} + +std::string PortFieldSumSubstitutionVisitor::name() const +{ + return "PortFieldSumSubstitutionVisitor"; +} + +} // namespace Antares::Solver::Visitors diff --git a/src/solver/expressions/visitors/PrintVisitor.cpp b/src/solver/expressions/visitors/PrintVisitor.cpp index b325ed7b75..6e3a2992b3 100644 --- a/src/solver/expressions/visitors/PrintVisitor.cpp +++ b/src/solver/expressions/visitors/PrintVisitor.cpp @@ -96,6 +96,11 @@ std::string PrintVisitor::visit(const Nodes::PortFieldNode* node) return node->getPortName() + "." + node->getFieldName(); } +std::string PrintVisitor::visit(const Nodes::PortFieldSumNode* node) +{ + return node->getPortName() + "." + node->getFieldName(); +} + std::string PrintVisitor::visit(const Nodes::ComponentVariableNode* node) { return node->getComponentId() + "." + node->getComponentName(); diff --git a/src/solver/expressions/visitors/TimeIndexVisitor.cpp b/src/solver/expressions/visitors/TimeIndexVisitor.cpp index 89bd84b000..c81430e67d 100644 --- a/src/solver/expressions/visitors/TimeIndexVisitor.cpp +++ b/src/solver/expressions/visitors/TimeIndexVisitor.cpp @@ -92,6 +92,11 @@ TimeIndex TimeIndexVisitor::visit(const Nodes::PortFieldNode* port_field_node) return context_.at(port_field_node); } +TimeIndex TimeIndexVisitor::visit(const Nodes::PortFieldSumNode* port_field_node) +{ + return context_.at(port_field_node); +} + TimeIndex TimeIndexVisitor::visit(const Nodes::ComponentVariableNode* component_variable_node) { return context_.at(component_variable_node); diff --git a/src/tests/src/solver/expressions/test_AstDOTStyleVisitor.cpp b/src/tests/src/solver/expressions/test_AstDOTStyleVisitor.cpp index 09f80008f3..c227cda025 100644 --- a/src/tests/src/solver/expressions/test_AstDOTStyleVisitor.cpp +++ b/src/tests/src/solver/expressions/test_AstDOTStyleVisitor.cpp @@ -50,7 +50,8 @@ class Fixture Node* variableNode = registry_.create("atoms_count"); Node* divisionNode = registry_.create(variableNode, multiplicationNode); Node* portFieldNode = registry_.create("gasStation", "1149"); - Node* sumNode = registry_.create(divisionNode, portFieldNode); + Node* portFieldSumNode = registry_.create("portfield", "sum"); + Node* sumNode = registry_.create(divisionNode, portFieldNode, portFieldSumNode); Node* componentVariableNode = registry_.create("1150", "otherStation"); Node* componentParameterNode = registry_.create("1151", @@ -103,7 +104,9 @@ node[style = filled] 14 [label="Param(avogadro_constant)", shape="box", style="filled, solid", color="wheat"]; 7 -> 16; 16 [label="PF(gasStation,1149)", shape="component", style="filled, solid", color="olive"]; -label="AST Diagram(Total nodes : 16)" + 7 -> 17; + 17 [label="PFSUM(portfield,sum)", shape="component", style="filled, solid", color="olive"]; +label="AST Diagram(Total nodes : 17)" labelloc = "t" subgraph cluster_legend { label = "Legend"; @@ -133,7 +136,9 @@ legend_NegationNode -> legend_ParameterNode [style=invis]; legend_ParameterNode [ label =" ParameterNode: 1"] legend_ParameterNode -> legend_PortFieldNode [style=invis]; legend_PortFieldNode [ label =" PortFieldNode: 1"] -legend_PortFieldNode -> legend_SubtractionNode [style=invis]; +legend_PortFieldNode -> legend_PortFieldSumNode [style=invis]; +legend_PortFieldSumNode [ label =" PortFieldSumNode: 1"] +legend_PortFieldSumNode -> legend_SubtractionNode [style=invis]; legend_SubtractionNode [ label =" SubtractionNode: 1"] legend_SubtractionNode -> legend_SumNode [style=invis]; legend_SumNode [ label =" SumNode: 1"] diff --git a/src/tests/src/solver/expressions/test_CompareVisitor.cpp b/src/tests/src/solver/expressions/test_CompareVisitor.cpp index 373d1ff314..b0da099b80 100644 --- a/src/tests/src/solver/expressions/test_CompareVisitor.cpp +++ b/src/tests/src/solver/expressions/test_CompareVisitor.cpp @@ -64,7 +64,8 @@ Node* ComparisonFixture::createComplexExpression() Node* sub = registry_.create(add, neg); Node* cmp = registry_.create(sub, add); Node* pf = registry_.create("port", "field"); - Node* addf = registry_.create(pf, cmp); + Node* pfsum = registry_.create("port", "sum"); + Node* addf = registry_.create(pf, pfsum, cmp); return addf; } diff --git a/src/tests/src/solver/expressions/test_LinearVisitor.cpp b/src/tests/src/solver/expressions/test_LinearVisitor.cpp index 689035f0f7..590a6e4e85 100644 --- a/src/tests/src/solver/expressions/test_LinearVisitor.cpp +++ b/src/tests/src/solver/expressions/test_LinearVisitor.cpp @@ -276,6 +276,7 @@ BOOST_FIXTURE_TEST_CASE(simple_constant_expression, Registry) // Port field PortFieldNode portFieldNode("port", "field"); + PortFieldSumNode portFieldSumNode("port", "sum"); // 65.*p1 Node* mult = create(&var1, &par); @@ -283,6 +284,10 @@ BOOST_FIXTURE_TEST_CASE(simple_constant_expression, Registry) Node* expr = create(mult, &portFieldNode); BOOST_CHECK_EQUAL(printVisitor.dispatch(expr), "((65.000000*p1)+port.field)"); BOOST_CHECK_EQUAL(linearVisitor.dispatch(expr), LinearStatus::CONSTANT); + + Node* expr2 = create(mult, &portFieldSumNode); + BOOST_CHECK_EQUAL(printVisitor.dispatch(expr2), "((65.000000*p1)+port.sum)"); + BOOST_CHECK_EQUAL(linearVisitor.dispatch(expr2), LinearStatus::CONSTANT); } BOOST_FIXTURE_TEST_CASE(LinearityVisitor_name, Registry) diff --git a/src/tests/src/solver/expressions/test_PrintAndEvalNodes.cpp b/src/tests/src/solver/expressions/test_PrintAndEvalNodes.cpp index 74743b383c..8ea1a61b1e 100644 --- a/src/tests/src/solver/expressions/test_PrintAndEvalNodes.cpp +++ b/src/tests/src/solver/expressions/test_PrintAndEvalNodes.cpp @@ -203,6 +203,15 @@ BOOST_FIXTURE_TEST_CASE(print_port_field_node, Registry) BOOST_CHECK_EQUAL(printed, "august.2024"); } +BOOST_FIXTURE_TEST_CASE(print_port_field_sum_node, Registry) +{ + PortFieldSumNode pt_fd("august", "2024"); + PrintVisitor printVisitor; + const auto printed = printVisitor.dispatch(&pt_fd); + + BOOST_CHECK_EQUAL(printed, "august.2024"); +} + BOOST_FIXTURE_TEST_CASE(evaluate_param, Registry) { ParameterNode root("my-param"); @@ -345,6 +354,7 @@ BOOST_FIXTURE_TEST_CASE(NotEvaluableNodes, Registry) create(&literalNode, &literalNode), create(&literalNode, &literalNode), create(name, name), + create(name, name), create(component_id, name), create(component_id, name)}; EvalVisitor evalVisitor; diff --git a/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp b/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp index a13d2392a8..dc310c7aa1 100644 --- a/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp +++ b/src/tests/src/solver/expressions/test_SubstitutionVisitor.cpp @@ -26,7 +26,8 @@ #include #include #include -#include +#include +#include #include #include @@ -113,10 +114,12 @@ class SubstitutionFixture: public Registry Node* substitute(Node* original) { - PortfieldSubstitutionContext ctx; - ctx.portfield.emplace(PortFieldNode("port", "literal"), create(10)); + PortFieldSubstitutionContext ctx; + ctx.portfield.emplace(std::piecewise_construct, + std::forward_as_tuple("port", "literal"), + std::forward_as_tuple(create(10))); - PortfieldSubstitutionVisitor sub(*this, ctx); + PortFieldSubstitutionVisitor sub(*this, ctx); return sub.dispatch(original); } }; @@ -134,10 +137,63 @@ BOOST_FIXTURE_TEST_CASE(PortfieldSubstitutionVisitor_simple, SubstitutionFixture BOOST_FIXTURE_TEST_CASE(PortfieldSubstitutionVisitor_name, Registry) { - PortfieldSubstitutionContext ctx; + PortFieldSubstitutionContext ctx; - PortfieldSubstitutionVisitor substitutionVisitor(*this, ctx); - BOOST_CHECK_EQUAL(substitutionVisitor.name(), "PortfieldSubstitutionVisitor"); + PortFieldSubstitutionVisitor substitutionVisitor(*this, ctx); + BOOST_CHECK_EQUAL(substitutionVisitor.name(), "PortFieldSubstitutionVisitor"); +} + +class SumSubstitutionFixture: public Registry +{ +public: + Node* originalExpression() + { + Node* port1 = create("port", "sum of literal"); + Node* port2 = create("another port", "another field"); + Node* root = create(port1, port2); + return root; + } + + Node* expectedExpressionAfterSubstitution() + { + Node* node1 = create(create(12), create(7)); + Node* port2 = create("another port", "another field"); + Node* root = create(node1, port2); + return root; + } + + Node* substitute(Node* original) + { + PortFieldSumSubstitutionContext ctx; + Node* sum1 = create(12); + Node* sum2 = create(7); + std::vector v = {sum1, sum2}; + ctx.portfieldSum.emplace(std::piecewise_construct, + std::forward_as_tuple("port", "sum of literal"), + std::forward_as_tuple(v)); + + PortFieldSumSubstitutionVisitor sub(*this, ctx); + return sub.dispatch(original); + } +}; + +BOOST_FIXTURE_TEST_CASE(PortFieldSumSubstitutionVisitor_simple, SumSubstitutionFixture) + +{ + Node* original = originalExpression(); + Node* substituted = substitute(original); + Node* expected = expectedExpressionAfterSubstitution(); + + CompareVisitor cmp; + BOOST_CHECK(cmp.dispatch(substituted, expected)); +} + +BOOST_FIXTURE_TEST_CASE(PortfieldSumSubstitutionVisitor_name, Registry) +{ + PortFieldSumSubstitutionContext ctx; + + PortFieldSumSubstitutionVisitor substitutionVisitor(*this, ctx); + BOOST_CHECK_EQUAL(substitutionVisitor.name(), "PortFieldSumSubstitutionVisitor"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/solver/expressions/test_TimeIndexVisitor.cpp b/src/tests/src/solver/expressions/test_TimeIndexVisitor.cpp index d95ae2f188..030318d517 100644 --- a/src/tests/src/solver/expressions/test_TimeIndexVisitor.cpp +++ b/src/tests/src/solver/expressions/test_TimeIndexVisitor.cpp @@ -128,6 +128,7 @@ static Node* singleNode(Registry& registry) static const std::vector& registry)> singleNode_ALL{ &singleNode, + &singleNode, &singleNode, &singleNode}; diff --git a/src/tests/src/solver/expressions/test_nodes.cpp b/src/tests/src/solver/expressions/test_nodes.cpp index 3078a9cfbe..b21caac631 100644 --- a/src/tests/src/solver/expressions/test_nodes.cpp +++ b/src/tests/src/solver/expressions/test_nodes.cpp @@ -63,6 +63,16 @@ BOOST_AUTO_TEST_CASE(PortFieldNodeTest) BOOST_CHECK_EQUAL(portFieldNode1 == portFieldNode2, false); } +BOOST_AUTO_TEST_CASE(PortFieldSumNodeTest) +{ + std::string portName1("p1"); + std::string fieldName1("f1"); + + PortFieldSumNode pfs(portName1, fieldName1); + BOOST_CHECK_EQUAL(pfs.getPortName(), portName1); + BOOST_CHECK_EQUAL(pfs.getFieldName(), fieldName1); +} + BOOST_FIXTURE_TEST_CASE(nodes_name, Registry) { auto literalNode = create(2024.2); @@ -82,7 +92,8 @@ BOOST_FIXTURE_TEST_CASE(nodes_name, Registry) "ComponentParameterNode"}, {create(literalNode->name()), "ParameterNode"}, {create(literalNode->name()), "VariableNode"}, - {create(literalNode->name(), literalNode->name()), "PortFieldNode"}}; + {create(literalNode->name(), literalNode->name()), "PortFieldNode"}, + {create(literalNode->name(), literalNode->name()), "PortFieldSumNode"}}; for (auto [node, name]: nodes) {