Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
polynomial_block.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//polynomial_block.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//polynomial_block.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 polynomial_block.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
38
39#pragma once
40
41#include <vector>
42#include <memory>
43
44#include <boost/serialization/access.hpp>
45#include <boost/serialization/vector.hpp>
46#include <boost/serialization/shared_ptr.hpp>
47
53
54namespace bertini {
55namespace blocks {
56
61{
62public:
63 using NE = std::shared_ptr<node::NamedExpression>;
64 using Nd = std::shared_ptr<node::Node>;
65 using Var = std::shared_ptr<node::Variable>;
66
68 PolynomialBlock() : precision_(DefaultPrecision()) {}
69
70 // ---- construction (System forwards AddFunction / AddSubFunction here) ----
72 void AddFunction(Nd const& f) { functions_.push_back(f); Invalidate(); }
74 void AddConstant(NE const& f) { constant_subfunctions_.push_back(f); Invalidate(); }
75
79 void SetVariableOrdering(VariableGroup const& vars) const { variables_ = vars; Invalidate(); }
81 void SetPathVariable(Var const& t) const { path_variable_ = t; Invalidate(); }
83 void ClearPathVariable() const { path_variable_.reset(); Invalidate(); }
84
85 // Mutable access for the owning System's construction-time manipulations (Homogenize walks
86 // the trees in place; Reorder/Simplify reassign entries). The System keeps the variable
87 // groups / ordering; the block keeps the functions and their derivatives.
89 std::vector<Nd>& Functions() { return functions_; }
91 std::vector<Nd> const& Functions() const { return functions_; }
93 std::vector<NE> const& ConstantSubfunctions() const { return constant_subfunctions_; }
95 size_t NumConstants() const { return constant_subfunctions_.size(); }
96
98 bool IsDifferentiated() const { return is_differentiated_; }
100 void Invalidate() const { is_differentiated_ = false; }
101
103 std::vector<int> Degrees() const
104 {
105 std::vector<int> d; d.reserve(functions_.size());
106 for (auto const& f : functions_) d.push_back(f->Degree());
107 return d;
108 }
109
110 std::vector<int> Degrees(VariableGroup const& vars) const
111 {
112 std::vector<int> d; d.reserve(functions_.size());
113 for (auto const& f : functions_) d.push_back(f->Degree(vars));
114 return d;
115 }
116
120 void Homogenize(VariableGroup const& group, Var const& hom_var)
121 {
122 for (auto& f : functions_)
123 f = f->Homogenized(group, hom_var);
124 Invalidate();
125 }
126
127 bool IsHomogeneous(VariableGroup const& vars) const
128 {
129 for (auto const& f : functions_) if (!f->IsHomogeneous(vars)) return false;
130 return true;
131 }
132
133 bool IsPolynomial(VariableGroup const& vars) const
134 {
135 for (auto const& f : functions_) if (!f->IsPolynomial(vars)) return false;
136 return true;
137 }
138
139 // ---- block contract: metadata ----
141 size_t NumFunctions() const { return functions_.size(); }
143 bool DependsOnPathVariable() const { return static_cast<bool>(path_variable_); }
144
147 void Describe(std::ostream& out, size_t& row, VariableGroup const& /*vars*/, bool /*verbose*/) const
148 {
149 for (auto const& f : functions_)
150 out << " f_" << row++ << " = " << f << "\n";
151 }
152
154 unsigned Precision() const { return precision_; }
156 void Precision(unsigned new_precision) const
157 {
158 // short-circuit when already materialized here. Each holder of mp values keeps its
159 // own "materialized at" tag; System deliberately keeps none and simply fans out on
160 // every evaluation, which is cheap precisely because of this early return (ADR-0057).
161 if (precision_==new_precision)
162 return;
163 // The SLP (its per-thread Memory) is the sole evaluator and carries its own precision; the
164 // function / derivative / variable nodes are no longer evaluated during tracking, so their
165 // precision is vestigial and left untouched (keeps the shared node DAG read-only).
166 slp_.precision(new_precision);
167 precision_ = new_precision;
168 }
169
170 // ---- block contract: evaluation (value-in) ----
171 // The compiled SLP is the sole evaluator; the function/derivative trees survive only as the
172 // thing the SLP is compiled from (and that Simplify/Differentiate operate on).
174 template <typename T>
175 void EvalInPlace(Eigen::Ref<Vec<T>> result, Vec<T> const& vars, T const& path_value) const
176 {
177 EnsureDifferentiated();
178 SetValues<T>(vars, path_value);
179 slp_.template GetFuncValsInPlace<T>(result);
180 }
181
183 template <typename T>
184 void JacobianInPlace(Eigen::Ref<Mat<T>> J, Vec<T> const& vars, T const& path_value) const
185 {
186 EnsureDifferentiated();
187 SetValues<T>(vars, path_value);
188 slp_.template GetJacobianInPlace<T>(J);
189 }
190
192 template <typename T>
193 void TimeDerivInPlace(Eigen::Ref<Vec<T>> result, Vec<T> const& vars, T const& path_value) const
194 {
195 if (!path_variable_) { result.setZero(); return; }
196 EnsureDifferentiated();
197 SetValues<T>(vars, path_value);
198 slp_.template GetTimeDerivInPlace<T>(result);
199 }
200
201 // ---- accessors the SLP compiler reads (mirror the System names) ----
203 VariableGroup const& VariableOrdering() const { return variables_; }
205 bool HavePathVariable() const { return static_cast<bool>(path_variable_); }
207 Var GetPathVariable() const { return path_variable_; }
209 size_t NumNaturalFunctions() const { return functions_.size(); }
211 std::vector<Nd> const& GetNaturalFunctions() const { return functions_; }
212 // The SLP is built from the explicit per-variable derivative trees (space/time derivatives).
214 std::vector<Nd> const& GetSpaceDerivatives() const
215 {
216 if (space_derivatives_.empty())
217 DifferentiateUsingDerivatives();
218 return space_derivatives_;
219 }
220
221 std::vector<Nd> const& GetTimeDerivatives() const
222 {
223 if (path_variable_ && time_derivatives_.empty())
224 DifferentiateUsingDerivatives();
225 return time_derivatives_;
226 }
227
231 void Differentiate() const
232 {
233 if (is_differentiated_) return;
234 DifferentiateUsingDerivatives();
235 is_differentiated_ = true; // set before Compile, which reads the deriv state
236 slp_ = SLPCompiler().Compile(*this);
237 }
238
240 void SimplifyFunctions() const
241 {
242 // Intentionally inert on the top-level functions, preserving long-standing behavior:
243 // when functions were Function-wrapped, Handle::Simplified() returned self (an opaque
244 // boundary), so top-level simplification never happened. Now that functions are bare
245 // roots, actually simplifying them here would be a behavior change, deferred to its own step.
246 Invalidate();
247 }
248
253 {
254 using bertini::Simplify;
255 for (auto& n : space_derivatives_) n = Simplify(n);
256 for (auto& n : time_derivatives_) n = Simplify(n);
257 }
258
264 {
265 for (auto& f : functions_)
266 f = node::Reintern(f, memo);
267 for (auto& c : constant_subfunctions_)
268 c = std::static_pointer_cast<node::NamedExpression>(node::Reintern(c, memo));
269 for (auto& v : variables_)
270 v = std::static_pointer_cast<node::Variable>(node::Reintern(v, memo));
271 if (path_variable_)
272 path_variable_ = std::static_pointer_cast<node::Variable>(node::Reintern(path_variable_, memo));
273 space_derivatives_.clear();
274 time_derivatives_.clear();
275 Invalidate();
276 }
277
278private:
279 void EnsureDifferentiated() const { if (!is_differentiated_) Differentiate(); }
280
281 template <typename T>
282 void SetValues(Vec<T> const& vars, T const& path_value) const
283 {
284 slp_.SetVariableValues(vars);
285 if (path_variable_) slp_.template SetPathVariable<T>(path_value);
286 }
287
288 void DifferentiateUsingDerivatives() const
289 {
290 const size_t n = functions_.size();
291 space_derivatives_.resize(n * variables_.size());
292 for (size_t jj = 0; jj < variables_.size(); ++jj)
293 for (size_t ii = 0; ii < n; ++ii)
294 space_derivatives_[ii + jj * n] = functions_[ii]->Differentiate(variables_[jj]);
295 if (path_variable_)
296 {
297 time_derivatives_.resize(n);
298 for (size_t ii = 0; ii < n; ++ii)
299 time_derivatives_[ii] = functions_[ii]->Differentiate(path_variable_);
300 }
301 }
302
303 mutable std::vector<Nd> functions_;
304 mutable std::vector<NE> constant_subfunctions_;
305
306 mutable std::vector<Nd> space_derivatives_;
307 mutable std::vector<Nd> time_derivatives_;
308 mutable StraightLineProgram slp_;
309
310 mutable VariableGroup variables_;
311 mutable Var path_variable_;
312
313 mutable bool is_differentiated_ = false;
314 mutable unsigned precision_;
315
317
318 template <typename Archive>
319 void serialize(Archive& ar, const unsigned /*version*/)
320 {
321 ar & constant_subfunctions_;
322 ar & functions_;
323 ar & is_differentiated_;
324 ar & space_derivatives_;
325 ar & time_derivatives_;
326 ar & slp_;
327 ar & variables_;
328 ar & path_variable_;
329 ar & precision_;
330 }
331};
332
333} // namespace blocks
334} // namespace bertini
Compiles a System (or polynomial block) into a StraightLineProgram by visiting its function-tree node...
Definition straight_line_program.hpp:1032
SLP Compile(SourceT const &source)
Compile a source (a System or polynomial block) into a StraightLineProgram.
void SetVariableValues(Eigen::MatrixBase< Derived > const &variable_values) const
Copy the values of the variables from the passed in vector to memory.
Definition straight_line_program.hpp:867
bool IsDifferentiated() const
Query whether the block's derivatives have been computed.
Definition polynomial_block.hpp:98
void Describe(std::ostream &out, size_t &row, VariableGroup const &, bool) const
Human-facing description: one line per function, f_k = <expression>.
Definition polynomial_block.hpp:147
size_t NumFunctions() const
Get the number of functions in the block.
Definition polynomial_block.hpp:141
void Homogenize(VariableGroup const &group, Var const &hom_var)
Homogenize each function w.r.t.
Definition polynomial_block.hpp:120
size_t NumConstants() const
Get the number of constant subfunctions.
Definition polynomial_block.hpp:95
bool IsPolynomial(VariableGroup const &vars) const
Query whether every function is polynomial in a variable group.
Definition polynomial_block.hpp:133
size_t NumNaturalFunctions() const
Get the number of natural (pre-randomization) functions.
Definition polynomial_block.hpp:209
void ClearPathVariable() const
Clear the path variable.
Definition polynomial_block.hpp:83
bool DependsOnPathVariable() const
Query whether the block depends on the path variable.
Definition polynomial_block.hpp:143
void SetPathVariable(Var const &t) const
Set the path variable the function trees are evaluated against.
Definition polynomial_block.hpp:81
void Invalidate() const
Mark the block's derivatives as stale (to be recomputed on next use).
Definition polynomial_block.hpp:100
Var GetPathVariable() const
Get the block's path variable (may be null).
Definition polynomial_block.hpp:207
std::vector< int > Degrees(VariableGroup const &vars) const
Per-function degrees with respect to a given variable group.
Definition polynomial_block.hpp:110
void AddConstant(NE const &f)
Add a named constant subfunction.
Definition polynomial_block.hpp:74
std::shared_ptr< node::NamedExpression > NE
Shorthand for a shared pointer to a named expression.
Definition polynomial_block.hpp:63
void JacobianInPlace(Eigen::Ref< Mat< T > > J, Vec< T > const &vars, T const &path_value) const
Evaluate the block's Jacobian in place at the given variable and path-variable values.
Definition polynomial_block.hpp:184
void EvalInPlace(Eigen::Ref< Vec< T > > result, Vec< T > const &vars, T const &path_value) const
Evaluate the block's functions in place at the given variable and path-variable values.
Definition polynomial_block.hpp:175
void TimeDerivInPlace(Eigen::Ref< Vec< T > > result, Vec< T > const &vars, T const &path_value) const
Evaluate the block's time derivative in place (zero if there is no path variable).
Definition polynomial_block.hpp:193
std::vector< Nd > const & GetNaturalFunctions() const
Get the block's natural function trees.
Definition polynomial_block.hpp:211
std::shared_ptr< node::Node > Nd
Shorthand for a shared pointer to a generic node.
Definition polynomial_block.hpp:64
void AddFunction(Nd const &f)
Add a function (one row of the block).
Definition polynomial_block.hpp:72
unsigned Precision() const
Get the block's current working precision.
Definition polynomial_block.hpp:154
std::vector< Nd > const & Functions() const
Get const access to the block's functions.
Definition polynomial_block.hpp:91
void SetVariableOrdering(VariableGroup const &vars) const
The variable ordering + path variable the function trees are evaluated against; the owning System kee...
Definition polynomial_block.hpp:79
std::shared_ptr< node::Variable > Var
Shorthand for a shared pointer to a variable node.
Definition polynomial_block.hpp:65
void Differentiate() const
Build the symbolic derivatives (and, for SLP eval, compile the SLP from this block).
Definition polynomial_block.hpp:231
VariableGroup const & VariableOrdering() const
Get the variable ordering the functions are evaluated against.
Definition polynomial_block.hpp:203
bool HavePathVariable() const
Query whether the block has a path variable.
Definition polynomial_block.hpp:205
void Reintern(node::ReinternMemo &memo)
Re-intern this block's nodes after deserialization (ADR-0042): functions, constant subfunctions,...
Definition polynomial_block.hpp:263
std::vector< int > Degrees() const
Per-function degrees (total, and with respect to a variable group).
Definition polynomial_block.hpp:103
friend class boost::serialization::access
Definition polynomial_block.hpp:316
void SimplifyDerivatives() const
Simplify the derivative trees.
Definition polynomial_block.hpp:252
std::vector< Nd > & Functions()
Get mutable access to the block's functions.
Definition polynomial_block.hpp:89
std::vector< Nd > const & GetSpaceDerivatives() const
Get the per-variable space-derivative trees (computing them if needed).
Definition polynomial_block.hpp:214
void SimplifyFunctions() const
Simplify the function trees (and invalidate the derivatives, which must be rebuilt).
Definition polynomial_block.hpp:240
std::vector< NE > const & ConstantSubfunctions() const
Get the block's constant subfunctions.
Definition polynomial_block.hpp:93
void Precision(unsigned new_precision) const
Set the block's working precision (delegated to the compiled SLP).
Definition polynomial_block.hpp:156
PolynomialBlock()
Construct an empty polynomial block at the current default precision.
Definition polynomial_block.hpp:68
bool IsHomogeneous(VariableGroup const &vars) const
Query whether every function is homogeneous with respect to a variable group.
Definition polynomial_block.hpp:127
std::vector< Nd > const & GetTimeDerivatives() const
Get the time-derivative trees (computing them if needed).
Definition polynomial_block.hpp:221
Bertini extensions of the Eigen linear algebra library.
Collects the various header files which define the Bertini2 function tree node types.
Definition blend_block.hpp:75
std::map< Node const *, std::shared_ptr< Node > > ReinternMemo
Memo for one re-interning pass: loaded node -> its interned replacement.
Definition reintern.hpp:57
std::shared_ptr< Node > Reintern(std::shared_ptr< Node > const &root, ReinternMemo &memo)
Rebuild the DAG rooted at root through the interning factories (memoized, post-order),...
Definition algorithm_builder.hpp:36
Eigen::Matrix< NumT, Eigen::Dynamic, 1 > Vec
A dynamically-sized column vector of NumT.
Definition eigen_extensions.hpp:296
std::vector< std::shared_ptr< node::Variable > > VariableGroup
An ordered group of variables (the unit of homogenization / variable grouping).
Definition node.hpp:69
Eigen::Matrix< NumT, Eigen::Dynamic, Eigen::Dynamic > Mat
A dynamically-sized matrix of NumT.
Definition eigen_extensions.hpp:298
auto DefaultPrecision()
Get the global default precision (digits) for multiprecision numbers.
Definition mpfr_complex.hpp:135
std::shared_ptr< bertini::node::Node > Simplify(std::shared_ptr< bertini::node::Node > const &n)
Functionally simplify a tree: returns a NEW simplified tree, leaving the input untouched (non-mutatin...
Provides an Eigen-like NumTraits struct for querying traits of a number type.
Re-intern deserialized node DAGs into the live hash-consing tables (ADR-0042).
Provides the bertini::StraightLineProgram class.