Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
eval_expression.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//include/bertini2/system/eval_expression.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//include/bertini2/system/eval_expression.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with include/bertini2/system/eval_expression.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
33
34#pragma once
35
36#include <map>
37#include <string>
38#include <stdexcept>
39#include <type_traits>
40
43
44namespace bertini {
45
68 template<typename T>
69 T EvalExpression(std::shared_ptr<node::Node> const& expr,
70 std::map<std::string, T> const& variable_values,
71 bool strict = true)
72 {
73 auto vars = node::GatherVariables(expr); // distinct, sorted by name
74
75 // Guard against typos: when strict, every supplied name must be a variable of the
76 // expression. When not strict, extra names are simply ignored (the point-binding loop
77 // below only ever reads names that are variables of the expression).
78 if (strict)
79 for (auto const& named_value : variable_values)
80 {
81 bool appears = false;
82 for (auto const& v : vars)
83 if (v->name() == named_value.first) { appears = true; break; }
84 if (!appears)
85 throw std::runtime_error("value supplied for '" + named_value.first +
86 "', which is not a variable of the expression being evaluated");
87 }
88
89 // Bind values into the System's variable order (which is the name order of `vars`).
90 Vec<T> point(static_cast<Eigen::Index>(vars.size()));
91 for (size_t i = 0; i < vars.size(); ++i)
92 {
93 auto it = variable_values.find(vars[i]->name());
94 if (it == variable_values.end())
95 throw std::runtime_error("no value supplied for variable '" + vars[i]->name() +
96 "' when evaluating an expression");
97 point(static_cast<Eigen::Index>(i)) = it->second;
98 }
99
100 // Compile the expression's evaluator once and memoize it on the (immutable, hash-consed)
101 // node, so repeated evaluation of the same expression reuses the compiled program rather
102 // than rebuilding a throwaway System and recompiling an SLP every call (ADR-0027).
103 // The compiled program holds no node pointers (its constants are value recipes), so caching
104 // it on the node creates no reference cycle.
105 auto cached = std::static_pointer_cast<const StraightLineProgram>(expr->EvalProgram());
106 if (!cached)
107 {
108 System sys;
109 sys.AddFunction(expr);
110 sys.AddVariableGroup(vars);
111 cached = std::make_shared<const StraightLineProgram>(sys);
112 expr->SetEvalProgram(cached);
113 }
114
115 // Per-call working copy: it shares the immutable compiled Program but gets its own
116 // evaluation Memory, so concurrent evaluations of the same cached expression do not race.
117 StraightLineProgram slp = *cached;
118
119 if constexpr (!std::is_same<T, complex_dbl>::value)
120 if (vars.size() > 0)
121 slp.precision(Precision(point));
122
123 slp.Eval(point);
124 return slp.template GetFuncVals<T>()(0);
125 }
126
127} // namespace bertini
An implementation of straight-line programs, implemented with strong inspiration from Bertini1's impl...
Definition straight_line_program.hpp:587
unsigned precision() const
Get the current precision of the SLP.
Definition straight_line_program.hpp:811
void Eval(Eigen::MatrixBase< Derived > const &variable_values) const
Evaluate the program at the given variable values (no path variable).
Definition straight_line_program.hpp:607
The fundamental polynomial system class for Bertini2.
Definition system.hpp:106
void AddFunction(Nd const &F)
Add a function to the system, as a bare expression.
void AddVariableGroup(VariableGroup const &v)
Add a variable group to the system.
Free functions for discovering the variables appearing in a function tree.
VariableGroup GatherVariables(std::shared_ptr< const Node > const &n)
Collect the distinct Variables appearing in a function-tree subtree.
Definition algorithm_builder.hpp:36
Eigen::Matrix< NumT, Eigen::Dynamic, 1 > Vec
A dynamically-sized column vector of NumT.
Definition eigen_extensions.hpp:296
T EvalExpression(std::shared_ptr< node::Node > const &expr, std::map< std::string, T > const &variable_values, bool strict=true)
Evaluate an expression tree at a point supplied as a variable-name -> value map.
Definition eval_expression.hpp:69
unsigned Precision(Eigen::MatrixBase< Derived > const &v)
Get the precision of an Eigen object.
Definition eigen_extensions.hpp:339
Provides the bertini::System class.