Skip to content

classifiers

pleat.classifiers

Classifiers for grouping graph elements by equivalence relations.

A :class:Classifier maps each item to a hashable index; items with the same index are deemed equivalent. Concrete subclasses implement different equivalences: by length, by multiset, up to cyclic rotation (with optional reflection), and combinations via :class:NestedClassifier.

The headline use case is :func:congruency_classifier, which groups faces of a tiling by polygon congruence (matching edge-length and interior-angle sequences up to cyclic rotation). Used by :mod:pleat.colorization.

Classifier

Classifier(
    save_items: bool = False, save_indices: bool = False
)

Bases: Generic[T]

Classify items by a hashable index, optionally tracking items and indices per class.

Source code in pleat/classifiers.py
def __init__(self, save_items: bool = False, save_indices: bool = False) -> None:
    super(Classifier, self).__init__()

    self.used_indices = set()

    # option to keep track of a dict mapping classes to items
    self.save_items = save_items
    if self.save_items:
        self.saved_items = dict()
    else:
        self.saved_items = None

    # option to keep track of a dict mapping classes to items
    self.save_indices = save_indices
    if self.save_indices:
        self.saved_indices = dict()
    else:
        self.saved_indices = None

classify

classify(item: T) -> Hashable

Return the equivalence class index for item and update saved items/indices.

Source code in pleat/classifiers.py
def classify(self, item: T) -> Hashable:
    """Return the equivalence class index for ``item`` and update saved items/indices."""
    index = self._get_index(item)
    if self.save_items:
        self.saved_items[index] = self.saved_items.get(index, set()).union({item})
    if self.save_indices:
        self.saved_indices[item] = index
    return index

CountingClassifier

CountingClassifier(other, *super_args, **super_kwargs)

Bases: Classifier[T]

Wrap a classifier to remap its indices to consecutive natural numbers.

Source code in pleat/classifiers.py
def __init__(self, other, *super_args, **super_kwargs):
    super(CountingClassifier, self).__init__(*super_args, **super_kwargs)
    self.non_counting_classifier = other
    self.current_count = 0
    self.index_to_count = dict()

RepresentationClassifier

RepresentationClassifier(*super_args, **super_kwargs)

Bases: Classifier[T]

Classify items by computing a representation and comparing it against known classes.

Source code in pleat/classifiers.py
def __init__(self, *super_args, **super_kwargs):
    super(RepresentationClassifier, self).__init__(*super_args, **super_kwargs)
    self.current_count = 0
    self.count_to_repr = dict()
    self.represented_first = False

NestedClassifier

NestedClassifier(
    coarse_to_fine, *super_args, **super_kwargs
)

Bases: Classifier[T]

Chain multiple classifiers from coarse to fine, producing a tuple index.

Source code in pleat/classifiers.py
def __init__(self, coarse_to_fine, *super_args, **super_kwargs):
    # coarse_to_fine should be a list of classifier classes
    super(NestedClassifier, self).__init__(*super_args, **super_kwargs)
    self.coarse_to_fine = coarse_to_fine
    self.nested_classfier_dict = dict()
    self.base_classifier = self.coarse_to_fine[0]()

LenClassifier

LenClassifier(
    save_items: bool = False, save_indices: bool = False
)

Bases: Classifier[Sized]

Classify items by their length.

Source code in pleat/classifiers.py
def __init__(self, save_items: bool = False, save_indices: bool = False) -> None:
    super(Classifier, self).__init__()

    self.used_indices = set()

    # option to keep track of a dict mapping classes to items
    self.save_items = save_items
    if self.save_items:
        self.saved_items = dict()
    else:
        self.saved_items = None

    # option to keep track of a dict mapping classes to items
    self.save_indices = save_indices
    if self.save_indices:
        self.saved_indices = dict()
    else:
        self.saved_indices = None

SumClassifier

SumClassifier(*super_args, **super_kwargs)

Bases: RepresentationClassifier[T]

Classify items by the sum of their elements (with tolerance).

Source code in pleat/classifiers.py
def __init__(self, *super_args, **super_kwargs):
    super(RepresentationClassifier, self).__init__(*super_args, **super_kwargs)
    self.current_count = 0
    self.count_to_repr = dict()
    self.represented_first = False

UnorderedClassifier

