Page MenuHomec4science

piecewise_linear_interpolator.py
No OneTemporary

File Metadata

Created
Sat, May 11, 16:44

piecewise_linear_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.poly_fitting.interpolator import GenericInterpolator
from rrompy.utilities.poly_fitting.custom_fit import customFit
from .kernel import vander, val
from rrompy.utilities.numerical import dot
from rrompy.utilities.exception_manager import RROMPyException, RROMPyAssert
from rrompy.parameter import checkParameterList
__all__ = ['PiecewiseLinearInterpolator']
class PiecewiseLinearInterpolator(GenericInterpolator):
def __init__(self, other = None):
if other is None: return
self.support = other.support
self.lims = other.lims
self.coeffs = other.coeffs
self.depths = other.depths
self.npar = other.npar
self.kind = other.kind
@property
def shape(self):
sh = self.coeffs.shape[1 :] if self.coeffs.ndim > 1 else 1
return sh
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 piecewise "
"linear function."))
return val(mu, self.coeffs, self.support, self.depths, self.kind,
self.lims)
def __copy__(self):
return RadialBasisInterpolator(self)
def __deepcopy__(self, memo):
other = RadialBasisInterpolator()
(other.support, other.lims, other.coeffs, other.depths, other.npar,
other.kind) = copy((self.support, self.lims, self.coeffs, self.depths,
self.npar, self.kind), memo)
return other
def postmultiplyTensorize(self, A:Np2D):
RROMPyAssert(A.shape[0], self.shape[-1], "Shape of output")
self.coeffs = dot(self.coeffs, A)
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.coeffs = np.pad(self.coeffs, padwidth, "constant",
constant_values = (0., 0.))
padwidth = [(0, 0)] * (self.npar - 1) + padwidth
def setupByInterpolation(self, support:paramList, values:ListAny,
lims:paramList, depths:Np2D,
kind : str = "UNIFORM", verbose : bool = True,
fitCoeffs : DictAny = {}):
support = checkParameterList(support)[0]
self.support = copy(support)
self.npar = support.shape[1]
lims = checkParameterList(lims, self.npar)[0]
self.lims = copy(lims)
self.depths = copy(depths)
self.kind = kind
values = values.reshape(values.shape[0], -1)
van = vander(support, depths, kind, lims)
fitOut = customFit(van, values, full = True, **fitCoeffs)
if verbose:
msg = ("Fitting {} samples through piecewise linear "
"interpolator... Conditioning of system: {:.4e}.").format(
len(support), fitOut[1][2][0] / fitOut[1][2][-1])
else: msg = None
self.coeffs = fitOut[0]
return fitOut[1][1] == van.shape[1], msg

Event Timeline