bertini.config

Reusable, low-friction ergonomics for Bertini config structs.

The C++ bindings expose each config struct (SteppingConfig, NewtonConfig, the endgame configs, the zero-dim configs, …) with one writable attribute per field, and expose each owner (every tracker and nag_algorithm) with a uniform, type-list-driven config interface: set_config, get_config and config_types (see configured_visitor.hpp).

This module layers Pythonic conveniences on top of those, with no per-config and no per-algorithm code – everything is discovered by introspection, so a newly added algorithm and its configs get the whole interface for free:

  • configs gain update(**kwargs) (chainable, validated), to_dict(), from_dict(), a readable repr and value-equality;

  • owners gain configure(**kwargs) and config_names(), built on the owner’s own config_types() so they always reflect what the owner accepts.

bertini.config.writable_fields(cls)[source]

The names of the writable (def_readwrite) data members of a bound class.

Discovered by walking the class for data descriptors (__set__), so it requires no hand-maintained field lists and tracks the C++ struct exactly.

bertini.config.config_key(cls)[source]

A short, snake_case keyword for a config class (drops a trailing ‘Config’).

e.g. SteppingConfig -> ‘stepping’, AMPConfig -> ‘amp’,

PostProcessingConfig -> ‘post_processing’.

bertini.config.configure(self, **kwargs)[source]

Change settings on this owner’s configs in one call.

Each keyword names a config (e.g. stepping, newton, tolerances); its value is either a dict of fields to change, or a ready config object.

tracker.configure(stepping={‘max_step_size’: 0.1},

newton={‘max_num_newton_iterations’: 2})

Returns self.

bertini.config.config_names(self)[source]

The keyword names accepted by configure() for this owner.

bertini.config.update(self, **fields)[source]

Set config fields on this owner by NAME, each routed to whichever config owns it.

You never name the config struct:

solver.update(final_tolerance="1e-11",          # -> TolerancesConfig
              max_num_crossed_path_resolve_attempts=3)   # -> ZeroDimConfig

Strings work for every numeric field (converted exactly). A field that none of this owner’s configs has raises AttributeError with the valid names – so a typo, or trying to set a tracker field on the algorithm (or vice versa), never silently does nothing. Returns self, so calls chain. To set a whole config at once, or to name the config explicitly, use configure().

bertini.config.get_settings(self, as_dict=False)[source]

This owner’s whole configuration as a carryable dict.

By default (as_dict=False) the value is {config_name: config} – each a copy of one of the owner’s configs (e.g. {'stepping': SteppingConfig(...), 'tolerances': TolerancesConfig(...)}), keyed by the short names config_names() lists. The configs are independent copies (and picklable), so the dict is a plain Python value you can stash, tweak, and apply to other owners – the way to carry one set of tracking settings across a series of related solves:

settings = first_solver.get_settings()
next_solver.set_settings(settings)

Pass as_dict=True for the flat, human-readable view instead: one {field_name: value} dict across ALL configs (field names are unique across an owner’s configs, so there is no collision). That form drops the struct layer nobody wants to poke at, and round-trips through set:

flat = solver.get_settings(as_dict=True)   # {'final_tolerance': ..., 'max_step_size': ..., ...}
other.set(**flat)

(The config-keyed default is kept because set_settings consumes it; use whichever fits.) See set_settings() for applying the config-keyed form back.

bertini.config.set_settings(self, settings, strict=False)[source]

Apply a settings dict (from get_settings()) onto this owner. Returns self.

settings is {config_name: config} (or {config_name: {field: value}}). By default only the configs this owner actually has are applied and the rest are skipped – so a bundle carried from one solver drops cleanly onto another whose config set differs (e.g. a different precision model, or a different algorithm stage). Pass strict=True to instead raise on any key this owner does not have.