from abc import ABC, abstractmethod
import numpy as np
from ddg.halfedge import complement
[docs]class HalfEdgeFunctional(ABC):
"""
Abstract base class for functionals on half-edge objects.
When creating functionals inheriting from this class the __init__ function
should be inherited as the defined attributes are being used in
optimization.
Attributes
----------
surface : ddg.halfedge.Surface
Half-edge surface to work on
attr_name : str
Name of the attribute for minimization
attr_dimension : int (optional)
Dimension of the attribute.
If not given it will be determined automatically.
cell_type : str
Either "verts", "edges" or "faces" depending on where the minimization
attribute is located
boundary_cells : set (default = set())
Boundary cells for the minimization, i.e. vertices that have
and keep a fixed value and are excluded from minimization process
interior_cell_index_attr_name : str (default = "interior_cell_index")
Attribute name for indices of interior cells.
The interior cells are enumerated using this attribute.
Parameters
----------
surface
attr_name
attr_dimension
boundary_cells
interior_cells
Methods
-------
evaluate
Returns the value of the functional.
Notes
-----
The functional can additionally implement the following methods
which are then used in the optimization process:
- gradient
- hessian
"""
def __init__(
self,
surface,
attr_name,
cell_type,
attr_dimension=None,
boundary_cells=set(),
interior_cell_index_attr_name="interior_cell_index",
):
self.surface = surface
self.attr_name = attr_name
self.cell_type = cell_type
self.boundary_cells = boundary_cells
self._generate_interior_cell_index(
interior_cell_index_attr_name=interior_cell_index_attr_name
)
if attr_dimension is None:
self.attr_dimension = self._attr_dimension()
def _attr_dimension(self):
"""
Method to automatically retrieve the attribute dimension
"""
x0 = np.array([getattr(v, self.attr_name) for v in self.interior_cells])
attr_dim = 1 if x0.ndim == 1 else x0.shape[1]
return attr_dim
[docs] @abstractmethod
def evaluate(self, x) -> float:
"""
Evaluation function of the functional
Parameters
----------
x: numpy.ndarray of shape (n, d)
Variables of the minimization process, where n is the number of
interior cells, and d=attr_dimension.
The n interior cells are ordered according to the attribute given
by interior_cell_index_attr_name.
The values of the attribute on the boundary cells need to be
retrieved directly from the surface.
Returns
-------
float
Value of the functional
"""
pass
@property
def interior_cells(self):
"""
Method to distinguish the interior cells of the surface from the
specified boundary cells. Equal to the complement of boundary_cells
attribute in the surface.
"""
return complement(self.boundary_cells, self.cell_type, self.surface)
def _generate_interior_cell_index(
self, interior_cell_index_attr_name="interior_cell_index"
):
"""
Method to enumerate the interior cells
"""
getattr(self.surface, self.cell_type).add_attribute(
interior_cell_index_attr_name, None
)
for i, v in enumerate(self.interior_cells):
setattr(v, interior_cell_index_attr_name, i)