Skip to content

API Reference

vizopt.base

Base classes

Callback = Callable[[int, Array, Any, Any], None] module-attribute

InputParams = TypeVar('InputParams') module-attribute

OptimVars = TypeVar('OptimVars') module-attribute

ObjectiveTerm dataclass

A term in an objective function.

Attributes:

Name Type Description
name str

A name for the term, e.g. "total distance".

compute Callable[[Any, Any], Array]

A function that computes the value of the term with arguments optim_vars, input_parameters

multiplier float

A multiplicative factor for the term.

schedule Callable[[Array], Array] | None

Optional JAX-compatible callable (step: Array) -> Array that returns a scalar multiplier for the given iteration step. The effective weight is multiplier * schedule(step). Must use JAX ops (e.g. jnp.minimum, jnp.where) so that it can be traced through without recompilation. None means constant 1.0 (no scheduling).

OptimConfig dataclass

Configuration for the gradient-descent optimizer.

Attributes:

Name Type Description
n_iters int

Number of optimization iterations.

learning_rate float

Step size for the Adam optimizer.

b1 float

Adam exponential decay rate for the first moment. Default 0.9.

b2 float

Adam exponential decay rate for the second moment. Default 0.999.

n_restarts int

Number of random restarts. The run with the lowest final loss is returned. Default 1 (single run).

seed int

Base random seed passed to initialize. Restart i receives seed + i.

track_every int

Record per-term history every this many iterations.

OptimizationProblem dataclass

Bases: Generic[InputParams, OptimVars]

An optimization problem.

Attributes:

Name Type Description
input_parameters InputParams

Fixed data for the problem (not optimized).

terms list[ObjectiveTerm]

Objective terms defining the loss function.

initialize Callable[[InputParams, int], OptimVars]

Callable that produces initial optimization variables from input_parameters.

plot_configuration Callable[[OptimVars, InputParams], None] | None

Optional callable to visualize a configuration. Signature: plot_configuration(optim_vars, input_parameters).

svg_configuration Callable[[list, InputParams, int], list[dict]] | None

Optional callable to produce SVG element specs for animation. Signature: svg_configuration(snapshots, input_parameters, size) -> list[dict].

var_scales dict | None

Optional per-variable scale factors. See :func:build_objective for details.

optimize(optim_config=None, callback=None)

Run gradient descent to minimize the objective.

When optim_config.n_restarts > 1, the optimization is run that many times with seeds seed, seed + 1, …. The result with the lowest final loss is returned.

Parameters:

Name Type Description Default
optim_config OptimConfig | None

Optimizer settings (iterations, learning rate, seeds, restarts, track_every). Uses OptimConfig defaults when None.

None
callback Callback | None

Optional callback called after each iteration with (iteration, loss, optim_vars, grads).

None

Returns:

Type Description
OptimizationResult[OptimVars]

An OptimizationResult with the

OptimizationResult[OptimVars]

optimized variables, per-term history, and final loss of the best run.

plot(**kwargs)

Plot the last optimization result using plot_configuration.

Keyword arguments are forwarded to plot_configuration, allowing optional display flags (e.g. show_arrows=True).

Raises:

Type Description
ValueError

If plot_configuration is not set or optimize() has not been called yet.

OptimizationProblemTemplate dataclass

Bases: Generic[InputParams, OptimVars]

A template for a class of optimization problems.

An instance represents a specific type of optimization problem (e.g. bubble layout optimization), independently of any particular input data. Call :meth:instantiate with concrete input parameters to obtain a runnable :class:OptimizationProblem.

If input_params_class is provided, it must be a Pydantic model class. instantiate will call model_validate on the supplied parameters, triggering Pydantic validation and coercion before the problem is created.

Attributes:

Name Type Description
terms list[ObjectiveTerm]

Objective terms defining the loss function.

initialize Callable[[InputParams, int], OptimVars]

Callable that produces initial optimization variables from input_parameters.

input_params_class type[InputParams] | None

Optional Pydantic model class for input parameters. When set, validation is performed at instantiation time.

plot_configuration Callable[[OptimVars, InputParams], None] | None

Optional callable to visualize a configuration. Signature: plot_configuration(optim_vars, input_parameters).

svg_configuration Callable[[list, InputParams, int], list[dict]] | None

Optional callable to produce SVG element specs for animation. Signature: svg_configuration(snapshots, input_parameters, size) -> list[dict] where each dict has a "tag" key and SVG attribute keys; list values are animated per-frame, scalar values are static.

