Source code for pygrates.abc

"""Abstract base classes for user-defined coordinates.

The base classes in this module form an interface for using the
functions in `pygrates.moves`. The user creates a coordinate class
by explicitly subclassing one of the bases and implementing its
abstract methods, or implicitly by implementing all of its methods.
All coordinates need to be *hashable* and to define *equality* with
coordinates of the same type: this can easily achieved with a named
tuple or dataclass implementation.

Examples
--------
>>> from dataclasses import dataclass
>>> @dataclass(frozen=True)
... class Point2D(pg.abc.DGCoords):
...   x: int
...   y: int
...
...   def children(self):
...     return Point2D(self.x + 1, self.y), Point2D(self.x, self.y + 1)
...
...   def parents(self):
...     return Point2D(self.x - 1, self.y), Point2D(self.x, self.y - 1)
...
>>> origin = Point2D(0, 0)
>>> isinstance(origin, pg.abc.DGCoords)
True
"""

from __future__ import annotations # Default behavior pending PEP 649

from abc import ABC, abstractmethod
from collections.abc import Iterable
from typing import Self

from itertools import chain

# Base coordinate classes to implement for using the library functions

[docs] class GCoords(ABC): """Base class for graph coordinates. Interface for using the functions in `pygrates.moves`. User-created coordinate class implicitly defines an undirected or directed graph. Methods to implement are `__eq__`, `__hash__` and `adjacent`. """ __slots__ = ()
[docs] @abstractmethod def __eq__(self, other: object) -> bool: """Return True if self is equal to other coordinate. Parameters ---------- other : Self Coordinate object of the same type as self. Returns ------- bool True if passed coordinate is equal to self. """ raise NotImplementedError
[docs] @abstractmethod def __hash__(self) -> int: """Return hash value of self. Returns ------- int Hash value of self. """ raise NotImplementedError
[docs] @abstractmethod def adjacent(self) -> Iterable[Self]: """Return iterable containing adjacent coordinates. Returns ------- Iterable[Self] Iterable containing coordinates adjacent to self, of the same type. """ raise NotImplementedError
[docs] def is_adjacent(self, other: Self) -> bool: """Return True if self is adjacent to other coordinate. Parameters ---------- other : Self Coordinate object of the same type as self. Returns ------- bool True if self is adjacent to passed coordinate. """ adjacent: Iterable[Self] = self.adjacent() return any(coords == other for coords in adjacent)
[docs] class DGCoords(GCoords, ABC): """Base class for directed graph coordinates. Interface for using the functions in `pygrates.moves`. User-created coordinate class implicitly defines a directed graph. Methods to implement are `__eq__`, `__hash__`, `children`, and `parents`. """ __slots__ = ()
[docs] @abstractmethod def children(self) -> Iterable[Self]: """Return iterable containing child coordinates. Returns ------- Iterable[Self] Iterable containing child coordinates of self, of the same type. """ raise NotImplementedError
[docs] @abstractmethod def parents(self) -> Iterable[Self]: """Return iterable containing parent coordinates. Returns ------- Iterable[Self] Iterable containing parent coordinates of self, of the same type. """ raise NotImplementedError
[docs] def adjacent(self) -> Iterable[Self]: """Return iterable containing adjacent coordinates. Returns ------- Iterable[Self] Iterable containing coordinates adjacent to self, of the same type. """ return chain(self.children(), self.parents())
[docs] def is_child(self, other: Self) -> bool: """Return True if self is a child of other coordinate. Parameters ---------- other : Self Coordinate object of the same type as self. Returns ------- bool True if self is a child of passed coordinate. """ parents: Iterable[Self] = self.parents() return any(coords == other for coords in parents)
[docs] def is_parent(self, other: Self) -> bool: """Return True if self is a parent of other coordinate. Parameters ---------- other : Self Coordinate object of the same type as self. Returns ------- bool True if self is a parent of passed coordinate. """ children: Iterable[Self] = self.children() return any(coords == other for coords in children)
class DAGCoords(DGCoords, ABC): """Base class for directed-acyclic-graph coordinates. Interface for using the functions in `pygrates.moves`. User-created coordinate class implicitly defines a directed acyclyc graph. Methods to implement are `__eq__`, `__hash__`, `children`, and `parents`. """ __slots__ = () class TGCoords(DAGCoords, ABC): """Base class for tree coordinates. Interface for using the functions in `pygrates.moves`. User-created coordinate class implicitly defines a tree graph. Methods to implement are `__eq__`, `__hash__`, `children`, and `parents`. """ __slots__ = ()