circular_ordering#

Circular ordering module.

A circular ordering represents a cyclic arrangement of elements, such as the order of taxa around a circular phylogenetic tree or network. Circular orderings are used in network reconstruction algorithms and visualization. This module provides classes for working with circular orderings of sets and elements.

class phylozoo.core.primitives.circular_ordering.CircularOrdering(order: list[T])[source]#

Bases: CircularSetOrdering

A circular ordering of elements.

This class represents a circular ordering where each element is in its own singleton set. It is a special case of CircularSetOrdering.

The ordering is stored in canonical form (lexicographically smallest rotation, considering both forward and reverse directions), which makes equality and hashing operations efficient.

Parameters:

order (list[T]) – List of elements in circular order.

Notes

The circular ordering is immutable and stored in canonical form. Two CircularOrderings are considered equal if they are the same up to cyclic permutation or reversal. Since both are canonical, equality is a simple tuple comparison.

Examples

>>> co = CircularOrdering([1, 2, 3, 4])
>>> len(co)
4
>>> 1 in co
True
>>> co.are_neighbors(1, 2)
True
__contains__(element: T) bool[source]#

Check if an element is in the circular ordering.

Parameters:

element (T) – Element to check.

Returns:

True if element is in the ordering, False otherwise.

Return type:

bool

Examples

>>> co = CircularOrdering([1, 2, 3])
>>> 1 in co
True
>>> 4 in co
False
__eq__(other: Any) bool[source]#

Check if two circular orderings are equal.

Two circular orderings are equal if they have the same elements and the same circular ordering (up to cyclic permutation or reversal).

Parameters:

other (Any) – Object to compare with.

Returns:

True if circular orderings are equal, False otherwise.

Return type:

bool

Examples

>>> co1 = CircularOrdering([1, 2, 3])
>>> co2 = CircularOrdering([2, 3, 1])  # Cyclic permutation
>>> co1 == co2
True
__hash__() int[source]#

Return hash of the circular ordering.

Returns:

Hash value based on canonical circular ordering.

Return type:

int

__iter__() Iterator[T][source]#

Return an iterator over the elements in circular order.

Returns:

Iterator over the elements in the circular ordering.

Return type:

Iterator[T]

__repr__() str[source]#

Return string representation of the circular ordering.

Returns:

String representation showing the elements in order.

Return type:

str

__setattr__(name: str, value: Any) None[source]#

Override to allow setting _order during initialization.

Parameters:
  • name (str) – Attribute name.

  • value (Any) – Attribute value.

Raises:
are_neighbors(elt1: T, elt2: T) bool[source]#

Check if two elements are neighbors in the circular ordering.

Two elements are neighbors if they appear consecutively in the circular ordering (including the wrap-around from last to first).

Parameters:
  • elt1 (T) – First element to check.

  • elt2 (T) – Second element to check.

Returns:

True if elements are neighbors, False otherwise.

Return type:

bool

Raises:

PhyloZooValueError – If elt1 equals elt2, or if either element is not in the order.

Examples

>>> co = CircularOrdering([1, 2, 3, 4])
>>> co.are_neighbors(1, 2)
True
>>> co.are_neighbors(1, 4)
True  # Wrap-around
property order: tuple#

Get the circular ordering of elements (read-only).

Returns:

Tuple of elements in the circular ordering.

Return type:

tuple

suborderings(size: int = 4) Iterator[CircularOrdering][source]#

Generate all suborderings of a specified size.

A subordering is a circular ordering formed by selecting a subset of elements from the current ordering (all combinations, not just consecutive).

Parameters:

size (int, optional) – Number of elements to include in each subordering, by default 4.

Yields:

CircularOrdering – Suborderings of the specified size.

Examples

>>> co = CircularOrdering([1, 2, 3, 4, 5])
>>> subs = list(co.suborderings(size=2))
>>> len(subs)
10  # C(5,2) = 10 combinations
to_circular_setordering(mapping: dict[T, set[T]] | None = None) CircularSetOrdering[source]#

Convert to CircularSetOrdering with optional mapping.

Maps each element to a set. If no mapping is provided, each element is mapped to its singleton set.

Parameters:

mapping (dict[T, set[T]] | None, optional) – Dictionary mapping elements to sets. If None, elements are mapped to singleton sets, by default None.

Returns:

A CircularSetOrdering with the mapped sets.

Return type:

CircularSetOrdering

Examples

>>> co = CircularOrdering([1, 2, 3])
>>> cso = co.to_circular_setordering()
>>> cso
CircularSetOrdering([{1}, {2}, {3}])
>>> # With custom mapping
>>> mapping = {1: {1, 10}, 2: {2}, 3: {3, 30}}
>>> cso2 = co.to_circular_setordering(mapping)
>>> cso2
CircularSetOrdering([{1, 10}, {2}, {3, 30}])
class phylozoo.core.primitives.circular_ordering.CircularSetOrdering(setorder: list[set[T]])[source]#

Bases: Partition

A circular ordering of sets that forms a partition.