instantiate(input_parameters, weight_overrides=None, var_scales=None)

Create a runnable problem instance from concrete input parameters.

If input_params_class is set, validates input_parameters via model_validate before creating the problem. The plain dict is passed through to the problem unchanged (Pydantic is used for validation only, so that input_parameters remains a JAX-compatible pytree).

Parameters:

Name Type Description Default
input_parameters InputParams

Fixed data for this problem instance.

required
weight_overrides dict[str, float] | None

Optional mapping of term name to multiplier. Overrides the default multiplier for the named terms. Unknown names raise KeyError.

None
var_scales dict | None

Optional per-variable scale factors used to normalise optim_vars during optimisation. See :func:build_objective for details. Values may be scalars or arrays.

None

Returns:

Name Type Description
An OptimizationProblem[InputParams, OptimVars]

class:OptimizationProblem ready to optimize.

Raises:

Type Description
KeyError

If a name in weight_overrides does not match any term.

ValidationError

If input_params_class is set and validation fails.

OptimizationResult dataclass

Bases: Generic[OptimVars]

Result returned by OptimizationProblem.optimize.

Attributes:

Name Type Description
optim_vars OptimVars

Optimized variables in physical (un-scaled) space.

history list[dict]

Per-iteration records. Each dict has keys "iteration", "total", one key per term name (schedule-weighted value), one per term name suffixed _unscheduled (end-weighted), and one per term name suffixed _unweighted (raw, un-multiplied value).

final_loss float

Scalar loss of the best run at the last iteration.

VizOptimizer

Bases: ABC

Base class for user-facing visualization optimizers.

Subclasses implement :meth:_build_problem to turn stored hyperparameters into a configured :class:OptimizationProblem. The base class handles the optimize → plot lifecycle and stores fitted state in problem_ and result_ after :meth:optimize is called.

animate(callback, **kwargs)

Create a matplotlib animation of the optimization progress.

Convenience wrapper around :func:~vizopt.animation.animate that renders each snapshot via this optimizer's plot_configuration. To save as a GIF, call .save(path, writer="pillow", fps=...) on the returned animation.

Parameters:

Name Type Description Default
callback

A :class:~vizopt.animation.SnapshotCallback passed to :meth:optimize, or a raw list of (iteration, optim_vars) tuples.

required
**kwargs

Forwarded to :func:~vizopt.animation.animate.

{}

Returns:

Type Description
Any

A matplotlib.animation.FuncAnimation.

Raises:

Type Description
ValueError

If :meth:optimize has not been called yet.

animate_svg(callback, **kwargs)

Create an animated SVG from a SnapshotCallback.

Convenience wrapper around :func:~vizopt.animation.snapshots_to_animated_svg that uses this optimizer's built problem and defaults history to the result from the last :meth:optimize call.

Parameters:

Name Type Description Default
callback

A :class:~vizopt.animation.SnapshotCallback passed to :meth:optimize, or a raw list of (iteration, optim_vars) tuples.

required
**kwargs

Forwarded to :func:~vizopt.animation.snapshots_to_animated_svg. history defaults to self.result_.history.

{}

Returns:

Type Description
str

An SVG string suitable for saving or displaying with

str

IPython.display.SVG.

Raises:

Type Description
ValueError

If :meth:optimize has not been called yet.

optimize(optim_config=None, callback=None)

Build the problem and run gradient descent.

Parameters:

Name Type Description Default
optim_config OptimConfig | None

Optimizer settings. Uses :class:OptimConfig defaults when None.

None
callback Callback | None

Optional callback (iteration, loss, optim_vars, grads).

None

Returns:

Name Type Description
An OptimizationResult

class:OptimizationResult with optimized variables, per-term

OptimizationResult

history, and final loss.

plot(**kwargs)

Plot the last optimization result.

Raises:

Type Description
ValueError

If :meth:optimize has not been called yet.

build_objective(terms, input_parameters, var_scales=None)

Build a composite objective function from a list of terms.

Parameters:

Name Type Description Default
terms list[ObjectiveTerm]

Objective terms to sum, each weighted by its multiplier.

required
input_parameters Any

Fixed data passed to each term's compute function.

required
var_scales dict | None

Optional per-variable scale factors. When provided, each optim_vars[k] is multiplied by var_scales[k] before being passed to any term's compute function, so the optimizer works in a normalised space while loss terms always receive physical values. Values may be scalars or arrays (broadcast over the variable's shape). Keys absent from var_scales are left unscaled.

