pylinkage.population package
Module contents
Population abstractions for working with collections of mechanisms.
Member: A single mechanism variant (dimensions + scores + trajectory).Ensemble: N parameter variants of one topology (fast batch simulation).Population: Heterogeneous collection of mechanisms (different topologies).
- class pylinkage.population.Ensemble(linkage: Linkage, dimensions: NDArray[np.float64], initial_positions: NDArray[np.float64], scores: dict[str, NDArray[np.float64]] | None = None)
Bases:
objectN parameter variants of one linkage topology.
All members share the same SolverData structure (joint_types, parent_indices, constraint_offsets, solve_order). Only constraints and initial_positions vary per member.
Supports vectorized batch simulation via numba.
Integer indexing returns a
Member; slice or array indexing returns a newEnsemble(numpy convention).- Parameters:
linkage – Template Linkage defining the topology. Used to compile the shared SolverData; not mutated.
dimensions – Constraint vectors, shape
(n_members, n_constraints).initial_positions – Joint positions, shape
(n_members, n_joints, 2).scores – Named score arrays, each of shape
(n_members,). Stored columnar for efficient ranking/filtering.
- property dimensions: ndarray[tuple[Any, ...], dtype[float64]]
Constraint vectors, shape (n_members, n_constraints).
- filter(predicate: Callable[[Member], bool]) Ensemble
Return a new Ensemble with members matching predicate.
- filter_by_score(name: str = 'score', *, min_val: float = -inf, max_val: float = inf) Ensemble
Return a new Ensemble with members whose score is in range.
- classmethod from_agents(linkage: Linkage, agents: list[Agent]) Ensemble
Create an Ensemble from a legacy optimization result.
- Parameters:
linkage – The linkage that was optimized.
agents – Results from PSO, grid search, etc.
- classmethod from_pareto_front(linkage: Linkage, front: ParetoFront) Ensemble
Create an Ensemble from a multi-objective Pareto front.
- Parameters:
linkage – The linkage that was optimized.
front – Pareto front result.
- property initial_positions: ndarray[tuple[Any, ...], dtype[float64]]
Initial positions, shape (n_members, n_joints, 2).
- property linkage: Linkage
Template linkage defining the shared topology.
- property n_constraints: int
Number of constraints per member.
- property n_joints: int
Number of joints in the shared topology.
- property n_members: int
Number of parameter variants.
- plot_plotly(idx: int = 0, iterations: int | None = None, **kwargs: Any) object
Plot a member with
plot_linkage_plotly().Simulates the member if no trajectory is cached.
- Parameters:
idx – Member index to visualize.
iterations – Simulation steps (if trajectory not yet computed).
**kwargs – Forwarded to
plot_linkage_plotly().
- Returns:
A plotly Figure object.
- rank(key: str = 'score', *, ascending: bool = True) Ensemble
Return a new Ensemble sorted by key.
- save_svg(path: str, idx: int = 0, iterations: int | None = None, **kwargs: Any) None
Save a member as SVG via
save_linkage_svg().Simulates the member if no trajectory is cached.
- Parameters:
path – Output file path.
idx – Member index to visualize.
iterations – Simulation steps (if trajectory not yet computed).
**kwargs – Forwarded to
save_linkage_svg().
- property scores: dict[str, ndarray[tuple[Any, ...], dtype[float64]]]
Named score arrays, each of shape (n_members,).
- show(idx: int = 0, iterations: int | None = None, **kwargs: Any) object
Animate a member with
show_linkage().Simulates the member if no trajectory is cached.
- Parameters:
idx – Member index to visualize.
iterations – Simulation steps (if trajectory not yet computed).
**kwargs – Forwarded to
show_linkage().
- Returns:
The matplotlib FuncAnimation object.
- simulate(iterations: int | None = None, dt: float = 1.0, *, store: bool = True) ndarray[tuple[Any, ...], dtype[float64]]
Batch-simulate all members.
- Parameters:
iterations – Steps per member. If None, uses the linkage’s rotation period.
dt – Time step for crank rotation.
store – If True, cache trajectories so they are available on individual Members and via
trajectories.
- Returns:
Array of shape
(n_members, iterations, n_joints, 2).
- simulate_member(idx: int, iterations: int | None = None, dt: float = 1.0) ndarray[tuple[Any, ...], dtype[float64]]
Simulate a single member (lazy per-member access).
The result is cached in
_trajectoriesif the full batch has already been computed; otherwise a one-off simulation is run and the result is returned (not cached in the batch array).
- property template: SolverData
Shared solver data for the topology, compiled on first access.
- Raises:
NotImplementedError – If the numba solver cannot represent the linkage. Such an Ensemble still holds its members and scores; only batch simulation is unavailable.
- to_agents() list[Agent]
Convert all members back to legacy Agents.
- to_pareto_front() ParetoFront
Members as a
ParetoFront.Every score column becomes one objective, in insertion order, so the front carries the
objective_namesgiven tomulti_objective_optimization(). Use it for the front’s own tools:best_compromise(),filter(),hypervolume()andplot().
- top(n: int, key: str = 'score', *, ascending: bool = True) Ensemble
Return the top n members by key.
- property topology_key: tuple[tuple[int, ...], tuple[tuple[int, ...], ...], tuple[int, ...]]
Hashable topology identity for grouping.
Two linkages with the same topology_key are structurally identical and can be merged into one Ensemble.
- property trajectories: ndarray[tuple[Any, ...], dtype[float64]] | None
Cached trajectories, shape (n_members, iterations, n_joints, 2).
- class pylinkage.population.Member(dimensions: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]], initial_positions: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]], scores: dict[str, float] = <factory>, trajectory: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | None = None, metadata: dict[str, ~typing.Any] = <factory>)
Bases:
objectOne mechanism variant in a population.
Universal record type for a single mechanism, replacing the various result types (Agent, ParetoSolution) with a unified representation.
- Variables:
dimensions (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Flat constraint vector, shape (n_constraints,).
initial_positions (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]]) – Joint positions, shape (n_joints, 2).
scores (dict[str, float]) – Named scores (e.g. {“stride”: 4.2, “smoothness”: 0.8}).
trajectory (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.float64]] | None) – Cached simulation result, shape (steps, n_joints, 2). None until simulate() is called.
metadata (dict[str, Any]) – Arbitrary extra data (topology name, catalog entry, etc.).
- dimensions: ndarray[tuple[Any, ...], dtype[float64]]
- classmethod from_agent(agent: Agent, n_joints: int) Member
Convert a legacy Agent to a Member.
- Parameters:
agent – Optimization result agent.
n_joints – Number of joints in the linkage (needed to reshape initial_positions into (n_joints, 2)).
- classmethod from_pareto_solution(sol: ParetoSolution, n_joints: int, objective_names: tuple[str, ...] = ()) Member
Convert a ParetoSolution to a Member.
- Parameters:
sol – Multi-objective optimization result.
n_joints – Number of joints in the linkage.
objective_names – Names for each objective score.
- initial_positions: ndarray[tuple[Any, ...], dtype[float64]]
- metadata: dict[str, Any]
- property score: float
Primary score (first entry, or NaN if empty).
- scores: dict[str, float]
- to_agent() Agent
Convert back to a legacy Agent for backwards compatibility.
- to_loci() tuple[tuple[tuple[float, float], ...], ...]
Convert trajectory to the loci format used by the visualizer.
- Returns:
Nested tuples
loci[frame][joint] = (x, y)compatible withshow_linkage()and friends.- Raises:
ValueError – If no trajectory has been computed yet.
- trajectory: ndarray[tuple[Any, ...], dtype[float64]] | None
- class pylinkage.population.Population(ensembles: dict[str, Ensemble] | None = None)
Bases:
objectCollection of mechanisms with potentially different topologies.
Internally organized as
topology_key → Ensemble. Supports the same iteration/filtering/ranking interface asEnsemblebut cannot batch-simulate across topologies.- Parameters:
ensembles – Pre-built ensembles keyed by a user-chosen label. If None, starts empty.
- add_ensemble(label: str, ensemble: Ensemble) None
Add or replace an ensemble.
- Parameters:
label – Human-readable label for this topology group.
ensemble – The Ensemble to add.
- ensemble(label: str) Ensemble
Get an ensemble by its label.
- Raises:
KeyError – If no ensemble with that label exists.
- flatten() list[Member]
All members as a flat list, regardless of topology.
- classmethod from_ensembles(ensembles: list[Ensemble]) Population
Build a Population from a list of Ensembles.
Labels are auto-generated as
"topology_0","topology_1", etc.
- classmethod from_members(members: list[tuple[Linkage, Member]]) Population
Build a Population from (linkage, member) pairs.
Members are grouped by topology key into Ensembles automatically.
- Parameters:
members – Pairs of (template linkage, member data).
- classmethod from_topology_solutions(solutions: list[TopologySolution]) Population
Build a Population from multi-topology synthesis results.
Groups solutions by
topology_idinto Ensembles. Each solution’sQualityMetricsare carried as scores on the Ensemble members.- Parameters:
solutions – Results from
multi_topology_synthesize()orgeneralized_synthesis().
- property n_topologies: int
Number of distinct topologies.
- rank(key: str = 'score', *, ascending: bool = True) list[Member]
All members ranked by key across topologies.
Returns a flat list because Members from different topologies cannot form a single Ensemble. If key is not found on a member but the member has exactly one score, that score is used.
- simulate_all(iterations: int | None = None, dt: float = 1.0) None
Simulate all ensembles (vectorized within each topology).
- Parameters:
iterations – Steps per member. If None, each ensemble uses its linkage’s rotation period.
dt – Time step for crank rotation.
- top(n: int, key: str = 'score', *, ascending: bool = True) list[Member]
Top n members across all topologies.
- property topologies: dict[str, Ensemble]
Topology label → Ensemble mapping (read-only view).