Bertini 2 d882924 (2026-10-06 19:56 UTC)
Numerical algebraic geometry library (C++ core)
Loading...
Searching...
No Matches
classic_writer.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//Bertini 2 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//Bertini 2 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 Bertini 2. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) 2015 - 2026 by Bertini2 developers
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
35
36#pragma once
37
41
42#include <ostream>
43#include <sstream>
44#include <iomanip>
45#include <string>
46#include <vector>
47
48namespace bertini{
49 namespace classic{
50
59 inline void EmitSystem(std::ostream& out, System const& sys)
60 {
61 auto emit_groups = [&out](char const* keyword, auto const& groups){
62 for (auto const& grp : groups)
63 {
64 out << keyword << " ";
65 for (size_t i = 0; i < grp.size(); ++i)
66 out << (i ? ", " : "") << *grp[i];
67 out << ";\n";
68 }
69 };
70 emit_groups("variable_group", sys.VariableGroups());
71 emit_groups("hom_variable_group", sys.HomVariableGroups());
72
73 // a homotopy is a system too: its path variable must be declared, or the functions that
74 // use it do not parse back and the file does not round-trip (b2#366)
75 if (sys.HavePathVariable())
76 out << "pathvariable " << *sys.GetPathVariable() << ";\n";
77
78 auto functions = sys.NaturalFunctionsAsNodes();
79
80 // Named subexpressions are not stored separately; they are discovered inside the function
81 // trees (nested ones included). Emit each as `name = expr;` before the functions, the way
82 // the classic parser expects a subfunction to be defined ahead of its use.
83 {
84 std::vector<std::shared_ptr<const node::Node>> roots(functions.begin(), functions.end());
85 for (auto const& ne : node::Find<node::NamedExpression>(roots))
86 out << ne->name() << " = " << ne->EntryNode() << ";\n";
87 }
88
89 out << "function ";
90 for (size_t i = 0; i < functions.size(); ++i)
91 out << (i ? ", " : "") << "f" << i;
92 out << ";\n";
93 for (size_t i = 0; i < functions.size(); ++i)
94 out << "f" << i << " = " << functions[i] << ";\n";
95 }
96
98 inline std::string SystemToClassic(System const& sys)
99 {
100 std::ostringstream ss;
101 EmitSystem(ss, sys);
102 return ss.str();
103 }
104
105
113 {
114 int tracktype = 0;
115 int mptype = 2;
116 int odepredictor = 5;
117 double tracktolbeforeeg = 1e-5;
118 double tracktolduringeg = 1e-6;
119 double finaltol = 1e-11;
120 // step-size cadence -- governs how aggressively a path may take a big step (i.e. jump),
121 // so it must be controlled for a fair crossing-rate comparison against Bertini 1.
122 double maxstepsize = 0.1;
123 double stepsuccessfactor = 2.0;
124 double stepfailfactor = 0.5;
125 unsigned stepsforincrease = 5;
126 unsigned long maxnumbersteps = 100000;
127 unsigned maxnewtonits = 2;
129 };
130
138 {
139 using P = tracking::Predictor;
140 switch (p)
141 {
142 case P::Constant: return -1;
143 case P::Euler: return 0;
144 case P::Heun: return 1;
145 case P::RK4: return 2;
146 case P::HeunEuler: return 1;
147 case P::RKNorsett34: return 4;
148 case P::RKF45: return 5;
149 case P::RKCashKarp45: return 6;
150 case P::RKDormandPrince56: return 7;
151 case P::RKVerner67: return 8;
152 }
153 return 5; // RKF45 -- the Bertini 2 default, a safe fallback
154 }
155
160 inline void EmitConfig(std::ostream& out, System const& sys, ClassicWriteOptions const& opt)
161 {
162 auto num = [](double v){ std::ostringstream s; s << std::setprecision(15) << v; return s.str(); };
163 out << "tracktype: " << opt.tracktype << ";\n";
164 out << "mptype: " << opt.mptype << ";\n";
165 out << "odepredictor: " << opt.odepredictor << ";\n";
166 out << "tracktolbeforeeg: " << num(opt.tracktolbeforeeg) << ";\n";
167 out << "tracktolduringeg: " << num(opt.tracktolduringeg) << ";\n";
168 out << "finaltol: " << num(opt.finaltol) << ";\n";
169 out << "maxstepsize: " << num(opt.maxstepsize) << ";\n";
170 out << "stepsuccessfactor: " << num(opt.stepsuccessfactor) << ";\n";
171 out << "stepfailfactor: " << num(opt.stepfailfactor) << ";\n";
172 out << "stepsforincrease: " << opt.stepsforincrease << ";\n";
173 out << "maxnumbersteps: " << opt.maxnumbersteps << ";\n";
174 out << "maxnewtonits: " << opt.maxnewtonits << ";\n";
175 out << "maxcrossedpathresolves: " << opt.maxcrossedpathresolves << ";\n";
176 out << "coefficientbound: " << num(static_cast<double>(sys.CoefficientBound<complex_dbl>())) << ";\n";
177 // A system that is not a polynomial one has no degree bound, and asking for one now
178 // throws. Write the file anyway -- "this is what Bertini 1 would eat, if it could
179 // eat it" is a useful thing to look at -- but say why the setting is absent instead
180 // of inventing a number. `%` is a comment in this format, and our own parser strips
181 // comments, so the file still reads back into b2.
182 if (sys.IsPolynomial())
183 out << "degreebound: " << sys.DegreeBound() << ";\n";
184 else
185 out << "% degreebound: omitted -- this system is not polynomial, so it has none\n";
186 }
187
189 inline void WriteClassicInput(std::ostream& out, System const& sys,
191 {
192 out << "CONFIG\n";
193 EmitConfig(out, sys, opt);
194 out << "END;\n\nINPUT\n";
195 EmitSystem(out, sys);
196 out << "END;\n";
197 }
198
200 inline std::string SystemToClassicFile(System const& sys,
202 {
203 std::ostringstream ss;
204 WriteClassicInput(ss, sys, opt);
205 return ss.str();
206 }
207
208 } // namespace classic
209} // namespace bertini
The fundamental polynomial system class for Bertini2.
Definition system.hpp:106
const Var & GetPathVariable() const
Get the system's path variable (throws if none is defined).
auto HomVariableGroups() const
Get the homogeneous (projective) variable groups in the problem.
Definition system.hpp:1807
Eigen::NumTraits< NumT >::Real CoefficientBound(unsigned num_evaluations=1) const
Compute an estimate of an upper bound of the absolute values of the coefficients in the system.
bool IsPolynomial() const
Checks whether a system is polynomial, overall.
int DegreeBound() const
Compute an upper bound on the degree of the system.
bool HavePathVariable() const
Query whether a path variable is set for this system.
auto VariableGroups() const
Get the affine variable groups in the problem.
Definition system.hpp:1799
std::vector< Nd > NaturalFunctionsAsNodes() const
The system's natural (pre-patch) functions as function-tree expression nodes, expanding any structure...
Discover named nodes of a given kind in a function tree (sympy's find).
Definition classic_writer.hpp:49
void WriteClassicInput(std::ostream &out, System const &sys, ClassicWriteOptions const &opt=ClassicWriteOptions{})
Write a complete Bertini 1 classic input file: CONFIG ... END;\nINPUT ... END;.
Definition classic_writer.hpp:189
std::string SystemToClassicFile(System const &sys, ClassicWriteOptions const &opt=ClassicWriteOptions{})
The complete classic input file as a string.
Definition classic_writer.hpp:200
int PredictorToClassic(tracking::Predictor p)
Map a Bertini 2 Predictor to its Bertini 1 classic odepredictor integer.
Definition classic_writer.hpp:137
std::string SystemToClassic(System const &sys)
The INPUT-section body as a string.
Definition classic_writer.hpp:98
void EmitConfig(std::ostream &out, System const &sys, ClassicWriteOptions const &opt)
Emit the CONFIG-section body (no CONFIG/END wrapper).
Definition classic_writer.hpp:160
void EmitSystem(std::ostream &out, System const &sys)
Emit the INPUT-section body of a system in classic syntax: the variable groups, any named subexpressi...
Definition classic_writer.hpp:59
std::vector< std::shared_ptr< T > > Find(std::shared_ptr< const Node > const &n)
All distinct nodes of kind T in the subtree rooted at n, sorted by name.
Predictor
The predictor (ODE integration) method used during path tracking.
Definition config.hpp:55
Definition algorithm_builder.hpp:36
std::complex< double > complex_dbl
The double-precision complex number type.
Definition double_extensions.hpp:47
Tracking / precision settings to emit in the CONFIG section, in Bertini 1 terms.
Definition classic_writer.hpp:113
double tracktolbeforeeg
Newton tolerance before the endgame.
Definition classic_writer.hpp:117
unsigned stepsforincrease
StepsForIncrease (B2 default 5).
Definition classic_writer.hpp:125
unsigned maxnewtonits
MaxNewtonIts (B2 default 2).
Definition classic_writer.hpp:127
int tracktype
0 = zero-dimensional solve
Definition classic_writer.hpp:114
unsigned long maxnumbersteps
MaxNumberSteps (B2 default 1e5).
Definition classic_writer.hpp:126
int mptype
0 double, 1 fixed-multiple, 2 adaptive
Definition classic_writer.hpp:115
double maxstepsize
MaxStepSize (B2 SteppingConfig default 1/10).
Definition classic_writer.hpp:122
unsigned maxcrossedpathresolves
endgame-boundary crossed-path re-track attempts
Definition classic_writer.hpp:128
double tracktolduringeg
Newton tolerance during the endgame.
Definition classic_writer.hpp:118
double stepsuccessfactor
StepSuccessFactor (B2 default 2).
Definition classic_writer.hpp:123
int odepredictor
5 = RKF45 (the Bertini 2 default)
Definition classic_writer.hpp:116
double finaltol
final tracking tolerance
Definition classic_writer.hpp:119
double stepfailfactor
StepFailFactor (B2 default 1/2).
Definition classic_writer.hpp:124
Provides the bertini::System class.
Configs and settings for tracking.