None

Returns:

Type Description
Callable[[OptimVars, Array], Array]

A callable fun(optim_vars, step) -> scalar suitable for gradient

Callable[[OptimVars, Array], Array]

descent. step is the current iteration as a JAX int32 array and

Callable[[OptimVars, Array], Array]

is passed to each term's schedule (if any).

default_print_callback(i_iter, loss_value, *_)

Print the loss value after every nth optimization iteration


vizopt.animation

Animation utilities for visualizing optimization progress.

OptimizationProblem dataclass

Bases: Generic[InputParams, OptimVars]

An optimization problem.

Attributes:

Name Type Description
input_parameters InputParams

Fixed data for the problem (not optimized).

terms list[ObjectiveTerm]

Objective terms defining the loss function.

initialize Callable[[InputParams, int], OptimVars]

Callable that produces initial optimization variables from input_parameters.

plot_configuration Callable[[OptimVars, InputParams], None] | None

Optional callable to visualize a configuration. Signature: plot_configuration(optim_vars, input_parameters).

svg_configuration Callable[[list, InputParams, int], list[dict]] | None

Optional callable to produce SVG element specs for animation. Signature: svg_configuration(snapshots, input_parameters, size) -> list[dict].

var_scales dict | None

Optional per-variable scale factors. See :func:build_objective for details.

optimize(optim_config=None, callback=None)

Run gradient descent to minimize the objective.

When optim_config.n_restarts > 1, the optimization is run that many times with seeds seed, seed + 1, …. The result with the lowest final loss is returned.

Parameters:

Name Type Description Default
optim_config OptimConfig | None

Optimizer settings (iterations, learning rate, seeds, restarts, track_every). Uses OptimConfig defaults when None.

None
callback Callback | None

Optional callback called after each iteration with (iteration, loss, optim_vars, grads).

None

Returns:

Type Description
OptimizationResult[OptimVars]

An OptimizationResult with the

OptimizationResult[OptimVars]

optimized variables, per-term history, and final loss of the best run.

plot(**kwargs)

Plot the last optimization result using plot_configuration.

Keyword arguments are forwarded to plot_configuration, allowing optional display flags (e.g. show_arrows=True).

Raises:

Type Description
ValueError

If plot_configuration is not set or optimize() has not been called yet.

SnapshotCallback

Callback that saves a numpy copy of optim_vars at regular intervals.

Pass an instance as the callback argument to :meth:OptimizationProblem.optimize. Snapshots accumulate in :attr:snapshots and can be passed to :func:animate.

Parameters:

Name Type Description Default
every int

Save a snapshot every this many iterations.

10

Attributes:

Name Type Description
snapshots list[tuple[int, Any]]

List of (iteration, optim_vars) tuples, one per recorded step.

Example::

cb = SnapshotCallback(every=100)
result = problem.optimize(n_iters=2000, callback=cb)
anim = animate(problem, cb.snapshots)

_loss_curve_svg_lines(history, snapshots, size, panel_height, n_frames, total_dur, calc_mode, log_scale=False)

Build SVG lines for a loss curve panel placed below the main animation.

Parameters:

Name Type Description Default
history list[dict]

List of history dicts with "iteration" and "total" keys.

required
snapshots list[tuple[int, Any]]

List of (iteration, optim_vars) tuples.

required
size int

Width of the SVG (same as the animation width).

required
panel_height int

Height of the loss curve panel in pixels.

required
n_frames int

Number of animation frames.

required
total_dur float

Total animation duration in seconds.

required
calc_mode str

SMIL calcMode ("linear" or "discrete").

required
log_scale bool

If True, the loss axis uses a log10 scale.

False

Returns:

Type Description
list[str]

A list of SVG element strings to append before the closing </svg>.

_optim_vars_spaghetti_svg_lines(snapshots, panel_y, size, panel_height, n_frames, total_dur, calc_mode)

Build SVG lines for a spaghetti-plot panel of optimization variables.

Each scalar component of optim_vars becomes one polyline traced across all snapshot iterations. Variables that share the same pytree leaf are drawn in the same colour. An animated vertical marker tracks the current animation frame, consistent with the loss curve panel.

Parameters:

Name Type Description Default
snapshots list[tuple[int, Any]]

List of (iteration, optim_vars) tuples.

required
panel_y int

Y-offset of this panel inside the SVG.

required
size int

