CLI, so many bugfixes, block structured systems, mhom exposed, user homotopy, two-level parallelism...#238
Open
ofloveandhate wants to merge 515 commits into
Open
CLI, so many bugfixes, block structured systems, mhom exposed, user homotopy, two-level parallelism...#238ofloveandhate wants to merge 515 commits into
ofloveandhate wants to merge 515 commits into
Conversation
…kObserver.on
Tracker events are templated on the emitter, so each precision exposes its own
SuccessfulStep/TrackingStarted/... class under observers.amp/double/multiple --
forcing users to know the precision just to name an event. Two ergonomic fixes,
both pure-Python (the templated-on-emitter C++ design that gives observers full
typed access to event.tracker() is untouched):
- bertini.tracking.events.<Name> bundles the three precision variants into a
tuple, which works directly with isinstance() and CallbackObserver.on(). So
`events.SuccessfulStep` works regardless of precision.
- CallbackObserver.on() now also accepts the event name as a string, resolved
against the observer's own precision: obs.on("SuccessfulStep", cb).
Tests cover the tuple-union handle and the string form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds nag_algorithms/events.hpp with four events emitted during a solve: AlgorithmStarted / AlgorithmComplete (around the whole Solve loop) and PathBeginning / PathComplete (around ExecuteOnePath, the per-start-point unit; PathComplete fires even when the pre-endgame leg fails). PathBeginning/Complete carry the path index. They are emitted on the non-templated AnyZeroDim base, so a SINGLE observer type can watch every templated ZeroDim variant (no per-instantiation explosion). An observer recovers the concrete solver from event.Get() -- in C++ via dynamic_cast, in Python (next commit) automatically via RTTI. ZeroDim overrides ObservableIsA to accept AnyZeroDim observers (in addition to its exact type). The point: between a PathBeginning and its PathComplete, the solver runs everything for that path -- main homotopy track AND endgame sub-tracks -- so an observer can group them as one complete solution path (the basis for SolutionPathCollector). (Event names are working placeholders; more events can be added by following the same pattern.) C++ tests: a ZeroDim observer sees AlgorithmStarted once, AlgorithmComplete once, and matched PathBeginning/PathComplete per path; a tracker observer attached to a ZeroDim is rejected. test_nag_algorithms (22) green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…erver + lifecycle events)
The Python ZeroDim solvers now have add_observer/remove_observer (ObservableVisitor
on ZDVisitor), and a new bertini.nag_algorithms.observers submodule exposes the
single AnyZeroDim-based observer surface for every solver variant:
- CustomObserver (subclassable base, shared_ptr holder -> co-owned when attached)
- AlgorithmStarted / AlgorithmComplete / PathBeginning / PathComplete
(PathBeginning/Complete carry .path_index()).
AnyZeroDim is registered and the concrete ZeroDim classes now declare
bases<AnyZeroDim>, so event.solver() (statically AnyZeroDim&) resolves via RTTI to
the concrete solver with its full python API -- confirmed by a test reading
e.solver().solutions() inside Observe(). The attach guard distinguishes observables:
a nag observer is rejected on a tracker and a tracker observer on the solver
(TypeError).
Tests in meta_observer_test.py cover the lifecycle event counts/indices, the
RTTI concrete-solver recovery, and the cross-observable guard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…game) in one observer bertini.nag_algorithm.SolutionPathCollector is the two-level meta-observer the dream was after. Attach it to a ZeroDim solver: on each PathBeginning it spins up a fresh tracking PathDataCollector and attaches it to the solver's tracker, and on the matching PathComplete it harvests that collector into .series and detaches it. Since the solver reuses one tracker for a path's main homotopy track AND its endgame sub-tracks, the per-path collector captures the entire journey to t -> 0 -- one clean series per solution path, endgame included, with no start-time filtering. It picks the right precision's PathDataCollector via tracker.observers, and recovers the tracker from event.solver().get_tracker() (RTTI-resolved concrete solver). The tutorial now leads with SolutionPathCollector (attach to the solver) as the clean way to collect and plot every path, and the regenerated figure shows each of the six z^6-2z^2+2 paths running all the way into its solution (the endgame carries the last leg). The tracker-level PathCollectionObserver is kept and mentioned as the lower-level building block. Tests: one series per solution path with the expected indices; whole-path series capture at least as many steps as the main-track-only filter. Full observer/nag/zero_dim suites green; docs build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ax.set_aspect(1.0) so Re/Im are scaled equally; regenerated the figure. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…on number New section solving the cyclic-3 system in three variables and plotting the paths in (Re x, Re y, Re z) space, each drawn as a Line3DCollection coloured along its length by the condition number (log scale, shared colorbar) -- showing where the tracking is worst-conditioned (near the solutions / in the endgame). Uses the same SolutionPathCollector and the diagnostics() condition-number column, with a 1:1:1 box aspect. Committed figure cyclic3_paths.png; docs build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…orn) section, SVG+PNG figures - Seed every example with bertini.random.set_random_seed(...) so a reader reproduces exactly the pictures shown. - New section "Watching the Cauchy endgame at a singular solution": solves Griewank-Osborn (triple root at the origin), selects the singular paths from the solver's own metadata (m.is_singular / m.path_index -- no hand-rolled coordinate thresholds), and plots one path's x-coordinate on a LOG-RADIAL scale so the geometrically-shrinking Cauchy loops stay visible as a spiral winding into the singularity (coloured by |t|). - Render every tutorial figure as SVG (crisp in the built docs) and also keep a PNG alongside for local viewing; figure directives reference the SVG. - z^6 plot: add set_box_aspect(1) so the box is square (with 1:1 data scaling). Docs build clean; figures regenerated from seeded scripts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Consistent lifecycle-event naming: AlgorithmStarted/AlgorithmComplete and PathStarted/PathComplete. Renamed the C++ event class, the emission point, the python-exposed class, SolutionPathCollector, and the tests/tutorial. C++ test_nag_algorithms and the python meta_observer suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…late De-template ZeroDim on the start system; add linear-product TotalDegree
First stage of splitting the zero-dim machinery into two roles. Introduce algorithm::HomotopySolver / algorithm::ZeroDimSolver as alias templates over the existing policy-parameterized ZeroDim (RefToGiven and CloneGiven respectively), and migrate the whole public surface onto the new, honest names: - Python bindings expose ZeroDimSolver<EG><Prec> (was ZeroDim<EG><Prec>) and HomotopySolver<EG><Prec> (replaces the ...UserHomotopy classes). - Python wrapper: ZeroDim(...) facade -> ZeroDimSolver(...); first-class HomotopySolver(...) facade; user_homotopy() kept as a thin forwarder. - The old ZeroDim name and the legacy class-name shims are DELETED outright (no alias, no deprecation) -- loud break by request. - All tests, examples, and tutorials re-pointed to the new names. Internal C++ (the ZeroDim template body, ETI, blackbox, output::Classic) is unchanged here; a follow-up collapses the aliases into two concrete, composed classes and retires the system-management policy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mSolver Turn the policy-parameterized ZeroDim<T,E,S,Policy> into two concrete classes, removing the system-management policy as a template parameter of the solver: - HomotopySolver<T,E,S> is the continuation engine: it holds the homotopy, start system, and target by reference (the old RefToGiven layout, now its only layout) and owns all the machinery -- pre-endgame tracking, endgame, crossing resolution, classification, reporting, threaded + MPI solve. The MPI system-broadcast is now a virtual DistributeSystems() hook (no-op here). - ZeroDimSolver<T,E,S> is the algorithm: it clones the user's target, homogenizes and patches it, builds a start system (via the injected factory) and a homotopy (an OwnedHomotopy base built BEFORE the engine base), then IS-A HomotopySolver over those owned systems -- reusing the engine, not duplicating it. It overrides DistributeSystems() to broadcast its owned systems under MPI. ConsistencyCheck moved here; RankCheck()/SquareUp() are stubbed (next). ETI, blackbox switches, output::Classic, and the C++ tests are updated to the two concrete types. common/policies.hpp still defines the now-unused CloneGiven / RefToGiven (deleted in a follow-up that also rehomes the StartSystemFactory and severs the NID placeholder). C++ tests pass (OMP=1); full Python suite green (518 passed, 14 skipped). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… sever NID The system-management policy is fully retired now that ZeroDim's policy parameter is gone: - StartSystemFactory / MakeStartFactory move out of the deleted policy:: into start_system:: (bertini2/system/start_base.hpp) -- they are start-system selection, not system ownership, and the base header is all they need. Every call site (ZeroDimSolver default, blackbox switches, python bindings, C++ tests) is updated. - NumericalIrreducibleDecomposition drops its SystemManagementP/CloneTarget base (it was placeholder scaffolding whose Solve() throws) and owns a cloned target inline. Its template is now <Tracker, Endgame, System>; the binding is unchanged. - common/policies.hpp (CloneGiven / RefToGiven / CloneTarget / SysMgmtPolicy) is deleted, its #includes removed (config.hpp, zero_dim_solve.hpp, NID), and the CMake header list updated. No references to the policy namespace remain. Core + all tests + bindings build; C++ nag/NID/blackbox suites pass (OMP=1); Python suite green (518 passed, 14 skipped). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…check Implement the two ZeroDimSolver feasibility behaviors (previously stubbed): - SquareUp(): an over-determined target (more equations than the affine dimension) is randomized down to square via System::Randomize so a start system can track it. The original system is kept; after the solve, ZeroDimSolver overrides the now-virtual PostEGAction to re-evaluate the ORIGINAL system at each finite endpoint and drop the extraneous solutions the squaring introduces (their function_residual is reported; is_finite -> false, so they leave finite/real/ singular accessors). Exposed: was_randomized() and randomization_matrix(). - RankCheck(): a system that is square by equation count can still be positive-dimensional (e.g. a repeated equation). At a generic point a zero-dimensional system has a full-rank Jacobian, so a rank-deficient Jacobian there raises a clear error. (Under-determined systems are already rejected by ConsistencyCheck, now with a friendlier message.) To support the post-solve filter, PostEGAction is protected+virtual and the per-endpoint metadata / endpoints are protected so ZeroDimSolver can read them. Tests: C++ (square solves w/o randomization; over-determined squared + filtered to the genuine roots; under-determined raises; positive-dimensional square raises) and a Python feasibility_test mirroring them. C++ nag suite passes (OMP=1); full Python suite green (518 passed, 14 skipped). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…solution filter New tutorial python/docs/source/tutorials/zerodim_solver.rst (doctest-runnable, in the toctree): ZeroDimSolver on a pleasant square system, an over-determined system (squared up, extraneous solutions filtered out -- was_randomized / finite_solutions), and an under-determined system (the helpful refusal). Writing it surfaced a precision bug in the extraneous-solution filter: when a prior AMP solve left the dehomogenized point at a higher precision than the original (precision-16) system, the filter's Eval threw a precision mismatch. Fixed by evaluating the original system in double precision -- the filter only needs to tell a tiny residual from an O(1) one, which double does robustly regardless of the solution's tracked precision. C++ nag suite passes (OMP=1); full Python suite green (521 passed, 14 skipped); the tutorial's testcode blocks all run clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…note ADR-0040 records the split rationale: two concrete classes replacing the policy-parameterized ZeroDim, why inheritance over a composed member (avoids duplicated Configured state), where the new feasibility behaviors live, the policies.hpp deletion + StartSystemFactory rehome + NID severance, and that SystemView is obviated. Backfill the README index (0037-0040) and note the rename in ADR-0039. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update the parameter-homotopy, moving-slice, and user-product-of-linears tutorials to call the first-class nag_algorithm.HomotopySolver (the continuation primitive) instead of the user_homotopy forwarder, and reference it consistently with :func:. Identical signature, clearer name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…stalls The wheel ships the bertini2 CLI at bertini/_bin/ via a SKBUILD-gated install rule, but a from-source EDITABLE install (`pip install -e .`) does not run install(), so the console-script shim had no binary to hand off to and the CLI smoke test skipped. Add a non-wheel POST_BUILD step on bertini2_exe that copies the freshly-built CLI into the source-tree python/bertini/_bin/bertini2 (where an editable install resolves the package), guarded on the package dir existing. Now every build path delivers the `bertini2` command: wheel (`pip install .`), editable (`pip install -e .`), and plain in-tree builds. python/bertini/_bin/ is gitignored. CLI smoke tests now run + pass locally (2 passed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tag the bertini2_exe install rules COMPONENT cli, so a user who wants only the solver -- no Python, no library/headers -- can `cmake --install build --component cli` and get just bin/bertini2 (the exe statically links libbertini2.a, so it is self-contained re: our code; it still needs Boost/GMP/MPFR/MPC/MPI like any from-source build). A plain `cmake --install` still installs everything. Verified: --component cli installs only bin/bertini2 (runs); the default install still ships the exe + library + headers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document that the bertini2 CLI is pure C++ (no Python dependency) and how to get it from each build path -- wheel (pip install bertini2), from-source pip (install . / -e .), the Python-free CLI-only install (cmake --install --component cli), and the full C++ dev install -- plus the shared-library expectations and threads-only/MPI note. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow-up on the over-determined filter, for regeneration-cascade use. - SolutionMetaData gains `is_nonsolution`: a finite, successful endpoint that is NOT a solution of the target -- the junk squaring up an over-determined system introduces. The filter now sets THIS (orthogonal to is_finite) instead of is_finite=false, so nonsolutions stay geometrically finite and no longer masquerade as at-infinity. The finite / real / singular accessors exclude them; a new Nonsolutions() / nonsolutions() surfaces them; SolveReport gains num_nonsolutions. - New `solutions(**flags)` getter on both ZeroDimSolver and HomotopySolver: finite genuine solutions by default, with category keywords -- singular / nonsingular, real / nonreal (a finite solution is returned iff its conditioning class AND its realness class are enabled), infinite=True to add at-infinity endpoints, nonsolution=True to add the junk. all_solutions() stays as the raw per-path list. is_nonsolution is bound, added to to_dataframe columns, and documented in the ZeroDimSolver tutorial. Tests: C++ over-determined test asserts the flag / Nonsolutions / report count; Python feasibility_test covers solutions() filtering by realness and nonsolution opt-in. C++ suites pass (OMP=1); Python suite 547 passed / 1 skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…"junk" -> nonsolutions The over-determined test asserted an exact nonsolution count (Nonsolutions == all - 2), which assumes every extra root of the squared system stays finite. How many of the squaring's extra roots land finite vs. diverge to infinity is RNG/gamma-dependent, so that passed locally but failed the Ubuntu C++ job. Assert the ROBUST partition instead: FiniteSolutions + Nonsolutions + InfiniteSolutions == all endpoints (every endpoint is exactly one of genuine finite solution / finite nonsolution / at infinity), plus solutions() == 2 (the genuine roots). Same fix in the Python feasibility test and the tutorial doctest. Also rename the user-facing "junk" wording to "nonsolutions" throughout (report line, docstrings, comments) per review. C++ suites pass (OMP=1 + threaded); Python suite 547 passed / 1 skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…perating-zone test ComputeCOverK drew a FRESH random probe vector on every call, so the c/k operating-zone estimate was non-deterministic: consecutive estimates disagreed by probe noise alone, which could certify (or stall) the zone spuriously and churned an mpfr allocation each call. It now reuses a single fixed probe (new member c_over_k_probe_, generated once per precision, re-precisioned in place), so the estimate is reproducible and CheckForCOverKStabilization measures actual sample stabilization. Effect on the actual default start system (RootsOfUnity), cyclic-5 AMP, seed 1: 3.37s -> ~3.06s with the number of escalating paths dropping from 2 to ~0 (the noisy probe had been driving spurious precision escalation), plus the per-call mpfr churn is gone. Also adds CauchyConfig::num_consecutive_same_cycle_number (default 2): refuse to accept a converged Cauchy approximation until the cycle number has reported the same value that many times in a row, so a coincidental approx_error dip on an unreliable low-precision cycle count is not mistaken for convergence. Exposed in the python bindings; verified not to regress the adaptive case. Scope note: this does NOT fix the linear-product TotalDegree start system, whose Cauchy endgame still stalls near t=0 (double and adaptive) -- that is a separate, known issue for a later sprint. Earlier "TotalDegree" validation through the python facade inadvertently exercised RootsOfUnity, because ZeroDim(sys, startsystem='totaldegree') maps to the default constructor / default start system. C++ ctest green; python suite green (1 pre-existing numpy-env failure unrelated). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…homogenization + interop Adds core/test/classes/start_system_interop_test.cpp (9 cases) exercising the start-system layer at the corners, to establish sanity around the linear-product TotalDegree and its multi-group generalization MHomogeneous: - EVERY start point of TotalDegree and MHomogeneous is verified to be a root of the start system, on its patch, in double AND high multiprecision (not a sampled few). At 100 digits the patch residual is < 1e-90, confirming start points are correctly homogenized and patch-fitted across the precision range -- i.e. there is no start-point patch-normalization defect. - MHomogeneous on a single affine variable group reproduces TotalDegree's Bezout count (product of the function degrees), across several degree tuples -- MHom is a generalization of total degree, and the two must agree on one group. - The blend homotopy H = (1-t) target + gamma t start vanishes at every start point at t=1, for both TotalDegree and MHomogeneous on the same target (homotopy interoperability). - Corners: single-variable degree-d (exactly d start points), Homogenize/Dehomogenize roundtrip, and the construction guards (non-square and homogeneous-group targets must throw). These run only the start-system layer (no full ZeroDim solve), so they are fast and cannot hang. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r hang-prone solves) macOS has no timeout(1), and some solves can spin/churn indefinitely (notably the linear-product TotalDegree start system, whose Cauchy endgame stalls near t=0). This wraps any command with a wall-clock limit and SIGKILLs the whole process group on overrun (exit 124), so a hung solve can't peg a core forever. The b2-mcp server bakes the same behavior into its tool runner; this is the plain-CLI equivalent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…_time_seconds) Adds SolutionMetaData::path_time_seconds -- the wall-clock time to execute a whole path (pre-endgame tracking + endgame), stamped in ExecuteOnePath around both exit points with a monotonic steady_clock. Each path writes only its own metadata slot, so there is no cross-path race in a threaded/distributed solve; it is plumbed through FullPathResult (Pack/Store + serialize) so the manager-worker and MPI paths carry it too. Excluded from SolutionMetaData::operator== (timing is not an identity field). Exposed to Python as the read-write `path_time_seconds` attribute and added to to_dataframe()'s column set, so per-path cost shows up in the solutions dataframe alongside condition_number and max_precision_used (e.g. sort paths by time, or correlate time with precision escalation). Verified: default cyclic-5 solve stamps all 120 paths (sum ~3.0s), C++ ctest 10/10 green, python suite green (1 pre-existing numpy-env failure unrelated). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…segfaulting
Manually composing a homotopy with a structured-block start system -- e.g.
(1-t)*target + gamma*t*TotalDegree, exactly the gamma-trick in the manual-endgame tutorial --
SEGFAULTED. System::operator+= and operator*= only touched PolyBlock().Functions(), but the
linear-product TotalDegree (and MHomogeneous) keep their functions in a ProductsOfLinearsBlock, not
the PolynomialBlock. So:
* operator*= (gamma*t*td) silently multiplied an EMPTY PolynomialBlock -> a wrong result (the start
system left unscaled), no crash;
* operator+= then indexed rhs.PolyFunctions() (size 0) up to lhs's function count -> out-of-bounds
read -> segmentation fault.
Both operators now detect a structured block (HasStructuredBlocks) and, in that case, expand every
block to function-tree nodes via NaturalFunctionsAsNodes(), operate on those, and store the result as
a single PolynomialBlock (a function-tree system that evaluates and tracks correctly). The
pure-polynomial fast path is unchanged, so existing systems are unaffected.
Verified: the previously-segfaulting (1-t)*gw + t*gamma*TotalDegree now builds a correct homotopy
(all 6 start points solve H at t=1 to ~5e-11), the manual_endgame_usage doctest no longer crashes,
C++ ctest 10/10 green, python suite green (1 pre-existing numpy-env failure unrelated).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mplated names After the de-templating (the start system is no longer baked into the ZeroDim type), the bound class names dropped the start-system suffix: ZeroDimCauchyDoublePrecision (not ...TotalDegree), etc. Update the doctest assertions accordingly and note that the start system is now a construction choice, so it is not part of the class name. (The separate precision_matters doctest -- at-infinity paths counted as num_failed -- is being handled elsewhere; untouched here.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…bertiniteam#263) System::Function(index) dereferenced PolyBlockPtr() with no null check, so it segfaulted on a system built from a slice (a pure LinearFormsBlock, with no PolynomialBlock). Route Function() and GetNaturalFunctions() through NaturalFunctionsAsNodes() so every block type (polynomial, linear forms, products of linears, randomization, blend) is expanded to a function-tree node on demand, in sync with NumNaturalFunctions(); out-of-range now throws std::out_of_range (-> Python IndexError) instead of crashing. Add System::Slices() (bound as system.slices()) to back out the linear-form slices embedded in a system -- the inverse of Slice.as_system() -- without exposing the Block variant to Python. Tests: function_accessor_test.py covers function(i) across all five block types plus slices() round-trip and node/block eval agreement; C++ system_blocks suite gains structured-block Function()/Slices() cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The over-determined filter flags is_nonsolution (a dedicated, orthogonal metadata field) rather than is_finite=false, so nonsolutions stay geometrically finite and are surfaced by Nonsolutions() / counted in num_nonsolutions; it is load-bearing for the regeneration cascade. Also note the additive solutions(**flags) getter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ertiniteam#264) A system built from a slice printed every function as the opaque placeholder `c.[x, y, z, 1]`, hiding the coefficients. Keep the placeholder (structure stays legible) and print the actual coefficient matrix just below it as a named-expression-style `c =` legend: 4 significant figures in the default / terse describe, full working precision under describe(verbose=True). The same applies to a randomization block's `R` matrix, which was previously gated behind verbose -- it now shows in the default describe too. PrintCoeff gains a significant-digits parameter (terse=4, verbose=current precision; the master coefficient matrix is stored far above working precision, so its full string would be thousands of digits). Each structured block truncates its terse listing after kTerseRowCap (10) rows with a "... (k more)" note so a large slice does not flood the terminal; verbose prints everything. products-of-linears and blend keep their existing structural terse output (they carry no inline coefficients to shorten). Tests: system_printing_test (Python + C++) updated for the new default output and extended with terse-vs-verbose digit-width and row-cap-truncation cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…_homotopysolver Split ZeroDim into HomotopySolver (engine) + ZeroDimSolver (algorithm)
# Conflicts: # python/docs/source/tutorials/precision_models.rst
…-timing Cauchy c/k probe determinism, start-system sanity tests, per-path timing
…ystem fix: function() on slice-derived systems + system.slices() (bertiniteam#263)
feat: show low-precision coefficients in system describe (bertiniteam#264)
The `H.eval_time_derivative(...)` block in the moving-slice tutorial failed under `sphinx -b doctest`: the preceding adaptive `solver.solve()` leaves the homotopy H at double precision (16), while the multiprecision evaluation point is created at the multiprec literal default (20), so the direct eval raised "precision of input point in SetVariables (20) must match the precision of the system (16)". Match H to the evaluation point's precision before the direct eval. (Using `bertini.default_precision()` does NOT work here: the AMP solve leaves the global default at 16, which disagrees with the multiprec literal default of 20 -- a latent precision-state inconsistency worth a separate look, but out of scope for this doctest fix.) Found by running the full tutorial doctest suite locally (it is not in the per-push PR CI, only the dispatched build_docs workflow): 147 tests, now 0 failures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ecision fix(docs): moving_slice eval_time_derivative doctest precision mismatch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.