"""Abstract base classes for geometries.
This module defines abstract base classes for different types of geometries.
Among other things, these can be used to pre-define metrics and absolute
quadrics and they can be given to spheres.
"""
from abc import ABC, abstractmethod
from ddg.geometry._quadrics import Quadric
from ddg.geometry.abc import CayleyKleinSphereFactory, SphereFactory
from ddg.geometry.spheres import (
CayleyKleinSphere,
GeneralizedCayleyKleinSphere,
MetricCayleyKleinSphere,
)
__all__ = ["MetricGeometry", "CayleyKleinGeometry", "MetricCayleyKleinGeometry"]
[docs]class MetricGeometry(ABC):
"""Geometry that just has a dimension and defines a metric.
Parameters
----------
dimension : int
Attributes
----------
dimension : int
Notes
-----
This class supports the `==` operator. Two metric geometries are equal if
and only if they have the same type and dimension.
"""
def __init__(self, dimension):
self.dimension = dimension
[docs] @abstractmethod
def d(self, v, w) -> float:
"""Metric function
Parameters
----------
v, w : Point or array_like of shape (n,)
Returns
-------
float
"""
raise NotImplementedError
def __eq__(self, other):
if type(self) is not type(other):
return False
return self.dimension == other.dimension
def __repr__(self):
module_name = type(self).__module__.split(".")[-1]
return f"{module_name}.{self.__class__.__name__}({self.dimension})"
@abstractmethod
def __contains__(self, point):
raise NotImplementedError
[docs]class CayleyKleinGeometry(CayleyKleinSphereFactory):
"""Cayley-Klein geometry abstract base class.
Parameters
----------
dimension : int
Dimension of the geometry. This is the actual "intuitive" dimension of
the geometry, *not* the ambient dimension of the model.
Attributes
----------
dimension : int
Notes
-----
This class supports `__eq__`, i.e. `==`. Two quadric geometries are equal
if and only if they have the same type, dimension and quadric.
"""
absolute: Quadric
"""The absolute quadric."""
def __init__(self, dimension):
self.dimension = dimension
@property
def ambient_dimension(self):
return self.absolute.ambient_dimension
[docs] def inner_product(self, v, w):
"""Alias for self.absolute.inner_product."""
return self.absolute.inner_product(v, w)
[docs] def cayley_klein_distance(self, v, w):
"""Alias for self.absolute.cayley_klein_distance."""
return self.absolute.cayley_klein_distance(v, w)
[docs] def cayley_klein_sphere(self, center, radius, subspace=None, atol=None, rtol=None):
"""Create a Cayley-Klein sphere.
Parameters
----------
center : ddg.geometry.Point or numpy.ndarray of shape (n+1,)
radius : float
Cayley-Klein radius
subspace : ddg.geometry.Subspace or list of numpy.ndarray of shape (k,)
(default=None)
Returns
-------
ddg.geometry.spheres.CayleyKleinSphere
"""
return CayleyKleinSphere(
center,
radius,
subspace=subspace,
absolute=self.absolute,
geometry=self,
atol=atol,
rtol=rtol,
)
[docs] def generalized_cayley_klein_sphere(
self, center, radius, subspace=None, atol=None, rtol=None
):
"""Create a generalized Cayley-Klein sphere.
Parameters
----------
center : ddg.geometry.Point or numpy.ndarray of shape (n+1,)
radius : float
Generalized radius
subspace : ddg.geometry.Subspace or list of numpy.ndarray of shape (k,)
(default=None)
Returns
-------
ddg.geometry.spheres.GeneralizedCayleyKleinSphere
"""
return GeneralizedCayleyKleinSphere(
center,
radius,
subspace=subspace,
absolute=self.absolute,
geometry=self,
atol=atol,
rtol=rtol,
)
def __eq__(self, other):
if type(self) is not type(other):
return False
return (self.dimension, self.absolute) == (other.dimension, other.absolute)
def __repr__(self):
module_name = type(self).__module__.split(".")[-1]
return f"{module_name}.{self.__class__.__name__}({self.dimension})"
@abstractmethod
def __contains__(self, point):
raise NotImplementedError
[docs]class MetricCayleyKleinGeometry(CayleyKleinGeometry, MetricGeometry, SphereFactory):
"""Metric Cayley-Klein geometry.
A metric Cayley-Klein geometry is a Geometry with a metric that is computed from a
Cayley-Klein "distance" induced by a quadric.
Parameters
----------
dimension : int
Attributes
----------
dimension : int
Notes
-----
This class supports `__eq__`, i.e. `==`. Two metric Cayley-Klein geometries are
equal if and only if they have the same type, dimension and quadric.
"""
[docs] @abstractmethod
def metric_to_cayley_klein_distance(self, d) -> float:
"""Return Metric distance converted to Cayley-Klein "distance".
Parameters
----------
d : float
Returns
-------
K : float
"""
[docs] @abstractmethod
def cayley_klein_distance_to_metric(self, d) -> float:
"""Convert Cayley-Klein "distance" to metric.
Parameters
----------
K : float
Returns
-------
d : float
"""
[docs] def d(self, v, w) -> float:
"""Cayley-Klein metric
Parameters
----------
v, w : numpy.ndarray or ddg.geometry.Point
Homogeneous coordinate vectors or Point instances. Both points
must be either inside or outside the absolute quadric.
Returns
-------
float
"""
return self.cayley_klein_distance_to_metric(self.cayley_klein_distance(v, w))
[docs] def sphere(self, center, radius, subspace=None, atol=None, rtol=None):
"""Create a sphere with metric radius.
Parameters
----------
center : ddg.geometry.Point or numpy.ndarray of shape (n+1,)
radius : float
Radius in terms of the Cayley-Klein Metric `self.d`.
subspace : ddg.geometry.Subspace or array_like of shape (m,n) (default=None)
Returns
-------
ddg.geometry.spheres.MetricCayleyKleinSphere
"""
return MetricCayleyKleinSphere(
center,
radius,
subspace=subspace,
absolute=self.absolute,
geometry=self,
atol=atol,
rtol=rtol,
)
def __contains__(self, point):
return point in self.absolute.subspace and point not in self.absolute