Width of the SVG (same as the animation width).

required
panel_height int

Height of this panel in pixels.

required
n_frames int

Number of animation frames.

required
total_dur float

Total animation duration in seconds.

required
calc_mode str

SMIL calcMode ("linear" or "discrete").

required

Returns:

Type Description
list[str]

A list of SVG element strings to append before the closing </svg>.

animate(problem, snapshots, interval=200)

Create an animation of the optimization process.

Renders each optim_vars snapshot via problem.plot_configuration and assembles the frames into a FuncAnimation.

Parameters:

Name Type Description Default
problem OptimizationProblem

The optimization problem; must have plot_configuration set.

required
snapshots list[tuple[int, Any]]

List of (iteration, optim_vars) tuples as produced by :class:SnapshotCallback.

required
interval int

Delay between frames in milliseconds.

200

Returns:

Type Description
Any

A matplotlib.animation.FuncAnimation. In a Jupyter notebook,

Any

display with IPython.display.HTML(anim.to_jshtml()).

Raises:

Type Description
ValueError

If problem.plot_configuration is not set or snapshots is empty.

chronophotograph(problem, snapshots, n_frames=8, alpha_start=0.15, alpha_end=1.0)

Create a static chronophotography composite of the optimization process.

Renders a selection of evenly-spaced snapshots and overlays them into a single static figure. Earlier frames are faint ghosts; the latest frame is fully opaque, so the eye reads the trajectory at a glance.

Parameters:

Name Type Description Default
problem OptimizationProblem

The optimization problem; must have plot_configuration set.

required
snapshots list[tuple[int, Any]]

List of (iteration, optim_vars) tuples as produced by :class:SnapshotCallback.

required
n_frames int

Number of evenly-spaced frames to overlay. Clamped to len(snapshots).

8
alpha_start float

Blend weight of the earliest selected frame (0–1).

0.15
alpha_end float

Blend weight of the latest selected frame (0–1).

1.0

Returns:

Type Description
Any

A matplotlib Figure containing the composite image.

Raises:

Type Description
ValueError

If problem.plot_configuration is not set or snapshots is empty.

default_print_callback(i_iter, loss_value, *_)

Print the loss value after every nth optimization iteration

smil_animate(attr_name, per_frame_values, n_frames, total_dur, calc_mode='linear')

Build a SMIL <animate> element string for a numeric SVG attribute.

Parameters:

Name Type Description Default
attr_name str

SVG attribute to animate (e.g. "cx", "opacity").

required
per_frame_values list[str]

Stringified values, one per frame.

required
n_frames int

Total number of frames, used to space keyTimes evenly.

required
total_dur float

Animation duration in seconds.

required
calc_mode str

"linear" or "discrete". Linear appends the first value at keyTime 1.0 to close the loop smoothly.

'linear'

Returns:

Type Description
str

An SVG <animate> element string.

snapshots_to_animated_svg(problem, snapshots, fps=10, size=500, calc_mode='linear', history=None, loss_curve_height=120, log_scale=False, optim_vars_panel_height=0, margin=None)

Create an animated SVG from optimization snapshots.

Uses problem.svg_configuration to obtain per-element SVG specs, then builds SMIL <animate> elements for attributes that vary across frames.

Parameters:

Name Type Description Default
problem OptimizationProblem

The optimization problem; must have svg_configuration set.

required
snapshots list[tuple[int, Any]]

List of (iteration, optim_vars) tuples as produced by :class:SnapshotCallback.

required
fps int

Frames per second.

10
size int

Width and height of the output SVG in pixels.

500
calc_mode str

"linear" for smooth interpolation or "discrete" for instant jumps between frames.

'linear'
history list[dict] | None

Optional list of history dicts as returned by :meth:OptimizationProblem.optimize (each dict has an "iteration" key and a "total" key with the aggregate loss). When provided, a loss curve is rendered below the animation with an animated marker tracking the current frame.

None
loss_curve_height int

Height in pixels of the loss curve panel, used only when history is provided.

120
log_scale bool

If True, the loss axis uses a log10 scale.

False
optim_vars_panel_height int

Height in pixels of the spaghetti-plot panel for optimization variables. When greater than zero, a panel is appended below the animation (and below the loss curve, if shown) with one polyline per scalar optimization variable, so you can see all variable trajectories across iterations at a glance. An animated vertical marker tracks the current frame, matching the style of the loss curve panel.

0
margin float | None