UnorderedClassifier(*super_args, **super_kwargs)

Bases: RepresentationClassifier[T]

Classify items by their sorted elements, ignoring order.

Source code in pleat/classifiers.py
def __init__(self, *super_args, **super_kwargs):
    super(RepresentationClassifier, self).__init__(*super_args, **super_kwargs)
    self.current_count = 0
    self.count_to_repr = dict()
    self.represented_first = False

CyclicClassifier

CyclicClassifier(
    tolerance=tol,
    allow_flip=False,
    *super_args,
    **super_kwargs
)

Bases: RepresentationClassifier[T]

Classify items up to cyclic permutation (and optionally reflection).

Source code in pleat/classifiers.py
def __init__(self, tolerance=tol, allow_flip=False, *super_args, **super_kwargs):
    super(CyclicClassifier, self).__init__(*super_args, **super_kwargs)
    self.tolerance = tolerance
    self.allow_flip = allow_flip

PreMapClassifier

PreMapClassifier(other, func, *super_args, **super_kwargs)

Bases: Classifier

Apply a function to each item before passing it to another classifier.

Source code in pleat/classifiers.py
def __init__(self, other, func, *super_args, **super_kwargs):
    super(PreMapClassifier, self).__init__(*super_args, **super_kwargs)
    self.func = func
    self.other = other

AdjacencyClassifier

AdjacencyClassifier(key, *super_args, **super_kwargs)

Bases: CyclicClassifier

Classify faces by the cyclic sequence of a given attribute on their neighbors.

Source code in pleat/classifiers.py
def __init__(self, key, *super_args, **super_kwargs):
    super(AdjacencyClassifier, self).__init__(tolerance=0, *super_args, **super_kwargs)
    self.key = key

EdgeLengthClassifier

EdgeLengthClassifier(*super_args, **super_kwargs)

Bases: RepresentationClassifier

Classify half-edges by their length attribute (with tolerance tol).

Source code in pleat/classifiers.py
def __init__(self, *super_args, **super_kwargs):
    super(RepresentationClassifier, self).__init__(*super_args, **super_kwargs)
    self.current_count = 0
    self.count_to_repr = dict()
    self.represented_first = False

EdgeOrientationClassifier

EdgeOrientationClassifier(*super_args, **super_kwargs)

Bases: RepresentationClassifier

Classify half-edges by orientation mod π, so an edge and its reverse share a class.

Source code in pleat/classifiers.py
def __init__(self, *super_args, **super_kwargs):
    super(RepresentationClassifier, self).__init__(*super_args, **super_kwargs)
    self.current_count = 0
    self.count_to_repr = dict()
    self.represented_first = False

VertexOrderClassifier

VertexOrderClassifier(
    save_items: bool = False, save_indices: bool = False
)

Bases: Classifier

Classify vertices by their degree (number of incident edges).

Source code in pleat/classifiers.py
def __init__(self, save_items: bool = False, save_indices: bool = False) -> None:
    super(Classifier, self).__init__()

    self.used_indices = set()

    # option to keep track of a dict mapping classes to items
    self.save_items = save_items
    if self.save_items:
        self.saved_items = dict()
    else:
        self.saved_items = None

    # option to keep track of a dict mapping classes to items
    self.save_indices = save_indices
    if self.save_indices:
        self.saved_indices = dict()
    else:
        self.saved_indices = None

lambda_classifier

lambda_classifier(func)

Create a Classifier class that uses the given function as its index.

Source code in pleat/classifiers.py
def lambda_classifier(func):
    """Create a Classifier class that uses the given function as its index."""

    class LambdaClassifier(Classifier[T]):
        """Classifier whose index is computed by the wrapped function."""

        def _get_index(self, item):
            return func(item)

    return LambdaClassifier

congruency_classifier

congruency_classifier(allow_flip=False)

Return a classifier that groups faces by polygon congruence (edge lengths and angles).

Source code in pleat/classifiers.py
def congruency_classifier(allow_flip=False):
    """Return a classifier that groups faces by polygon congruence (edge lengths and angles)."""
    return CountingClassifier(
        PreMapClassifier(
            NestedClassifier([LenClassifier, SumClassifier, lambda: CyclicClassifier(allow_flip=allow_flip)]),
            _face_to_array,
        )
    )