Minimal Spanning Tree API Reference
Data
Data model for Minimal Spanning Tree use case.
MinimalSpanningTreeData
Bases: UcData
Data for the Minimal Spanning Tree use case.
Finds the minimum-weight spanning tree in a weighted graph.
Attributes:
-
name(Literal['minimal_spanning_tree']) –Identifier for this data type.
-
adjacency_matrix(NumPyArray) –Symmetric weighted adjacency matrix. Zero means no edge.
-
node_names(list[int | str]) –Node identifiers.
plot(*, ax: Axes | None = None) -> Axes
Plot the Minimal Spanning Tree graph instance.
Parameters:
-
ax(Axes | None, default:None) –Matplotlib axes to draw on. Creates a new figure if
None.
Returns:
-
Axes–The axes with the plot.
to_string() -> str
from_adjacency_matrix(adjacency_matrix: np.ndarray, node_names: list[int | str]) -> MinimalSpanningTreeData
staticmethod
Create MinimalSpanningTreeData from an adjacency matrix.
Parameters:
-
adjacency_matrix(ndarray) –Symmetric weighted adjacency matrix. Zero means no edge.
-
node_names(list[int | str]) –List of node identifiers.
Returns:
-
MinimalSpanningTreeData–The Minimal Spanning Tree data instance.
generate_random(n_nodes: int = 5, edge_prob: float = 0.5, max_weight: float = 10.0, seed: int | None = None) -> MinimalSpanningTreeData
staticmethod
Generate a random Minimal Spanning Tree instance.
The generated graph is guaranteed to be connected. A random spanning
tree is first created, and then additional edges are added with
probability edge_prob.
Parameters:
-
n_nodes(int, default:5) –Number of nodes, by default 5.
-
edge_prob(float, default:0.5) –Probability of additional edges beyond the spanning tree, by default 0.5.
-
max_weight(float, default:10.0) –Maximum edge weight, by default 10.0.
-
seed(int | None, default:None) –Random seed for reproducibility, by default None.
Returns:
-
MinimalSpanningTreeData–A randomly generated data instance.
Examples:
Formulation
Formulation for Minimal Spanning Tree use case.
MinimalSpanningTreeFormulation
Bases: UcFormulation[MinimalSpanningTreeData, MinimalSpanningTreeSolution]
Constraint-based flow formulation for Minimal Spanning Tree.
Mathematical Formulation
Indices and Sets: V = {0, 1, ..., n-1} -- set of nodes (node 0 is the root) E = {(i,j) : i < j, adjacency_matrix[i,j] != 0} -- set of undirected edges (upper triangle only) n = |V| -- number of nodes
Decision Variables:
y_{i,j} in {0, 1}
for each (i,j) in E.
y_{i,j} = 1 if undirected edge {i,j} is selected for the spanning tree,
y_{i,j} = 0 otherwise.
f_{i,j} in {0, 1, ..., n-1}
for each (i,j) in E and for each (j,i) in E (i.e., both directions).
f_{i,j} = amount of flow routed from node i to node j along edge {i,j}.
The flow is directed even though the underlying graph is undirected;
at most one of f_{i,j} and f_{j,i} will be nonzero in any feasible solution.
Objective: minimize sum_{(i,j) in E} adjacency_matrix[i,j] * y_{i,j}
Minimises the total weight of selected edges.
Constraints: 1. Exactly n-1 edges selected (1 constraint): sum_{(i,j) in E} y_{i,j} == n - 1 A spanning tree on n nodes has exactly n-1 edges.
2. Flow conservation at each non-root node v in V \\ {0}
(n-1 constraints, one per non-root node):
sum_{(u,v) in E} f_{u,v} - sum_{(v,w) in E} f_{v,w} == 1
Each non-root node must receive exactly 1 unit of net flow.
Together with constraint 4 this guarantees that every node is
reachable from the root, i.e. the selected edges form a connected graph.
3. Flow capacity: flow only on selected edges
(|E| constraints, one per undirected edge):
f_{i,j} + f_{j,i} <= (n-1) * y_{i,j} for all (i,j) in E
If edge {i,j} is not selected (y_{i,j} = 0) no flow can cross it
in either direction. If it is selected (y_{i,j} = 1) the combined
flow in both directions is bounded by n-1 (the maximum possible
flow any single edge could carry in a tree on n nodes).
4. Root sends exactly n-1 units of flow (1 constraint):
sum_{j : (0,j) in E} f_{0,j} - sum_{j : (j,0) in E} f_{j,0} == n - 1
The root (node 0) is the sole source of flow; it emits one unit
for each of the n-1 non-root nodes.
5. Flow variable bounds (4*|E| constraints):
0 <= f_{i,j} <= n-1 for all directed pairs (i,j)
Explicit lower and upper bounds on the integer flow variables.
Connectivity argument: Constraints 2 and 4 together ensure that the root can reach every other node via the selected edges: if any node v were unreachable from the root, the net inflow to v would be 0, violating constraint 2. Combined with constraint 1 (exactly n-1 edges), connectivity implies the selected edges form a tree (a connected acyclic graph on n nodes with n-1 edges is always a tree).
to_string(data: MinimalSpanningTreeData) -> str
staticmethod
Format the formulation as a human-readable string.
Summarises the sizes of the index sets, the decision variables, the objective, and the constraint groups for a given problem instance.
Parameters:
-
data(MinimalSpanningTreeData) –The problem data. Relevant fields: -
data.node_names: list of length n with a name for each node. -data.adjacency_matrix: n×n weight matrix; entry [i,j] is the edge weight for {i,j}, or 0 if the edge does not exist.
Returns:
-
str–Multi-line string describing the formulation dimensions and constraint groups for the given instance.
formulate(data: MinimalSpanningTreeData) -> Model
staticmethod
Formulate the MST problem as a mixed-integer programming (MIP) model.
Uses a flow-based formulation to enforce connectivity without exponential subtour elimination constraints. The key insight is that routing one unit of flow from a designated root to every other node is equivalent to requiring that those nodes are reachable from the root — i.e. the selected edges span the graph.
Variable naming convention
Binary edge variables:
y_{i}_{j} where i < j and (i,j) in E.
The indices i and j are the 0-based positions of the two endpoints
in data.node_names.
Integer flow variables (one per directed arc):
f_{i}_{j} for the arc from node i to node j.
f_{j}_{i} for the arc from node j to node i.
Again, i < j to match the edge set E; both directions are created
for each undirected edge.
Constraint naming convention
n_minus_1_edges -- constraint 1 (exactly n-1 edges).
flow_conservation_{v} -- constraint 2 for node v (v != 0).
flow_capacity_{i}_{j} -- constraint 3 for edge (i,j).
root_flow -- constraint 4 (root net outflow = n-1).
flow_lb_{i}_{j} -- lower bound f_{i,j} >= 0.
flow_ub_{i}_{j} -- upper bound f_{i,j} <= n-1.
(similarly flow_lb_{j}_{i} / flow_ub_{j}_{i} for the reverse arc)
Parameters:
-
data(MinimalSpanningTreeData) –The problem data. Relevant fields: -
data.node_names: list of n node labels (strings or ints). The index of a label in this list is the node index used throughout the model. Node at index 0 is the root. -data.adjacency_matrix: n×n numpy array. Entry [i, j] is the weight of edge {i, j}; 0 means the edge does not exist. The matrix is assumed to be symmetric; only the upper triangle (i < j) is read.
Returns:
-
Model–A Luna Model ready to be solved. The model name encodes a hash of the input data so that repeated calls with identical data reuse cached results where possible.
interpret(solution: Solution, data: MinimalSpanningTreeData) -> MinimalSpanningTreeSolution
staticmethod
Extract a Minimal Spanning Tree solution from the solver result.
Reads the binary edge-selection variables y_{i}_{j} from the best
sample returned by the solver and reconstructs the list of selected
tree edges in terms of the original node names (rather than their
0-based indices).
Variable lookup:
The solver stores each variable under its string name. For a binary
edge variable between nodes at indices i and j (i < j) the name is
"y_{i}_{j}". A value above BINARY_DIVIDER (0.5) is rounded
to 1 (edge selected); at or below it is rounded to 0 (not selected).
Index-to-name mapping:
data.node_names[i] gives the original label for node index i.
Selected edges are therefore reported as
(data.node_names[i], data.node_names[j]).
Parameters:
-
solution(Solution) –The solver solution object.
solution.best()returns a list of samples;sample.sampleis a dict mapping variable name (str) to its value in that sample. -
data(MinimalSpanningTreeData) –The original problem data. Used to: - determine n = len(data.node_names), - reconstruct the edge list E (same upper-triangle enumeration used in
formulate), - look up edge weights viadata.adjacency_matrix[i, j], - map node indices back to node names viadata.node_names.
Returns:
-
MinimalSpanningTreeSolution–Structured solution with: -
tree_edges: list of (name_i, name_j) pairs for selected edges. -total_weight: sum of weights of selected edges (float). -is_valid: True iff the selected edges form a valid spanning tree.
Raises:
-
NoSolutionFoundError–If the solver did not find any feasible solution (
solution.best()returns None).
Solution
Solution model for Minimal Spanning Tree use case.
MinimalSpanningTreeSolution
Bases: UcSolution
Solution for the Minimal Spanning Tree use case.
Attributes:
-
name(Literal['minimal_spanning_tree']) –Identifier.
-
tree_edges(list[tuple[int | str, int | str]]) –Edges in the spanning tree.
-
total_weight(float) –Total weight of the spanning tree.
-
is_valid(bool) –Whether the solution is a valid spanning tree (n-1 edges, connected, all edges exist in the graph).
plot(data: MinimalSpanningTreeData | None = None, *, ax: Axes | None = None) -> Axes
Plot the Minimal Spanning Tree solution on the problem graph.
Tree edges are highlighted in green; other edges are grey.
Parameters:
-
data(MinimalSpanningTreeData | None, default:None) –Problem data used to reconstruct the graph. Required -- a
ValueErroris raised whenNone. -
ax(Axes | None, default:None) –Matplotlib axes to draw on. Creates a new figure if
None.
Returns:
-
Axes–The axes with the plot.
Raises:
-
ValueError–If data is
None.
to_string() -> str
Format the solution as a human-readable string.
Returns:
-
str–String representation of the solution.
Instance
Instance model for Minimal Spanning Tree use case.
MinimalSpanningTreeInstance
Bases: UcInstance[MinimalSpanningTreeData, MinimalSpanningTreeFormulation, MinimalSpanningTreeSolution]
Instance combining data and formulation for Minimal Spanning Tree.
Collection
Collection of Minimal Spanning Tree instances.
MinimalSpanningTreeCollection
Bases: UcInstanceCollection[MinimalSpanningTreeInstance]
Collection of Minimal Spanning Tree instances.
This collection provides methods to generate benchmark instances with various characteristics for testing and evaluation.
from_random(min_nodes: int, max_nodes: int, edge_prob: float = 0.5, max_weight: float = 10.0, num_instances: int = 1, *, seed: int | None = None) -> MinimalSpanningTreeCollection
classmethod
Generate random Minimal Spanning Tree instances.
Parameters:
-
min_nodes(int) –Minimum number of nodes.
-
max_nodes(int) –Maximum number of nodes.
-
edge_prob(float, default:0.5) –Additional edge probability beyond the spanning tree, by default 0.5.
-
max_weight(float, default:10.0) –Maximum edge weight, by default 10.0.
-
num_instances(int, default:1) –Number of instances per size, by default 1.
-
seed(int | None, default:None) –Random seed for reproducibility, by default None.
Returns:
-
MinimalSpanningTreeCollection–Collection containing generated instances.
Examples: