Skip to content

Python API

The novomodelo package is the Python binding of the Novomodelo solver (import novomodelo). This page lists the signature, behaviour, return shape and raised exception classes of each public name in the novomodelo package, novomodelo.run, novomodelo.io, novomodelo.results, novomodelo.errors and novomodelo.schema, and the fields of the data classes in novomodelo.model and the typed result dicts in novomodelo._types. To install the package, see Installation; for a guided first session, see the Python Quickstart.

Conventions used by every entry:

  • Paths accept str or pathlib.Path.
  • The package runs in a single process. It never initialises MPI, and it releases the GIL (Python’s global interpreter lock) while the solver computes.
  • Warning diagnostics are written to file descriptor 2. contextlib.redirect_stderr does not capture them.
  • Each heading is the qualified name of a symbol and is the anchor of that entry (#novomodelostudytrain for novomodelo.Study.train).
__version__: str

The package version string, for example 0.18.0.

def version_info() -> dict[str, Any]: ...

Describes the running build. The dict has the keys version (equal to novomodelo.__version__), solver (the LP backend and its version), comm (always local, because the package is single-process), zstd (enabled), arch (target architecture and operating system) and build (debug or release).

Returns: the build description dict.

import novomodelo
print(novomodelo.version_info())
{'version': '0.18.0', 'solver': 'HiGHS 1.13.1', 'comm': 'local', 'zstd': 'enabled', 'arch': 'x86_64-linux', 'build': 'release'}
class Study:
def __init__(
self,
case_dir: Union[str, Path],
output_dir: Optional[Union[str, Path]] = None,
threads: Optional[int] = None,
config_overrides: Optional[Mapping[str, Any]] = None,
) -> None: ...

A loaded, reusable study. Construction loads the case, resolves the configuration, runs the stochastic and hydro-model preprocessing, and writes training/scaling_report.json, training/model_provenance.json and training/hydro_models.json (plus the stochastic exports when enabled) under output_dir. Validation happens here: a case or configuration that fails validation raises from the constructor, so a constructed Study is valid.

Parameters

  • case_dir: the case directory.
  • output_dir: where results are written. Defaults to <case_dir>/output.
  • threads: worker threads for training and simulation, at least 1. None runs on one thread, not on every core. The value is stored for train and simulate and is not used while loading.
  • config_overrides: a flat mapping of dotted keys deep-merged into config.json. {"training.enabled": False} sets that one key and keeps its sibling keys. A nested value under a single key replaces the whole object at that key, so {"training": {"enabled": False}} discards every other training key and fails validation. An unknown key fails validation. For the keys, see Configuration.

Raises

  • OSError (builtin) when case_dir does not exist, before any work.
  • ValueError (builtin) when threads is 0, or when config_overrides has a non-str key or an unsupported value type.
  • novomodelo.errors.ValidationError for a configuration override, parse or read failure, for a missing or unreadable case file, and for a schema, parse or constraint failure in the case data, for a refused policy.path, and for an invalid-input setup failure such as an unsupported stochastic model (no valid historical windows found).
  • novomodelo.errors.CaseIoError when writing one of those files fails, such as under an unwritable output_dir.
  • novomodelo.errors.SolverError for a solver or internal failure during preprocessing or construction.
@property
def output_dir(self) -> str: ...

The resolved output directory as a string.

@property
def system(self) -> System: ...

The loaded novomodelo.model.System. The property shares the study’s system; it does not copy it.

@property
def stochastic(self) -> StochasticSummary: ...

The structural stochastic summary, a dict fixed at construction. Its shape is novomodelo._types.StochasticSummary.

@property
def hydro_models(self) -> HydroModelsSummary: ...

The structural hydro-model summary, a dict fixed at construction. Its shape is novomodelo._types.HydroModelsSummary; for the 1dtoy scaffold it reads {'n_constant': 1, 'n_fpha': 0, 'total_planes': 0, 'n_evaporation': 0, 'n_no_evaporation': 1}.

@property
def provenance(self) -> ProvenanceReport: ...

The model-provenance report, a dict fixed at construction. Its shape is novomodelo._types.ProvenanceReport.

def validate(self) -> dict[str, Any]: ...

Reports the warnings captured during construction and checks the configured policy load against the study’s output_dir, without re-reading the case.

Returns: {"valid": True, "errors": [], "warnings": [...]}. The result has the same shape as novomodelo.io.validate. valid is False, with the error novomodelo.io.validate reports for that directory, when the configured policy load fails; policy-load warnings join warnings.

def train(
self,
on_iteration: Optional[Callable[[dict[str, Any]], Any]] = None,
) -> "Policy": ...

Trains an SDDP policy against the study’s in-memory setup and returns a novomodelo.Policy. The call writes the policy to <output_dir>/<policy.path> (default policy/) and the training artifacts under training/. The GIL is released while the solver computes; the callback runs on a separate thread that takes the GIL only at iteration boundaries.

Parameters

  • on_iteration: called once per iteration boundary with a dict holding kind, iteration, lower_bound, upper_bound, gap and wall_time_ms. gap is the raw relative gap, not multiplied by 100. A truthy return requests a cooperative stop at a later iteration boundary; the stop is asynchronous, so the iteration at which the run ends is not fixed. An exception raised by the callback is re-raised verbatim after the artifacts are written.

A stop requested by the callback, or an exception raised by it, ends the run with convergence.termination_reason set to "graceful_shutdown" and status set to "partial" in training/metadata.json unless the stopping rules or the iteration budget also ended it at that iteration; see training/metadata.json.

Returns: a novomodelo.Policy. With training.enabled set to false, train returns a zero-iteration policy that holds no cuts; simulate rejects it. Load a trained policy with load_policy instead.

A second train call on the same Study runs against a setup that already carries the first call’s cuts, so it is not a fresh training. On the 1dtoy scaffold the second call raises SolverError (basis row count mismatch).

Raises

  • novomodelo.errors.SolverError for a solver initialisation failure or a training failure the solver classifies.
  • novomodelo.errors.ValidationError for a missing prior policy directory under warm start or resume (Policy directory not found: ...), and for a refused boundary or training input.
  • novomodelo.errors.PolicyIncompatibleError when the warm-start or resume checkpoint at policy.path fails the Policy Load Contract, a policy.boundary checkpoint was written by another software or version, or a checkpoint’s manifest.bin is missing or cannot be decoded.
  • novomodelo.errors.CaseIoError when writing the policy or a training artifact fails; a periodic-checkpoint write failure raises FileNotFoundError, CaseIoError, novomodelo.errors.OutputError or ValidationError by its cause.
  • novomodelo.errors.InternalError when the callback thread panics.
  • Any exception raised by the callback, and KeyboardInterrupt, re-raised after the artifacts are written.
def load_policy(
self,
output_dir: Optional[Union[str, Path]] = None,
) -> "Policy": ...

Reads a policy checkpoint from <output_dir>/<policy.path>/ and returns a novomodelo.Policy that simulate accepts in the same way as a trained one. The checkpoint is always checked against the study’s state dimension, stage count and terminal entity manifest.

Parameters

  • output_dir: the directory that holds the policy. Defaults to the study’s output_dir.

Returns: the loaded novomodelo.Policy.

Raises

  • novomodelo.errors.ValidationError when the policy directory is missing (Policy directory not found: ...).
  • novomodelo.errors.PolicyIncompatibleError when the checkpoint cannot be read, decoded or reconstructed, or policy validation rejects it.
  • novomodelo.errors.CaseIoError when a checkpoint file cannot be opened.
def simulate(
self,
policy: "Policy",
output_dir: Optional[Union[str, Path]] = None,
) -> dict[str, Any]: ...

Runs the simulation phase with policy and writes the simulation/ artifacts. Each call writes a fresh output set, and one policy can feed repeated calls.

Parameters

  • policy: a novomodelo.Policy from train or load_policy.
  • output_dir: where the simulation/ directory is written. Defaults to the study’s output_dir.

Returns: {"n_scenarios": int, "completed": int}, for example {'n_scenarios': 10, 'completed': 10}.

Raises

  • novomodelo.errors.SolverError when the policy holds no cuts (Policy has no cuts to simulate; when training is disabled, call Study.load_policy() to load a trained policy before simulate()), or on a simulation workspace initialisation failure.
  • novomodelo.errors.SimulationError for a simulation failure.
  • novomodelo.errors.CaseIoError for a writer failure.
  • novomodelo.errors.InternalError when the worker thread panics.
class Policy: ...

A trained or loaded policy: the Benders cuts that approximate the future cost of each stage, together with the data novomodelo.Study.simulate needs. The class has no Python constructor; novomodelo.Policy() raises TypeError (cannot create 'builtins.Policy' instances). Obtain a handle from novomodelo.Study.train or novomodelo.Study.load_policy.

Every stage argument is 0-based: stage t of the 1-based numbering used in the methodology is stage = t - 1.

evaluate and cut_matrix read the in-memory cut pool, which holds intercepts and coefficients in the solver’s cost scale: the checkpoint’s currency-unit values divided by the pool’s cost_scale_factor (modeling.cost_scale_factor, 1000000.0 by default). Multiply by cost_scale_factor to get currency units. final_lower_bound, final_upper_bound and the values returned by novomodelo.results.load_policy are in currency units. For the conversion, see Cost-Scale Canonicalization.

@property
def iterations(self) -> int: ...

The number of completed training iterations. A policy from load_policy reports the checkpoint’s completed_iterations; a training-disabled policy reports 0.

@property
def final_lower_bound(self) -> float: ...

The final lower bound, in currency units. A policy from load_policy reports the checkpoint’s recorded final lower bound; a training-disabled policy reports 0.0.

@property
def final_upper_bound(self) -> float: ...

The final mean upper bound, in currency units. A policy from load_policy reports the checkpoint’s recorded upper bound (the last training iteration’s value, not a running best), or inf when the checkpoint records none; a training-disabled policy reports inf.

def evaluate(self, stage: int, state: Sequence[float]) -> float: ...

Evaluates the future-cost function at state: the maximum over the stage’s active cuts of intercept + coeffs · state. The value is in the solver’s cost scale, not in currency (see novomodelo.Policy). A stage with no active cut returns float('-inf'); the last stage of the 1dtoy case holds none.

Parameters

  • stage: the 0-based stage index.
  • state: the incoming state, one float per state dimension of the policy (1 for the 1dtoy case).

Returns: the future-cost value as a float.

Raises

  • IndexError (builtin) when stage is at or beyond the stage count (stage 4 out of range (policy has 4 stages)).
  • ValueError (builtin) when state has the wrong length (state has length 2, expected 1 (policy state dimension)).
  • OverflowError (builtin) when stage is negative.
def cut_matrix(self, stage: int) -> tuple[Any, Any]: ...

Returns the active cuts of one stage as two NumPy arrays, in ascending slot order. Read cut k as θ ≥ intercepts[k] + coeffs[k] · state. The coefficients are the stored values, not negated. The values are in the solver’s cost scale, not in currency (see novomodelo.Policy).

Parameters

  • stage: the 0-based stage index.

Returns: (intercepts, coeffs), two float64 arrays of shapes (n_cuts,) and (n_cuts, dim), where dim is the policy state dimension. A stage with no active cut returns shapes (0,) and (0, dim).

Raises

  • IndexError (builtin) when stage is at or beyond the stage count.
  • OverflowError (builtin) when stage is negative.
  • ImportError (builtin) when NumPy is not installed.
import novomodelo
import novomodelo.results
study = novomodelo.Study("case", output_dir="output")
policy = study.train()
intercepts, coeffs = policy.cut_matrix(0)
print(intercepts.shape, coeffs.shape)
print(policy.evaluate(0, [50.0]))
saved = novomodelo.results.load_policy("output")
stage0 = saved["stage_cuts"][0]
print(intercepts[0], stage0["cuts"][0]["intercept"])
print(stage0["cost_scale_factor"])
print(round(stage0["cuts"][0]["intercept"] / intercepts[0]))
(128,) (128, 1)
21.650084092030454
31.669512704831718 31669512.70483172
1000000.0
1000000

The saved intercept is cost_scale_factor times the in-memory one. The evaluate result of about 21.65 is therefore about 21650084 in currency units.

def write_policy_checkpoint(
path: Union[str, Path],
stage_cuts: Sequence[Mapping[str, Any]],
metadata: Mapping[str, Any],
stage_bases: Optional[Sequence[Mapping[str, Any]]] = None,
stage_states: Optional[Sequence[Mapping[str, Any]]] = None,
inflow_lag_depth: Optional[int] = None,
) -> None: ...

Writes a policy checkpoint to path from plain Python dicts. stage_cuts and metadata mirror the "stage_cuts" and "metadata" keys that novomodelo.results.load_policy returns, so a loaded checkpoint round-trips. stage_bases and stage_states default to empty. The checkpoint always records the running novomodelo version; software, software_version or novomodelo_version keys in metadata are ignored. For the dict shapes, see Write a checkpoint, Round-trip example and Input validation.

inflow_lag_depth = N with N > 0 reserves N inflow-lag state slots per storage hydro in every stage and places each cut’s inflow_lag_coefficients at their (hydro, depth) positions. Use it to author a boundary policy for a converted case with no PAR model to infer the depth from. Absent or 0, the checkpoint is identical to one written without the argument.

Returns: None.

Raises

  • ValueError (builtin) when a cut’s coefficients length differs from its stage’s state_dimension, when a stage’s state data length differs from count * state_dimension, when a cut carries inflow_lag_coefficients without a positive inflow_lag_depth, or, with inflow_lag_depth set, when a stage manifest lacks a leading storage block or an inflow-lag coefficient has no slot to be placed in.
  • novomodelo.errors.ValidationError (a ValueError) when path (for a link, its target) or its .staging or .previous sibling holds an entry no checkpoint writer leaves there (refusing to write a checkpoint: ...); nothing on disk changes.
  • A novomodelo.errors class mapped from the underlying write failure for any other error, such as novomodelo.errors.OutputError.
def run(
case_dir: Union[str, Path],
output_dir: Optional[Union[str, Path]] = None,
threads: Optional[int] = None,
config_overrides: Optional[Mapping[str, Any]] = None,
on_iteration: Optional[Callable[[dict[str, Any]], Optional[bool]]] = None,
) -> RunResult: ...

Loads a case, trains, simulates when the configuration enables it, and writes the results. One novomodelo.Study drives the call. The phases that run follow the configuration, in three branches.

Parameters

Returns: a dict of shape novomodelo._types.RunResult. All keys are present on every branch; the values below differ by branch.

Branchconvergediterationslower_boundupper_boundgap_percentsimulation
Training enabledTrue when the stopping rules ended training and a gap or bound_stalling rule triggered at that iteration; False for any other stopping reasoniterations runfinal lower boundfinal upper boundgap times 100the summary dict, or None if simulation is off
Training disabled, simulation enabled (simulation-only)False0the checkpoint’s lower boundthe checkpoint’s recorded upper bound (the last training iteration’s value), None if not finiteNonethe summary dict
Both disabledFalse00.0NoneNoneNone

gap_percent is the relative gap times 100; see Optimality gap. A simulation-only run loads the policy from <output_dir>/<policy.path>/ (default policy/); see Simulation-Only Mode. The stochastic, hydro_models and provenance keys hold the same summaries as the Study properties.

A Ctrl-C during the run is delivered as KeyboardInterrupt after the call returns to the interpreter, not at an iteration boundary. To end a run early, return a truthy value from on_iteration.

A stop requested by on_iteration records convergence.termination_reason as "graceful_shutdown" in training/metadata.json unless the stopping rules or the iteration budget also ended it at that iteration; see training/metadata.json.

Raises

  • OSError (builtin) when case_dir does not exist.
  • ValueError (builtin) when threads is 0, or when config_overrides is malformed.
  • The classes listed for novomodelo.Study, novomodelo.Study.train and novomodelo.Study.simulate, according to the phase that fails.
  • Any exception raised by the callback, re-raised verbatim after the artifacts are written.
import novomodelo.run
def on_iteration(info):
print(info)
return info["iteration"] >= 3 # a truthy return requests a stop
novomodelo.run.run("case", output_dir="output", on_iteration=on_iteration)
{'kind': 'iteration', 'iteration': 1, 'lower_bound': 5060208.389407688, 'upper_bound': 17125951.86504142, 'gap': 2.3844360838756016, 'wall_time_ms': 3}
{'kind': 'iteration', 'iteration': 2, 'lower_bound': 6970347.641468819, 'upper_bound': 583065.7603054191, 'gap': -0.9163505480219415, 'wall_time_ms': 5}
{'kind': 'iteration', 'iteration': 3, 'lower_bound': 7171550.050534338, 'upper_bound': 12565763.664663631, 'gap': 0.7521684400330416, 'wall_time_ms': 7}

wall_time_ms varies between runs. The stop requested at iteration 3 takes effect at a later iteration boundary, so the run can finish after more than three iterations.

def load_case(path: Union[str, Path]) -> model.System: ...

Loads and validates a case directory through the full validation pipeline and returns a novomodelo.model.System. A relative path resolves from the process working directory.

Parameters

  • path: the case directory.

Returns: the validated novomodelo.model.System.

Raises

  • OSError (builtin) when the directory does not exist.
  • novomodelo.errors.ValidationError for a missing or unreadable case file (reported as a [FileNotFound] constraint violation) and for a parse, schema or constraint failure.
def validate(
path: Union[str, Path],
config_overrides: Optional[Mapping[str, Any]] = None,
*,
output_dir: Optional[Union[str, Path]] = None,
) -> dict[str, Any]: ...

Runs the full validation pipeline (case structure, schema, configuration, stochastic preparation, hydro models, generic constraints, study construction, boundary reconciliation when configured, and the configured warm-start, resume or simulation-only policy load from <output_dir>/<policy.path>) and stops at the first failure. validate returns failures as data; it does not raise for an invalid case.

Parameters

  • path: the case directory. A missing directory yields a failure entry of kind IoError.
  • config_overrides: as for novomodelo.Study.
  • output_dir: keyword-only; the directory the policy load reads from. Defaults to <path>/output; a relative path resolves from the working directory. Nothing is written, and an absent directory is not created.

Returns: a dict with valid (bool), errors (a list of {"kind", "message"} dicts; empty when valid is True) and warnings (a list of {"kind", "message", "file", "entity"} dicts). Warnings do not change valid.

Raises

  • ValueError (builtin) only when config_overrides is malformed.
import novomodelo.io
report = novomodelo.io.validate("case")
print(report)
{'valid': True, 'errors': [], 'warnings': []}

Loaders for the artifacts a run writes under its output directory. Every function takes output_dir, the directory that holds training/, simulation/, policy/ and stochastic/. A relative path resolves from the process working directory, and a missing output_dir raises FileNotFoundError. NumPy and pyarrow are optional dependencies, imported only by the functions that return their types. To read the numbers, see Convergence & Diagnostics.

def load_results(output_dir: Union[str, Path]) -> dict[str, Any]: ...

Reads the run manifests.

Parameters

  • output_dir: the output directory.

Returns: a dict with two sub-dicts.

  • "training": "metadata", the parsed training/metadata.json; "manifest", an alias of "metadata" with equal contents; "convergence_path" and "timing_path", the absolute paths of training/convergence.parquet and training/timing/iterations.parquet; and "complete".
  • "simulation": "manifest", the parsed simulation/metadata.json, or None when that file is absent (simulation did not run); and "complete".

Both "complete" values are _SUCCESS marker flags, not a verdict on the run. training["complete"] is always True in a returned dict, because the call raises when the training/_SUCCESS marker is absent. simulation["complete"] is True when simulation/_SUCCESS exists and False otherwise. To learn how a run ended, read the metadata dicts; see Metadata Files.

Raises

  • FileNotFoundError (builtin) when output_dir or training/_SUCCESS is missing.
  • ValueError (builtin) when a metadata file is not valid JSON.
  • OSError (builtin) for other read failures.
def load_convergence(output_dir: Union[str, Path]) -> Any: ...

Reads training/convergence.parquet; for the columns, see training/convergence.parquet.

Parameters

  • output_dir: the output directory.

Returns: a list[dict] with one dict per row (one per training iteration), keyed by the file’s own columns. The list is empty when the file has zero rows.

Raises

  • FileNotFoundError (builtin) when output_dir or training/convergence.parquet is missing.
  • OSError (builtin) for other I/O failures and Parquet decoding failures.
import novomodelo.results
import novomodelo.run
novomodelo.run.run("case", output_dir="output")
rows = novomodelo.results.load_convergence("output")
print(len(rows))
print(sorted(rows[0]))
128
['cuts_active', 'cuts_added', 'cuts_removed', 'forward_passes', 'gap_percent', 'iteration', 'lower_bound', 'lp_solves', 'mean_rows_in_lp', 'time_backward_ms', 'time_forward_ms', 'time_total_ms', 'upper_bound', 'upper_bound_kind', 'upper_bound_std']
def load_convergence_arrow(output_dir: Union[str, Path]) -> Any: ...

Reads the same file as novomodelo.results.load_convergence without building Python objects per value.

Parameters

  • output_dir: the output directory.

Returns: a pyarrow.Table with the schema of training/convergence.parquet.

Raises

  • FileNotFoundError (builtin) when output_dir or training/convergence.parquet is missing.
  • OSError (builtin) for Parquet decoding failures or Arrow serialisation errors.
  • ImportError (builtin) when pyarrow is not installed.
def load_simulation(
output_dir: Union[str, Path],
entity_type: Optional[str] = None,
) -> Any: ...

Reads the Hive-partitioned Parquet files under simulation/; see Simulation Output and Hive Partitioning. Each row dict carries a scenario_id key, read from the file’s own scenario_id column or, when the file has none, from the partition path, and rows are ordered by scenario_id.

Parameters

  • output_dir: the output directory.
  • entity_type: the name of a simulation/ subdirectory, such as "costs", "hydros" or "thermals". None loads every entity directory that exists.

Returns: with entity_type, a list[dict] of row dicts. Without it, a dict[str, list[dict]] keyed by entity type (for the 1dtoy case: buses, costs, hydro_bus_generation, hydros, inflow_lags and thermals).

Raises

  • FileNotFoundError (builtin) when output_dir, simulation/ or the named entity directory is missing.
  • OSError (builtin) for corrupt Parquet files and other I/O failures.
def load_simulation_arrow(
output_dir: Union[str, Path],
entity_type: Optional[str] = None,
) -> Any: ...

Reads the same files as novomodelo.results.load_simulation as Arrow tables, with all scenarios concatenated in ascending scenario_id order.

Parameters

  • output_dir, entity_type: as for load_simulation.

Returns: with entity_type, a pyarrow.Table. Without it, a dict[str, pyarrow.Table] keyed by entity type. The first column of each table is scenario_id (the first three columns of the 1dtoy costs table are scenario_id, stage_id and node_id).

Raises

  • FileNotFoundError (builtin) when output_dir, simulation/ or the named entity directory is missing.
  • OSError (builtin) for corrupt Parquet files or Arrow serialisation errors.
  • ImportError (builtin) when pyarrow is not installed.
def load_policy(
output_dir: Union[str, Path],
policy_subdir: str = "policy",
) -> Any: ...

Reads the policy checkpoint from <output_dir>/<policy_subdir> into plain dicts; see Policy Checkpoint. The function does not check the novomodelo version that wrote the checkpoint. For the key tables, see Load a policy.

Parameters

  • output_dir: the output directory.
  • policy_subdir: the checkpoint directory under output_dir. Pass the configured policy.path when it is not policy.

Returns: a dict with the keys metadata, stage_cuts and stage_bases. stage_cuts holds one entry per cut pool, one per stage on a stage chain (four for the 1dtoy case). Intercepts and coefficients are in currency units; see novomodelo.Policy for the scaled values of cut_matrix.

Raises

  • FileNotFoundError (builtin) when output_dir is missing, or the policy directory (for a link, its target) is missing and neither <policy>.staging nor <policy>.previous holds a manifest.bin.
  • novomodelo.errors.OutputError (an OSError) when a checkpoint buffer cannot be read.
def load_stochastic(output_dir: Union[str, Path]) -> Stochastic: ...

Reads the fitted stochastic model from stochastic/inflow_ar_coefficients.parquet and stochastic/noise_openings.parquet; see Stochastic Artifacts. Those files exist only when the run had exports.stochastic enabled. Constructing the handle does not need NumPy.

Parameters

  • output_dir: the output directory.

Returns: a novomodelo.results.Stochastic handle.

Raises

  • FileNotFoundError (builtin) when output_dir or a required file is missing. Without the exports the message reads .../stochastic/inflow_ar_coefficients.parquet not found — stochastic artifacts are written only when exports.stochastic is enabled in config.json.
  • OSError (builtin) when a Parquet file cannot be decoded.
class Stochastic: ...

A read-only view of a run’s fitted stochastic model. The class has no Python constructor; novomodelo.results.Stochastic() raises TypeError. Obtain a handle from novomodelo.results.load_stochastic.

novomodelo.results.Stochastic.par_coefficients

Section titled “novomodelo.results.Stochastic.par_coefficients”
def par_coefficients(self) -> Any: ...

Returns the fitted PAR(p) coefficients, in the row order of stochastic/inflow_ar_coefficients.parquet.

Returns: a float64 NumPy array of shape (n_rows, 4) with the columns [hydro_id, stage_id, lag, coefficient]. The three integer columns are cast to float64, and lag is 1-based. The array has zero rows for a case with AR order 0, such as the 1dtoy case.

Raises

  • ImportError (builtin) when NumPy is not installed.

novomodelo.results.Stochastic.opening_tree

Section titled “novomodelo.results.Stochastic.opening_tree”
def opening_tree(self, stage: int) -> Any: ...

Returns the noise openings of one stage from stochastic/noise_openings.parquet. Row k is the noise vector of opening k.

Parameters

  • stage: the 0-based stage index.

Returns: a float64 NumPy array of shape (n_openings, dim), for example (10, 1) at any stage of the 1dtoy case.

Raises

  • IndexError (builtin) when the stage is absent from the file (stage 9 not present in the opening tree (valid stages are 0..=3)).
  • OverflowError (builtin) when stage is negative.
  • ImportError (builtin) when NumPy is not installed.

The classes in novomodelo.model are frozen, read-only views that novomodelo.io.load_case and novomodelo.Study.system return; a System cannot be constructed from Python, and assigning to a field raises AttributeError. Each entity list holds its items in canonical (operational_start_date, id) order, and the field meanings follow the case files, whose JSON Schemas are listed in JSON Schemas.

Each class reports __module__ as builtins; reach it as novomodelo.model.<Name>. Two reads of the same list can return different Python objects for the same entity, so compare entities by field values, not by identity (is).

The loaded system: entity counts and one list per entity class.

FieldTypeDescription
n_busesintThe number of buses.
n_hydrosintThe number of hydro plants.
n_linesintThe number of transmission lines.
n_stagesintThe number of stages, study and pre-study.
n_thermalsintThe number of thermal plants.
buseslist[Bus]The buses, in canonical order.
hydroslist[Hydro]The hydro plants, in canonical order.
lineslist[Line]The transmission lines, in canonical order. Empty when the case has none.
thermalslist[Thermal]The thermal plants, in canonical order.
contractslist[EnergyContract]The energy contracts, in canonical order. Empty when the case has none.
pumping_stationslist[PumpingStation]The pumping stations, in canonical order. Empty when the case has none.
non_controllable_sourceslist[NonControllableSource]The non-controllable sources, in canonical order. Empty when the case has none.
import novomodelo.io
system = novomodelo.io.load_case("case")
print(system.n_hydros)
print([h.name for h in system.hydros])
print(system.hydros[0].max_storage_hm3)
1
['UHE1']
1000.0

An electrical network node where energy balance is maintained.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
deficit_segmentslist[dict]The piecewise-linear deficit cost segments, one dict per segment with the keys depth_mw (float, or None for the final unbounded segment) and cost_per_mwh (float, $/MWh).
excess_costfloatThe cost of absorbing surplus generation, in $/MWh.

A transmission interconnection that carries power in both directions between two buses.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
source_bus_idintThe id of the bus at the source end.
target_bus_idintThe id of the bus at the target end.
direct_capacity_mwfloatThe maximum flow from source to target, in MW.
reverse_capacity_mwfloatThe maximum flow from target to source, in MW.
losses_percentfloatThe transmission losses as a percentage; 2.5 means 2.5%.
exchange_costfloatThe regularization cost per MWh exchanged, in $/MWh.

A thermal power plant with a scalar marginal cost.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
bus_idintThe id of the bus the plant feeds.
min_generation_mwfloatThe minimum electrical generation (minimum stable load), in MW.
max_generation_mwfloatThe maximum electrical generation (installed capacity), in MW.
cost_per_mwhfloatThe marginal cost of generation, in $/MWh.

A hydroelectric plant with reservoir storage. Plants form a cascade through downstream_id.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
downstream_idOptional[int]The id of the next hydro in the cascade. None for a plant with no downstream plant.
min_storage_hm3floatThe minimum operational storage (dead volume), in hm³.
max_storage_hm3floatThe maximum operational storage (flood control level), in hm³.
min_turbined_m3sfloatThe minimum turbined flow, in m³/s.
max_turbined_m3sfloatThe maximum turbined flow (installed turbine capacity), in m³/s.
productivity_mw_per_m3sOptional[float]Always None. The productivity is resolved per stage from the production-model files.

A bilateral energy contract with an external system.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
operational_start_datestrThe date the entity enters service, as an ISO 8601 YYYY-MM-DD string.
bus_idintThe id of the bus the contract connects to.
contract_typestrThe direction of energy flow: "import" or "export".
entry_stage_idOptional[int]The stage index at which the contract enters service. None when it is active from the first stage.
exit_stage_idOptional[int]The stage index at which the contract expires. None when it never expires.
price_per_mwhfloatThe contract price, in $/MWh. A negative value represents export revenue.
min_mwfloatThe minimum contracted power, in MW.
max_mwfloatThe maximum contracted power, in MW.

A pumping station that transfers water between hydro reservoirs.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
operational_start_datestrThe date the entity enters service, as an ISO 8601 YYYY-MM-DD string.
bus_idintThe id of the bus the station draws power from.
source_hydro_idintThe id of the hydro the pumped water is taken from.
destination_hydro_idintThe id of the hydro that receives the pumped water.
entry_stage_idOptional[int]The stage index at which the station enters service. None when it is active from the first stage.
exit_stage_idOptional[int]The stage index at which the station is decommissioned. None when it is never decommissioned.
consumption_mw_per_m3sfloatThe power consumption per unit of pumped flow, in MW/(m³/s).
min_flow_m3sfloatThe minimum pumped flow, in m³/s.
max_flow_m3sfloatThe maximum pumped flow (installed pump capacity), in m³/s.

An intermittent generation source that is not dispatched.

FieldTypeDescription
idintThe entity id from the case file.
namestrThe entity name from the case file.
operational_start_datestrThe date the entity enters service, as an ISO 8601 YYYY-MM-DD string.
bus_idintThe id of the bus the source feeds.
entry_stage_idOptional[int]The stage index at which the source enters service. None when it is active from the first stage.
exit_stage_idOptional[int]The stage index at which the source is decommissioned. None when it is never decommissioned.
max_generation_mwfloatThe maximum generation (installed capacity), in MW.
allow_curtailmentboolWhether the LP may curtail the source. False is the must-run regime.
curtailment_costfloatThe resolved cost of curtailed generation, in $/MWh. Unused when allow_curtailment is False.

Every leaf class subclasses novomodelo.errors.NovomodeloError and one builtin exception, and its __module__ is novomodelo.errors. NovomodeloError itself subclasses Exception directly and reports __module__ as errors. For the per-kind messages and exit codes, see Error Codes; for which policy-load path raises which class, see Policy-load errors.

class NovomodeloError(Exception): ...

The base class of every Novomodelo exception. Catch the typed class for one failure kind, the builtin base (ValueError, OSError, RuntimeError) to keep builtin-style handling, or NovomodeloError for all of them.

class ValidationError(NovomodeloError, ValueError): ...

Case data or configuration failed validation. Raised for an error of the invalid-input class, whatever its message prefix (a refused policy.path, a missing prior policy directory, and a checkpoint write refused for its manifest or a foreign entry included), and for message prefixes config override error, config parse error, config read error and setup validation error, and for parse, schema and constraint failures in the case data. It also covers a missing or unreadable case file.

class PolicyIncompatibleError(NovomodeloError, ValueError): ...

A policy is incompatible with the current system or build. Raised for an error of the incompatible-policy class: a warm-start, resume or simulation-only checkpoint refused for its software, version or a failed contract check, a boundary checkpoint refused for its software or version, a warm-start, resume or simulation-only checkpoint file that is missing or cannot be decoded, and an FCF construction failure.

class CaseIoError(NovomodeloError, OSError): ...

A filesystem read or write failure while loading or writing a case. Raised for message prefixes output write error and policy checkpoint error. It also covers a policy checkpoint read that the operating system refuses.

class OutputError(NovomodeloError, OSError): ...

An output serialization or schema failure, raised by novomodelo.write_policy_checkpoint, novomodelo.results.load_policy and a periodic checkpoint write during training. A not-found I/O error raises the builtin FileNotFoundError and other I/O errors raise CaseIoError. A manifest failure or a foreign entry raises ValidationError, not OutputError.

class SolverError(NovomodeloError, RuntimeError):
stage: int | None
iteration: int | None
scenario: int | None

A training or solver failure. An error of the solver or internal class raises SolverError, and so does a message whose prefix no other class claims; a simulation failure raises SimulationError. The three attributes are always present. For an infeasible subproblem they hold the integer coordinates of the infeasibility; for every other failure they are None.

FieldTypeDescription
stageint | NoneThe stage of the infeasible subproblem.
iterationint | NoneThe training iteration of the infeasible subproblem.
scenarioint | NoneThe scenario of the infeasible subproblem.
class SimulationError(NovomodeloError, RuntimeError): ...

A simulation-phase failure. Raised for the message prefix simulation error.

class InternalError(NovomodeloError, RuntimeError): ...

An internal software or environment fault, such as a worker-thread panic. Raised for the message prefix internal error.

Some failures raise a builtin exception that is not a NovomodeloError: a missing case directory (OSError), threads=0 and a malformed config_overrides mapping (ValueError), and a callback’s own exception.

import novomodelo
from novomodelo.errors import ValidationError
try:
novomodelo.Study("case", config_overrides={"trainning.enabled": False})
except ValidationError as err:
print(isinstance(err, ValueError))
print(err)
True
config override error: schema error in <config_overrides>, field trainning: unknown field `trainning`, expected one of `$schema`, `modeling`, `training`, `upper_bound_evaluation`, `policy`, `simulation`, `exports`, `estimation`
def export(output_dir: Union[str, Path] = ".") -> int: ...

Writes the JSON Schema file of every case-directory input type into output_dir, creating the directory if needed and overwriting existing files. For the schemas, see JSON Schemas.

Parameters

  • output_dir: the directory that receives the files. Defaults to the current directory.

Returns: the number of files written, as an int.

Raises

  • ValueError (builtin) when schema generation or serialisation fails.
  • OSError (builtin) when the directory cannot be created or a file cannot be written.
import novomodelo.schema
print(novomodelo.schema.export("schemas"))
18

The names in novomodelo._types are typing-only TypedDict classes for the dicts that novomodelo.run.run and the novomodelo.Study properties return; a type checker reads them from the package stubs. import novomodelo._types raises ModuleNotFoundError at runtime, and novomodelo.StochasticSummary, novomodelo.HydroModelsSummary, novomodelo.ProvenanceReport and novomodelo.System are likewise stub-only re-exports that are absent at runtime. Import the names under typing.TYPE_CHECKING and reach the runtime system class as novomodelo.model.System.

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from novomodelo._types import RunResult
def final_lower_bound(result: RunResult) -> float:
return result["lower_bound"]

StochasticSummary, HydroModelsSummary and ProvenanceReport are declared total=False; the dicts the package returns carry every key listed.

The dict novomodelo.run.run returns.

KeyTypeDescription
convergedboolTrue when the stopping rules ended training and a gap or bound_stalling rule triggered at that iteration. False for any other stopping reason and for a run without training.
iterationsintThe number of training iterations run. 0 when training did not run.
lower_boundfloatThe final lower bound, in currency units.
upper_boundOptional[float]The final upper bound, in currency units. None when it is not available.
gap_percentOptional[float]The relative optimality gap times 100. None when training did not run.
total_time_msintThe training time in milliseconds. 0 when training did not run.
output_dirstrThe output directory the run wrote to.
simulationOptional[SimulationSummary]The simulation summary. None when simulation did not run.
stochasticOptional[StochasticSummary]The same summary as novomodelo.Study.stochastic. novomodelo.run.run always sets it.
hydro_modelsOptional[HydroModelsSummary]The same summary as novomodelo.Study.hydro_models. novomodelo.run.run always sets it.
provenanceOptional[ProvenanceReport]The same summary as novomodelo.Study.provenance. novomodelo.run.run always sets it.

Every key is present on every branch. After training, upper_bound and gap_percent are set. On a simulation-only run (training disabled, simulation enabled), iterations is 0, gap_percent is None, and upper_bound is the loaded checkpoint’s recorded upper bound (the last training iteration’s value) when it is finite, otherwise None. With both phases disabled, lower_bound is 0.0 and upper_bound, gap_percent and simulation are None.

The six training headline keys that RunResult carries at its top level. No function returns a TrainingSummary; use it to annotate those keys in isolation.

KeyTypeDescription
convergedboolTrue when the stopping rules ended training and a gap or bound_stalling rule triggered at that iteration. False for any other stopping reason and for a run without training.
iterationsintThe number of training iterations run. 0 when training did not run.
lower_boundfloatThe final lower bound, in currency units.
upper_boundOptional[float]The final upper bound, in currency units. None when it is not available.
gap_percentOptional[float]The relative optimality gap times 100. None when training did not run.
total_time_msintThe training time in milliseconds. 0 when training did not run.

The dict under RunResult["simulation"], and the return value of novomodelo.Study.simulate.

KeyTypeDescription
n_scenariosintThe number of simulation scenarios.
completedintThe number of scenarios that completed.

The dict novomodelo.Study.stochastic returns.

KeyTypeDescription
inflow_sourceOptional[str]The source of the inflow seasonal statistics: one of "estimated" (computed from the historical records), "loaded" (read from the case files) or None (the component is not modelled).
n_hydrosintThe number of hydro plants.
n_seasonsintThe number of seasons in the PAR model.
ar_orderOptional[dict]The autoregressive (AR) order summary; None when the system has no hydros. The dict has the keys method (str, the order-selection method: "PACF" or "PACF_ANNUAL" for the estimation.order_selection that ran, or "fixed" when the orders come from the case files), min_order and max_order (int), n_hydros (int) and order_counts (list[int], the number of hydros at each order, indexed by order).
correlation_sourceOptional[str]The source of the correlation data: one of "estimated" (computed from the historical records), "loaded" (read from the case files) or None (the component is not modelled).
correlation_dimOptional[str]The dimension of the correlation matrix as a string, for example "1x1". None when there is no correlation matrix.
opening_tree_sourceOptional[str]The source of the opening tree: one of "estimated" (computed from the historical records), "loaded" (read from the case files) or None (the component is not modelled).
openings_per_stagelist[int]The number of openings at each stage.
n_stagesintThe number of stages in the stochastic context.
n_load_busesintThe number of buses with stochastic load noise.
seedintThe random seed used for noise generation.

The dict novomodelo.Study.hydro_models returns.

KeyTypeDescription
n_constantintThe number of hydros that use a constant productivity.
n_fphaintThe number of hydros that use the FPHA production model.
total_planesintThe total number of hyperplanes across all FPHA hydros.
n_evaporationintThe number of hydros with linearized evaporation.
n_no_evaporationintThe number of hydros with no evaporation model.

The dict novomodelo.Study.provenance returns.

KeyTypeDescription
estimation_pathstrThe estimation path taken, one of "deterministic", "user_stats_white_noise", "user_provided_no_history", "full_estimation", "user_ar_history_stats", "partial_estimation" or "user_provided_all".
seasonal_stats_sourcestrThe origin of the seasonal mean and standard deviation: one of "estimated" (computed from the inflow history), "user_file" (read from a case file) or "n/a" (not applicable).
ar_coefficients_sourcestrThe origin of the AR coefficients: one of "estimated" (computed from the inflow history), "user_file" (read from a case file) or "n/a" (not applicable).
correlation_sourcestrThe origin of the spatial correlation: one of "estimated" (computed from the inflow history), "user_file" (read from a case file) or "n/a" (not applicable).
opening_tree_sourcestrThe origin of the noise opening tree: one of "estimated" (computed from the inflow history), "user_file" (read from a case file) or "n/a" (not applicable).
n_hydrosintThe number of hydro plants.
ar_methodOptional[str]The order-selection method used when the AR coefficients were estimated: "PACF" or "PACF_ANNUAL". None when they were not estimated.
ar_max_orderOptional[int]The maximum AR order across all hydros when the AR coefficients were estimated. None otherwise.
white_noise_fallbackslist[int]The ids of the hydros that fell back to white noise. Empty unless the path is "partial_estimation".
hydro_productiondictThe hydro-production source counts. The dict has the integer keys n_fpha_computed_from_geometry, n_fpha_precomputed_hyperplanes, n_evaporation_ref_user_supplied and n_evaporation_ref_default_midpoint.