Page MenuHomec4science

moving_least_squares_interpolator.py
No OneTemporary

File Metadata

Created
Thu, May 16, 15:12

moving_least_squares_interpolator.py

# Copyright (C) 2018 by the RROMPy authors
#
# This file is part of RROMPy.
#
# RROMPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RROMPy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with RROMPy. If not, see <http://www.gnu.org/licenses/>.
#
import numpy as np
from copy import deepcopy as copy
from rrompy.utilities.base.types import (List, ListAny, DictAny, Np1D, Np2D,
paramList)
from rrompy.utilities.numerical import customPInv
from .vander import mlsweights
from rrompy.utilities.poly_fitting.interpolator import GenericInterpolator
from rrompy.utilities.poly_fitting.polynomial.vander import (polyvander as pv,
polyvanderTotal as pvT)
from rrompy.utilities.exception_manager import RROMPyException, RROMPyAssert
from rrompy.parameter import checkParameterList
__all__ = ['MovingLeastSquaresInterpolator']
class MovingLeastSquaresInterpolator(GenericInterpolator):
"""HERE"""
def __init__(self, other = None):
if other is None: return
self.support = other.support
self.localProjector = other.localProjector
self.localVanders = other.localVanders
self.suppValues = other.suppValues
self.directionalWeights = other.directionalWeights
self.degree = other.degree
self.npar = other.npar
self.radialbasis = other.radialbasis
self.polybasis = other.polybasis
self.evalParams = other.evalParams
self.totalDegree = other.totalDegree
@property
def shape(self):
sh = self.suppValues.shape[1 :] if self.suppValues.ndim > 1 else 1
return sh
@property
def deg(self):
return self.degree
def __call__(self, mu:paramList, der : List[int] = None,
scl : Np1D = None):
if der is not None and np.sum(der) > 0:
raise RROMPyException(("Cannot take derivatives of moving least "
"squares function."))
mu = checkParameterList(mu, self.npar)[0]
sh = self.shape
if sh == 1: sh = tuple([])
values = np.empty((len(mu),) + sh, dtype = self.suppValues.dtype)
for i, m in enumerate(mu):
weights = mlsweights(m, self.support, self.radialbasis,
directionalWeights = self.directionalWeights)
weights /= np.linalg.norm(weights)
vanderLS = np.sum(self.localVanders * weights, axis = 2)
RHSLS = np.tensordot(self.localProjector * weights,
self.suppValues, 1)
if self.totalDegree:
vanderEval, _, _ = pvT(m, self.deg[0], self.polybasis,
**self.evalParams)
else:
vanderEval = pv(m, self.deg, self.polybasis, **self.evalParams)
vanderEval = vanderEval.flatten()
values[i] = vanderEval.dot(customPInv(vanderLS).dot(RHSLS))
return values
def __copy__(self):
return MovingLeastSquaresInterpolator(self)
def __deepcopy__(self, memo):
other = MovingLeastSquaresInterpolator()
(other.support, other.localProjector, other.localVanders,
other.suppValues, other.directionalWeights, other.degree,
other.npar, other.radialbasis, other.polybasis, other.evalParams,
other.totalDegree) = copy(
self.support, self.localProjector, self.localVanders,
self.suppValues, self.directionalWeights, self.degree,
self.npar, self.radialbasis, self.polybasis,
self.evalParams, self.totalDegree, memo)
return other
def postmultiplyTensorize(self, A:Np2D):
RROMPyAssert(A.shape[0], self.shape[-1], "Shape of output")
self.suppValues = np.tensordot(self.suppValues, A, axes = (-1, 0))
def pad(self, nleft : List[int] = None, nright : List[int] = None):
if nleft is None: nleft = [0] * len(self.shape)
if nright is None: nright = [0] * len(self.shape)
if not hasattr(nleft, "__len__"): nleft = [nleft]
if not hasattr(nright, "__len__"): nright = [nright]
RROMPyAssert(len(self.shape), len(nleft), "Shape of output")
RROMPyAssert(len(self.shape), len(nright), "Shape of output")
padwidth = [(0, 0)] + [(l, r) for l, r in zip(nleft, nright)]
self.suppValues = np.pad(self.suppValues, padwidth, "constant",
constant_values = (0., 0.))
def setupByInterpolation(self, support:paramList, values:ListAny,
deg:int, polybasis : str = "MONOMIAL_GAUSSIAN",
directionalWeights : Np1D = None,
totalDegree : bool = True,
vanderCoeffs : DictAny = {}):
support = checkParameterList(support)[0]
self.support = copy(support)
if "reorder" in vanderCoeffs.keys():
self.support = self.support[vanderCoeffs["reorder"]]
self.npar = support.shape[1]
if directionalWeights is None:
directionalWeights = np.ones(self.npar)
self.directionalWeights = directionalWeights
self.polybasis, self.radialbasis, _ = polybasis.split("_")
self.totalDegree = totalDegree
self.evalParams = vanderCoeffs
if totalDegree:
vander, _, _ = pvT(support, deg, self.polybasis, **vanderCoeffs)
if not hasattr(deg, "__len__"): deg = [deg] * self.npar
else:
if not hasattr(deg, "__len__"): deg = [deg] * self.npar
vander = pv(support, deg, self.polybasis, **vanderCoeffs)
self.degree = deg
self.localProjector = vander.T.conj()
self.localVanders = np.array([np.outer(van, van.conj()) \
for van in vander])
self.localVanders = np.swapaxes(self.localVanders, 0, 2)
self.suppValues = np.array(values)

Event Timeline