This class represents a partition with an additional circular ordering structure. The sets must be disjoint (as required by Partition), and the ordering is considered equivalent under cyclic permutations and reversals.

The ordering is stored in canonical form (lexicographically smallest rotation, considering both forward and reverse directions), which makes equality and hashing operations efficient.

Parameters:

setorder (list[set[T]]) – List of sets in circular order. The sets must be disjoint.

Notes

The circular ordering is immutable and stored in canonical form. Two CircularSetOrderings are considered equal if they are the same up to cyclic permutation or reversal. Since both are canonical, equality is a simple tuple comparison.

Examples

>>> cso = CircularSetOrdering([{1, 2}, {3}, {4, 5}])
>>> len(cso)
3
>>> {1, 2} in cso
True
>>> cso.are_neighbors({1, 2}, {3})
True
__eq__(other: Any) bool[source]#

Check if two circular set orderings are equal.

Two circular set orderings are equal if they have the same sets and the same circular ordering (up to cyclic permutation or reversal). Since both are stored in canonical form, we can compare directly.

Parameters:

other (Any) – Object to compare with.

Returns:

True if circular set orderings are equal, False otherwise.

Return type:

bool

Examples

>>> cso1 = CircularSetOrdering([{1, 2}, {3}, {4}])
>>> cso2 = CircularSetOrdering([{3}, {4}, {1, 2}])  # Cyclic permutation
>>> cso1 == cso2
True
__hash__() int[source]#

Return hash of the circular set ordering.

Since the ordering is stored in canonical form, we can hash it directly.

Returns:

Hash value based on canonical circular ordering.

Return type:

int

__iter__() Iterator[frozenset][source]#

Return an iterator over the sets in circular order.

Returns:

Iterator over the sets in the circular ordering.

Return type:

Iterator[frozenset]

__repr__() str[source]#

Return string representation of the circular set ordering.

Returns:

String representation showing the sets in order.

Return type:

str

__setattr__(name: str, value: Any) None[source]#

Override to allow setting _setorder during initialization.

Parameters:
  • name (str) – Attribute name.

  • value (Any) – Attribute value.

Raises:
are_neighbors(set1: set[T, frozenset], set2: set[T, frozenset]) bool[source]#

Check if two sets are neighbors in the circular ordering.

Two sets are neighbors if they appear consecutively in the circular ordering (including the wrap-around from last to first).

Parameters:
Returns:

True if sets are neighbors, False otherwise.

Return type:

bool

Raises:

PhyloZooValueError – If set1 equals set2, or if either set is not in the setorder.

Examples

>>> cso = CircularSetOrdering([{1, 2}, {3}, {4}])
>>> cso.are_neighbors({1, 2}, {3})
True
>>> cso.are_neighbors({1, 2}, {4})
True  # Wrap-around
>>> cso.are_neighbors({1, 2}, {4})
True
are_singletons() bool[source]#

Check if all sets in the ordering are singletons.

Returns:

True if all sets have exactly one element, False otherwise.

Return type:

bool

Examples

>>> cso = CircularSetOrdering([{1}, {2}, {3}])
>>> cso.are_singletons()
True
>>> cso2 = CircularSetOrdering([{1, 2}, {3}])
>>> cso2.are_singletons()
False
representative_orderings() Iterator[CircularOrdering][source]#

Generate all CircularOrderings with exactly one element per set.

For each set in the circular set ordering, selects exactly one element, creating all possible circular orderings.

Yields:

CircularOrdering – Representative circular orderings.

Examples

>>> cso = CircularSetOrdering([{1, 2}, {3}])
>>> reps = list(cso.representative_orderings())
>>> len(reps)
2  # 2 choices from first set * 1 choice from second set

Notes

The number of representative orderings grows exponentially with the number of sets and their sizes. For large orderings, this method may be slow or consume significant memory. This method is a generator, so it yields results lazily rather than building a list in memory.

property setorder: tuple#

Get the circular ordering of sets (read-only).

Returns:

Tuple of frozensets representing the circular ordering.

Return type:

tuple

suborderings(size: int = 4) Iterator[CircularSetOrdering][source]#

Generate all suborderings of a specified size.

A subordering is a circular set ordering formed by selecting a subset of sets from the current ordering (all combinations, not just consecutive).

Parameters:

size (int, optional) – Number of sets to include in each subordering, by default 4.

Yields:

CircularSetOrdering – Suborderings of the specified size.

Examples

>>> cso = CircularSetOrdering([{1}, {2}, {3}, {4}, {5}])
>>> subs = list(cso.suborderings(size=2))
>>> len(subs)
10  # C(5,2) = 10 combinations
to_circular_ordering() CircularOrdering[source]#

Convert to CircularOrdering if all sets are singletons.

Returns:

A CircularOrdering with the elements from singleton sets.

Return type:

CircularOrdering

Raises:

PhyloZooValueError – If not all sets are singletons.

Examples

>>> cso = CircularSetOrdering([{1}, {2}, {3}])
>>> co = cso.to_circular_ordering()
>>> co
CircularOrdering([1, 2, 3])