Empty border around the content, as a fraction of the content's span. Only forwarded to problem.svg_configuration if that function accepts a margin keyword (e.g. one built by StarRepresentation.make_svg_configuration); left at None (the underlying function's own default) otherwise.

None

Returns:

Type Description
str

An SVG string. Save with Path("out.svg").write_text(svg) or

str

display in Jupyter with IPython.display.SVG(data=svg).

Raises:

Type Description
ValueError

If problem.svg_configuration is not set, snapshots is empty, or margin is given but problem.svg_configuration does not accept a margin keyword.


vizopt.components.common

calculate_collision_penalty(node_xys, node_radii, collision_pairs, offset=1.0)

Vectorized collision penalty for node pairs that should not overlap.

Parameters:

Name Type Description Default
node_xys

Array of node positions with shape (n, 2).

required
node_radii

Array of node radii with shape (n,).

required
collision_pairs

Integer array of shape (k, 2) with index pairs to check.

required
offset

Minimum required gap between circle boundaries.

1.0

Returns:

Type Description

Scalar penalty value.

calculate_total_width_penalty_for_circular_layout(node_xys, node_radii)

A penalty for the overall width and height of the drawing with circular nodes.

Parameters:

Name Type Description Default
node_xys ndarray

Array of node positions with shape (n, 2).

required
node_radii ndarray

Array of node radii with shape (n,).

required

calculate_total_width_penalty_ignoring_radii(node_xys)

A penalty for the overall width and height of the drawing.

Parameters:

Name Type Description Default
node_xys ndarray

Array of node positions with shape (n, 2).

required

multiple_bbox_intersections(bbox_matrix, other_bbox_matrix)

Calculate the pairwise intersections of two sets of bounding boxes

This vectorized implementation is more efficient than the avoided double for loop

Parameters:

Name Type Description Default
bbox_matrix ArrayLike

array of shape (n, 2, 2) dimensions: points, min and max, xy coordinates

required
other_bbox_matrix ArrayLike

array of shape (m, 2, 2) dimensions: points, min and max, xy coordinates

required

Returns:

Type Description

array of shape (n, m)

should_be_positive_activation(x_value, factor=100.0)

A penalty for negative values.


vizopt.schedules

Schedule factory functions for loss term weight scheduling.

Schedules are JAX-compatible callables (step: Array) -> Array that scale a term's effective weight over the course of optimization. They must use JAX ops (e.g. jnp.clip) so they can be traced through without recompilation.

TermSchedules dataclass

Per-term weight schedules with warmup/cooldown categorization.

Attributes:

Name Type Description
schedules dict

Dict mapping term name to a JAX-compatible schedule callable, ready to pass as term_schedules to any optimizer.

quality_terms set

Term names whose schedules end at 1 (warmup). Use these when computing a quality score from the final loss history.

relaxation_terms set

Term names whose schedules end at 0 (cooldown). These are expected to fade out and should be excluded from quality scoring.

cooldown(peak_frac, ramp_frac, n_iters)

Linear cooldown: ramps from 1.0 down to 0.01 over a window of the run.

Parameters:

Name Type Description Default
peak_frac float

Fraction of n_iters at which the weight is still 1.0.

required
ramp_frac float

Fraction of n_iters over which to ramp down.

required
n_iters int

Total number of optimization iterations.

required

Returns:

Type Description

JAX-compatible callable (step: Array) -> Array.

make_term_schedules(params, n_iters)

Build a :class:TermSchedules from a flat parameter dict.

Term names and schedule types are inferred from param key suffixes:

  • {term}_delay + {term}_ramp → :func:warmup for term
  • {term}_peak + {term}_ramp → :func:cooldown for term

Parameters:

Name Type Description Default
params dict

Flat dict whose keys follow the naming convention above. All values are fractions of n_iters in [0, 1].

required
n_iters int

Total number of optimization iterations. Schedules scale automatically — the same params work for any run length.

required

Returns:

Type Description
TermSchedules

class:TermSchedules with schedules, quality_terms, and

TermSchedules

relaxation_terms populated from params.

warmup(delay_frac, ramp_frac, n_iters)

Linear warmup: ramps from 0.01 to 1.0 over a window of the run.

Parameters:

Name Type Description Default
delay_frac float

Fraction of n_iters before ramping starts.

required
ramp_frac float

Fraction of n_iters over which to ramp up.

required
n_iters int

Total number of optimization iterations.

required

Returns:

Type Description

JAX-compatible callable (step: Array) -> Array.