Partitions#
Working with Partitions#
The Partition class represents a partition of a set
into disjoint, non-empty subsets that cover the entire set. Partitions are immutable
and provide methods for mathematical operations essential to phylogenetic analysis.
Creating Partitions#
Partitions can be created from any iterable of iterables representing the disjoint subsets:
from phylozoo.core.primitives import Partition
# Create a partition from sets
partition = Partition([{1, 2}, {3, 4}, {5}])
# Create from lists (automatically converted to sets)
partition2 = Partition([[1, 2], [3, 4], [5]])
# Empty partition (edge case)
empty_partition = Partition([])
The constructor validates that the input represents a valid mathematical partition. All subsets must be disjoint.
Accessing Partition Properties#
Basic properties
Partitions provide access to their parts and the set of all elements:
# Access the partition parts
parts = partition.parts # frozenset({frozenset({1, 2}), frozenset({3, 4}), frozenset({5})})
# Get all elements in the partition
elements = partition.elements # frozenset({1, 2, 3, 4, 5})
Equality and hashing
Partitions are immutable and hashable. Two partitions are considered equal if they have the same parts, regardless of the order in which parts were specified:
# Two partitions are equal if they have the same parts
p1 = Partition([{1, 2}, {3, 4}])
p2 = Partition([{3, 4}, {1, 2}]) # Same parts, different order
are_equal = p1 == p2 # True
# Partitions are hashable (can be used as dict keys or set elements)
partition_set = {partition, finer}
partition_dict = {partition: "coarse", finer: "fine"}
Element queries
The get_part() method returns the part
containing a specific element. You can check if a set is one of the partition parts
using the in operator:
# Get the part containing a specific element
part_containing_3 = partition.get_part(3) # frozenset({3, 4})
# Check if a set is one of the partition parts
is_part = {1, 2} in partition # True
is_part = {1, 3} in partition # False
Size and length
size() returns the total number of
elements; len() returns the number of parts:
# Number of parts in the partition
num_parts = len(partition) # 3
# Total number of elements across all parts
total_elements = partition.size() # 5
Iteration
You can iterate over the parts of a partition (in canonical order):
for part in partition:
print(part) # Each part is a frozenset
Partition Operations#
Partitions support fundamental mathematical operations used in phylogenetic analysis.
Refinement checking
A partition \(P\) is a refinement of partition \(Q\) if every part of \(P\) is contained within
some part of \(Q\). Refinement relations can be checked using the is_refinement() method:
# Create a finer partition (more parts)
finer = Partition([{1}, {2}, {3, 4}, {5}])
# Check if finer is a refinement of partition
is_refinement = partition.is_refinement(finer) # False
is_refinement = finer.is_refinement(partition) # True
Subpartitions
The subpartitions() method yields all subpartitions of a given
size. A subpartition is formed by selecting that many parts from the current partition.
# All subpartitions with 2 parts from a 5-part partition
partition = Partition([{1}, {2}, {3}, {4}, {5}])
subparts = list(partition.subpartitions(size=2))
len(subparts) # C(5, 2) = 10
Representative partitions
The representative_partitions() method yields all partitions
that have exactly one element chosen from each part (singleton representatives). Useful for
enumerating one representative per block.
partition = Partition([{1, 2}, {3, 4}])
reps = list(partition.representative_partitions())
len(reps) # 2 * 2 = 4 (one element from first part, one from second)
reps[0] # e.g. Partition([{1}, {3}])
See Also#
API Reference - Complete function signatures and detailed examples
Splits - A specific partition with exactly two parts
Circular Ordering - A partition with a circular ordering structure