Antares Simulator
Power System Simulator
Loading...
Searching...
No Matches
EvalVisitor.h
1/*
2** Copyright 2007-2024, RTE (https://www.rte-france.com)
3** See AUTHORS.txt
4** SPDX-License-Identifier: MPL-2.0
5** This file is part of Antares-Simulator,
6** Adequacy and Performance assessment for interconnected energy networks.
7**
8** Antares_Simulator is free software: you can redistribute it and/or modify
9** it under the terms of the Mozilla Public Licence 2.0 as published by
10** the Mozilla Foundation, either version 2 of the License, or
11** (at your option) any later version.
12**
13** Antares_Simulator is distributed in the hope that it will be useful,
14** but WITHOUT ANY WARRANTY; without even the implied warranty of
15** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16** Mozilla Public Licence 2.0 for more details.
17**
18** You should have received a copy of the Mozilla Public Licence 2.0
19** along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
20*/
21#pragma once
22
23#include <cmath>
24#include <sstream>
25#include <variant>
26
27#include <antares/expressions/visitors/EvaluationContext.h>
28#include <antares/optimisation/linear-problem-api/ILinearProblemData.h>
29#include "antares/expressions/visitors/NodeVisitor.h"
30
32{
33struct DataSeriesKeys;
34}
35
36namespace Antares::Expressions::Visitors
37{
38
39class EvalVisitorDivisionException: public std::runtime_error
40{
41public:
42 EvalVisitorDivisionException(double left, double right, const std::string& message);
43};
44
45class EvalVisitorNotImplemented: public std::invalid_argument
46{
47public:
48 EvalVisitorNotImplemented(const std::string& visitor, const std::string& node);
49};
50
52{
53public:
54 explicit EvaluationResult(double value);
55
56 explicit EvaluationResult(const std::vector<double>& values);
57
58 EvaluationResult operator+(const EvaluationResult& right) const
59 {
60 return evaluateBinaryOperation(right, std::plus<>());
61 }
62
63 EvaluationResult operator-(const EvaluationResult& right) const
64 {
65 return evaluateBinaryOperation(right, std::minus<>());
66 }
67
68 EvaluationResult operator*(const EvaluationResult& right) const
69 {
70 return evaluateBinaryOperation(right, std::multiplies<>());
71 }
72
74 {
75 static constexpr double DEFAULT_THRESHOLD = 1e-16;
76
77 explicit SafeDivides(double threshold = DEFAULT_THRESHOLD):
78 threshold_(threshold)
79 {
80 }
81
82 double operator()(double lhs, double rhs) const
83 {
84 if (std::abs(rhs) <= threshold_)
85 {
86 throw EvalVisitorDivisionException(lhs, rhs, "Division by zero");
87 }
88 return lhs / rhs;
89 }
90
91 private:
92 double threshold_;
93 };
94
95 EvaluationResult operator/(const EvaluationResult& right) const
96 {
97 return evaluateBinaryOperation(right, SafeDivides{});
98 }
99
100 EvaluationResult operator-() const
101 {
102 return evaluateUnaryOperation(std::negate<>());
103 }
104
105 [[nodiscard]] std::variant<double, std::vector<double>> value() const
106 {
107 return value_;
108 }
109
110 class EvalResultType: public std::runtime_error
111 {
112 public:
113 using std::runtime_error::runtime_error;
114 };
115
116 [[nodiscard]] double valueAsDouble() const
117 {
118 if (!std::holds_alternative<double>(value_))
119 {
120 throw EvalResultType("Expected a double but found a vector.");
121 }
122 return std::get<double>(value_);
123 }
124
125 [[nodiscard]] std::vector<double> valuesAsVector() const
126 {
127 if (!std::holds_alternative<std::vector<double>>(value_))
128 {
129 throw EvalResultType("Expected a vector but found a double.");
130 }
131 return std::get<std::vector<double>>(value_);
132 }
133
134private:
135 std::variant<double, std::vector<double>> value_;
136 explicit EvaluationResult(const std::variant<double, std::vector<double>>& value);
137
138 template<typename Op>
139 EvaluationResult evaluateBinaryOperation(const EvaluationResult& right, Op op) const;
140 template<typename Op>
141 EvaluationResult evaluateUnaryOperation(Op op) const;
142};
143
144template<typename BinaryOp>
145double computeBinaryOperation(double lhs, double rhs, BinaryOp op)
146{
147 return op(lhs, rhs);
148}
149
150template<typename BinaryOp>
151std::vector<double> computeBinaryOperation(const std::vector<double>& lhs, double rhs, BinaryOp op)
152{
153 auto result(lhs);
154 for (double& value: result)
155 {
156 value = op(value, rhs);
157 }
158 return result;
159}
160
161template<typename BinaryOp>
162std::vector<double> computeBinaryOperation(double lhs, const std::vector<double>& rhs, BinaryOp op)
163{
164 return computeBinaryOperation(rhs, lhs, op);
165}
166
167class VectorsMismatchSize final: public std::runtime_error
168{
169public:
170 using std::runtime_error::runtime_error;
171};
172
173template<typename BinaryOp>
174std::vector<double> computeBinaryOperation(const std::vector<double>& lhs,
175 const std::vector<double>& rhs,
176 BinaryOp op)
177{
178 if (lhs.size() != rhs.size())
179 {
180 std::ostringstream errorMsg;
181 errorMsg << "Failed to compute binary operation: vectors have different sizes ("
182 << lhs.size() << " and " << rhs.size() << ").";
183 throw VectorsMismatchSize(errorMsg.str());
184 }
185
186 std::vector<double> result(lhs.size());
187 for (size_t i = 0; i < lhs.size(); ++i)
188 {
189 result[i] = op(lhs[i], rhs[i]);
190 }
191 return result;
192}
193
194template<typename Op>
195EvaluationResult EvaluationResult::evaluateBinaryOperation(const EvaluationResult& right,
196 Op op) const
197{
198 return EvaluationResult(
199 std::visit([&op](const auto& l, const auto& r) -> std::variant<double, std::vector<double>>
200 { return computeBinaryOperation(l, r, op); },
201 value_,
202 right.value_));
203}
204
205template<typename UnaryOp>
206std::vector<double> computeUnaryOperation(const std::vector<double>& values, UnaryOp op)
207{
208 auto result(values);
209 for (double& v: result)
210 {
211 v = op(v);
212 }
213 return result;
214}
215
216template<typename UnaryOp>
217double computeUnaryOperation(double value, UnaryOp op)
218{
219 return op(value);
220}
221
222template<typename Op>
223EvaluationResult EvaluationResult::evaluateUnaryOperation(Op op) const
224{
225 return EvaluationResult(
226 std::visit([&op](const auto& v) -> std::variant<double, std::vector<double>>
227 { return computeUnaryOperation(v, op); },
228 value_));
229}
230
234class EvalVisitor: public NodeVisitor<EvaluationResult>
235{
236public:
243 explicit EvalVisitor(EvaluationContext context,
245 std::string name() const override;
246
247private:
248 const EvaluationContext context_;
250 EvaluationResult visit(const Nodes::SumNode* node) override;
251 EvaluationResult visit(const Nodes::SubtractionNode* node) override;
252 EvaluationResult visit(const Nodes::MultiplicationNode* node) override;
253 EvaluationResult visit(const Nodes::DivisionNode* node) override;
254 EvaluationResult visit(const Nodes::EqualNode* node) override;
255 EvaluationResult visit(const Nodes::LessThanOrEqualNode* node) override;
256 EvaluationResult visit(const Nodes::GreaterThanOrEqualNode* node) override;
257 EvaluationResult visit(const Nodes::NegationNode* node) override;
258 EvaluationResult visit(const Nodes::VariableNode* node) override;
259 EvaluationResult visit(const Nodes::ParameterNode* node) override;
260 EvaluationResult visit(const Nodes::LiteralNode* node) override;
261 EvaluationResult visit(const Nodes::PortFieldNode* node) override;
262 EvaluationResult visit(const Nodes::PortFieldSumNode* node) override;
263 EvaluationResult visit(const Nodes::ComponentVariableNode* node) override;
264 EvaluationResult visit(const Nodes::ComponentParameterNode* node) override;
265};
266} // namespace Antares::Expressions::Visitors
Represents a component parameter node in a syntax tree.
Definition ComponentNode.h:80
Represents a component variable node in a syntax tree.
Definition ComponentNode.h:66
Represents a division node in a syntax tree.
Definition DivisionNode.h:31
Represents an equality comparison node in a syntax tree.
Definition EqualNode.h:31
Represents a greater than or equal comparison node in a syntax tree.
Definition GreaterThanOrEqualNode.h:31
Represents a less than or equal comparison node in a syntax tree.
Definition LessThanOrEqualNode.h:31
Represents a literal node in a syntax tree, storing a double value.
Definition LiteralNode.h:11
Represents a multiplication node in a syntax tree.
Definition MultiplicationNode.h:31
Represents a negation node in a syntax tree.
Definition NegationNode.h:31
Represents a parameter node in a syntax tree, storing a string value.
Definition ParameterNode.h:19
Represents a port field node in a syntax tree.
Definition PortFieldNode.h:33
Represents a port field node where the expression is a sum.
Definition PortFieldSumNode.h:33
Represents a subtraction node in a syntax tree.
Definition SubtractionNode.h:31
Represents a variable node in a syntax tree, storing a string value.
Definition VariableNode.h:20
Represents a visitor for evaluating expressions within a given context.
Definition EvalVisitor.h:235
EvalVisitor(EvaluationContext context, Optimisation::LinearProblemApi::FillContext fillContext)
Constructs an evaluation visitor with the specified context.
Definition EvalVisitor.cpp:31
Represents the context for evaluating expressions.
Definition EvaluationContext.h:35
Namespace for the classes related to the linear problem API.
Definition EvaluationContext.h:9