Open the original notebook on GitHub
Powerfit reports and record exports
This notebook focuses on the plain-record and nested-report helpers around low-level fits, realized-pair matching, and the self-consistent active-set solver.
import numpy as np
import pyvoro2 as pv
import pyvoro2.inverse as inverse
import pyvoro2.inverse.separator as separator
1) Resolve a small candidate set
We use explicit integer ids so that exported rows already carry the labels that downstream code wants to show.
points = np.array(
[
[0.0, 0.0, 0.0],
[2.0, 0.0, 0.0],
[4.0, 0.0, 0.0],
],
dtype=float,
)
ids = np.array([100, 101, 102], dtype=int)
box = pv.Box(((-1.0, 5.0), (-2.0, 2.0), (-2.0, 2.0)))
observations = inverse.resolve_separator_observations(
points,
[(0, 1, 0.35), (1, 2, 0.55), (0, 2, 0.50)],
measurement="fraction",
domain=box,
ids=ids,
)
observations.to_records(use_ids=True)
({'constraint_index': 0,
'site_i': 100,
'site_j': 101,
'shift': (0, 0, 0),
'target': 0.35,
'confidence': 1.0,
'measurement': 'fraction',
'distance': 2.0,
'target_fraction': 0.35,
'target_position': 0.7,
'input_index': 0,
'explicit_shift': False},
{'constraint_index': 1,
'site_i': 101,
'site_j': 102,
'shift': (0, 0, 0),
'target': 0.55,
'confidence': 1.0,
'measurement': 'fraction',
'distance': 2.0,
'target_fraction': 0.55,
'target_position': 1.1,
'input_index': 1,
'explicit_shift': False},
{'constraint_index': 2,
'site_i': 100,
'site_j': 102,
'shift': (0, 0, 0),
'target': 0.5,
'confidence': 1.0,
'measurement': 'fraction',
'distance': 4.0,
'target_fraction': 0.5,
'target_position': 2.0,
'input_index': 2,
'explicit_shift': False})
2) Fit power weights and export low-level reports
model = separator.FitModel(
mismatch=separator.SquaredLoss(),
feasible=separator.Interval(0.0, 1.0),
penalties=(
separator.ExponentialBoundaryPenalty(
lower=0.0,
upper=1.0,
margin=0.05,
strength=0.2,
tau=0.02,
),
),
)
fit = inverse.fit_weights_from_separators(
points,
observations,
model=model,
)
fit_rows = fit.to_records(observations, use_ids=True)
fit_report = fit.to_report(observations, use_ids=True)
fit_report["summary"]
fit_report["weight_shift"]
0.0
3) Check realized pairs against the actual power tessellation
realized = separator.match_realized_pairs(
points,
domain=box,
weights=fit.state.mathematical_weights,
constraints=observations,
return_boundary_measure=True,
return_tessellation_diagnostics=True,
)
realized_rows = realized.to_records(observations, use_ids=True)
realized_report = realized.to_report(observations, use_ids=True)
realized_report["summary"]
{'n_constraints': 3,
'n_realized': 2,
'n_same_shift': 2,
'n_other_shift': 0,
'n_unrealized': 1,
'n_unaccounted_pairs': 0}
4) Run the self-consistent active-set solver
Final-state vs optimization-path reports
solve_report["connectivity"] and solve_report["realized"] describe the final returned solution. solve_report["path_summary"] and the optional history rows capture transient disconnectivity or candidate-absent realized pairs that occurred during the outer iterations.
result = separator.solve_self_consistent_power_weights(
points,
observations,
domain=box,
model=model,
options=separator.ActiveSetOptions(
add_after=1,
drop_after=2,
relax=0.5,
max_iter=12,
cycle_window=6,
),
return_history=True,
return_boundary_measure=True,
return_tessellation_diagnostics=True,
)
result_rows = result.to_records(use_ids=True)
solve_report = result.to_report(use_ids=True)
solve_report["summary"]
solve_report["path_summary"]
{'n_iterations': 12,
'ever_fit_active_graph_disconnected': False,
'ever_fit_active_effective_graph_disconnected': False,
'ever_fit_active_offsets_unidentified_by_data': False,
'ever_unaccounted_pairs': False,
'max_fit_active_graph_components': 1,
'max_fit_active_effective_graph_components': 1,
'max_n_unaccounted_pairs': 0,
'first_fit_active_graph_disconnected_iter': None,
'first_fit_active_effective_graph_disconnected_iter': None,
'first_unaccounted_pairs_iter': None}
5) Serialize the report bundle
text = separator.dumps_report_json(solve_report, sort_keys=True)
text[:200]
'{\n "connectivity": {\n "active_effective_graph": {\n "connected_components": [\n [\n 100,\n 101,\n 102\n ]\n ],\n "fully_connected": true,\n "iso'