Page MenuHomec4science

sparse_grid_sampler.py
No OneTemporary

File Metadata

Created
Wed, May 29, 16:26

sparse_grid_sampler.py

# Copyright (C) 2018-2020 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/>.
#
from copy import deepcopy as copy
from itertools import product
import numpy as np
from rrompy.parameter.parameter_sampling.generic_sampler import GenericSampler
from rrompy.utilities.poly_fitting.piecewise_linear import (sparsekinds,
sparseMap)
from rrompy.utilities.base.types import Tuple, List, Np1D, DictAny, paramList
from rrompy.utilities.exception_manager import RROMPyException
__all__ = ['SparseGridSampler']
class SparseGridSampler(GenericSampler):
"""Generator of sparse grid sample points."""
def __init__(self, lims:paramList, kind : str = "UNIFORM",
parameterMap : DictAny = 1.):
super().__init__(lims = lims, parameterMap = parameterMap)
self.kind = kind
self.reset()
def __str__(self) -> str:
return "{}[{}_{}]_{}".format(self.name(), self.lims[0],
self.lims[1], self.kind)
@property
def npoints(self):
"""Number of points."""
return len(self.points)
@property
def kind(self):
"""Value of kind."""
return self._kind
@kind.setter
def kind(self, kind):
if kind.upper() not in [sk.split("_")[2] + extra for sk, extra in
product(sparsekinds, ["", "-HAAR"])]:
raise RROMPyException("Generator kind not recognized.")
self._kind = kind.upper()
self._noBoundary = "HAAR" in self._kind
def reset(self):
limsE = self.mapParameterList(self.lims)
centerEff = .5 * (limsE[0] + limsE[1])
self.points = self.mapParameterList(centerEff, "B")
self.depth = np.array([[self._noBoundary] * self.npar], dtype = int)
def refine(self, active : List[int] = None) -> Tuple[List[int], List[int]]:
if active is None: active = np.arange(self.npoints)
active = np.array(active)
if np.any(active < 0) or np.any(active >= self.npoints):
raise RROMPyException(("Active indices must be between 0 "
"(included) and npoints (excluded)."))
newIdxs, oldIdxs = [], []
for act in active:
point, dpt = self.points[act], self.depth[act]
for jdelta, signdelta in product(range(self.npar), [-1., 1.]):
idx = self.addForwardPoint(point, dpt, jdelta, signdelta)
if idx is not None:
if idx > 0: newIdxs += [idx]
elif - idx not in newIdxs: oldIdxs += [- idx]
return newIdxs, oldIdxs
def addForwardPoint(self, basepoint:Np1D, basedepth:Np1D, index:int,
sign:float) -> int:
if basedepth[index] < self._noBoundary:
return None #makeshift skip for wrong boundary points at lvl 1
limd = self.mapParameterList(self.lims(index), idx = [index])(0)
xd0 = sparseMap(self.mapParameterList(basepoint[index],
idx = [index])(0, 0),
limd, self.kind, False) + .5 ** basedepth[index] * sign
if np.abs(xd0) >= 1. + 1e-15 * (1 - 2 * self._noBoundary):
return None #point out of bounds
pt = copy(basepoint)
pt[index] = self.mapParameterList(sparseMap(xd0, limd, self.kind),
"B", [index])(0, 0)
dist = np.sum(np.abs(self.points.data - pt.reshape(1, -1)), axis = 1)
samePt = np.where(np.isclose(dist, 0., atol = 1e-15))[0]
if len(samePt) > 0: #point already exists
return - samePt[0]
self.points.append(pt)
self.depth = np.append(self.depth, [basedepth], 0)
self.depth[-1, index] += 1
return self.npoints - 1
def generatePoints(self, n:int, reorder = None) -> paramList:
if self.npoints > n: self.reset()
idx = np.arange(self.npoints)
while self.npoints < n: idx = self.refine(idx)[0]
return self.points

Event Timeline