def project(grid, dims): """ Project all grid points to the given dimensions @param grid: Grid sparse grid @param dims: list dimensions to which the grid points are projected """ gs = grid.getStorage() # create a new empty grid dim = len(dims) gps = [None] * gs.getSize() # run over all grid points in grid and # project them to the dimensions dims for i in range(gs.getSize()): gp = gs.getPoint(i) ngp = HashGridPoint(dim) # copy level index to new grid point for k, d in enumerate(dims): ngp.set(k, gp.getLevel(d), gp.getIndex(d)) # insert it to the new grid gps[i] = ngp # compute new basis ngrid = createGrid(grid, len(dims)) basis = getBasis(ngrid) return gps, basis
def findIntersectionsOfOverlappingSuppportsForOneGridPoint( self, gpi, gpsj, overlap, grid): numDims = gpi.getDimension() gs = grid.getStorage() # find all possible intersections of grid points comparisonCosts = 0 for j, gpj in list(gpsj.items()): if not isHierarchicalAncestor(gpi, gpj): comparisonCosts += 1 if haveOverlappingSupport(gpi, gpj): levelOuter, indexOuter = self.findOuterIntersection( gpi, gpj) if (levelOuter, indexOuter) not in overlap: gpOuterIntersection = HashGridPoint(self.numDims) for idim in range(self.numDims): gpOuterIntersection.set(idim, levelOuter[idim], indexOuter[idim]) # TODO: this might not be correct # -> it does work for a few test cases but this might # be a coincidence # if not gs.isContaining(gpOuterIntersection): overlap[levelOuter, indexOuter] = gpi, gpj, gpOuterIntersection return comparisonCosts
def transformToReferenceGrid(self, globalGrid): # 1. set the root node of the local grid localRoot = {'level': self.level, 'index': self.index} # 2. shift and scale the global grid to the local one localGrid = {} locallevels = np.ndarray(self.numDims, dtype="int") localindices = np.ndarray(self.numDims, dtype="int") for levelsGlobal, indicesGlobal in list(globalGrid.keys()): gpdd = HashGridPoint(self.numDims) for idim in range(self.numDims): lg, ig = levelsGlobal[idim], indicesGlobal[idim] llroot, ilroot = localRoot['level'][idim], localRoot['index'][ idim] # compute level and index of local grid # 1 -> level index of global root node, always the same locallevels[idim] = int(lg + (llroot - 1)) localindices[idim] = int(ig + (ilroot - 1) * 2**(lg - 1)) gpdd.set(idim, locallevels[idim], localindices[idim]) localGrid[(tuple(locallevels), tuple(localindices))] = gpdd return localGrid
def lookupFullGridPointsRec1d(self, grid, alpha, gp, d, p, opEval, maxLevel, acc): gs = grid.getStorage() level, index = gp.getLevel(d), gp.getIndex(d) # if the function value for the left child # is negtive, then add it with all its # hierarchical ancestors gp.getLeftChild(d) gp.getStandardCoordinates(p) if opEval.eval(alpha, p) < 0: acc.append(HashGridPoint(gp)) if level + 1 < maxLevel: self.lookupFullGridPointsRec1d(grid, alpha, gp, d, p, opEval, maxLevel, acc) # if the function value for the right child # is negtive, then add it with all its # hierarchical ancestors gp.set(d, level, index) gp.getRightChild(d) gp.getStandardCoordinates(p) if opEval.eval(alpha, p) < 0: acc.append(HashGridPoint(gp)) # store them for next round if level + 1 < maxLevel: self.lookupFullGridPointsRec1d(grid, alpha, gp, d, p, opEval, maxLevel, acc) # reset the grid point gp.set(d, level, index)
def copy(localFullGrid): numDims = localFullGrid.numDims gp = HashGridPoint(numDims) for idim in range(numDims): gp.set(idim, localFullGrid.level[idim], localFullGrid.index[idim]) fullGrid = LocalFullGrid(localFullGrid.grid, gp, np.array(localFullGrid.fullGridLevels)) return fullGrid
def computeCandidates(self, sortedOverlap, localFullGridLevels, grid, alpha): # create full grid locally gs = grid.getStorage() maxLevel = gs.getMaxLevel() ans = {} costs = 0 while len(sortedOverlap) > 0: numLocalGridPoints, levels, indices, (ranges, gpi, gpj) = sortedOverlap.pop() # do not consider intersection if it is already part of the local grid # -> TODO: if an intersection is already part of some other local grid # then there exists an ancestor in the list of intersections. # Check first if there are ancestors available and if yes, # remove the successor node from the intersection list if (levels, indices) not in ans: globalGrid = self.computeAnisotropicFullGrid( levels, indices, localFullGridLevels[levels, indices]) costs += len(globalGrid) assert numLocalGridPoints == len(globalGrid) # 1. set the root node of the local grid localRoot = {'level': levels, 'index': indices} # 2. shift and scale the global grid to the local one localGrid = {} levels = [None] * self.numDims indices = [None] * self.numDims for levelsGlobal, indicesGlobal in list(globalGrid.keys()): gpdd = HashGridPoint(self.numDims) for idim in range(self.numDims): lg, ig = levelsGlobal[idim], indicesGlobal[idim] llroot, ilroot = localRoot['level'][idim], localRoot[ 'index'][idim] # compute level and index of local grid # 1 -> level index of global root node, always the same levels[idim] = int(lg + (llroot - 1)) indices[idim] = int(ig + (ilroot - 1) * 2**(lg - 1)) gpdd.set(idim, levels[idim], indices[idim]) if not gs.isContaining(gpdd): localGrid[(tuple(levels), tuple(indices))] = gpdd if self.plot and self.numDims == 2: self.plotDebug(grid, alpha, localGrid, gpi, gpj, ans) assert len(localGrid) > 0 oldSize = len(ans) ans.update(localGrid) assert len(ans) > oldSize return list(ans.values()), costs
def parent(grid, gp, d): # get parent level = gp.getLevel(d) - 1 index = gp.getIndex(d) / 2 + ((gp.getIndex(d) + 1) / 2) % 2 if isValid1d(grid, level, index): # create parent ans = HashGridPoint(gp) ans.set(d, level, index) return ans return None
def findIntersections(self, grid, currentSubspaces): gs = grid.getStorage() numDims = gs.getDimension() maxLevel = gs.getMaxLevel() subspaces = np.vstack(list(currentSubspaces.keys())) costs = 0 # enumerate all the available subspaces in the grid intersections = {} alreadyChecked = {} gpintersection = HashGridPoint(numDims) level, index = np.ndarray(numDims, dtype="int"), np.ndarray(numDims, dtype="int") while len(currentSubspaces) > 0: nextSubspaces = {} levels = list(currentSubspaces.keys()) for i in range(len(levels)): levelk = levels[i] gpsk = currentSubspaces[levelk] for j in range(i + 1, len(levels)): levell = levels[j] gpsl = currentSubspaces[levell] for gpk in gpsk: for gpl in gpsl: if haveOverlappingSupportByLevelIndex(gpk, gpl) and \ not haveHierarchicalRelationshipByLevelIndex(gpk, gpl): # compute intersection self.findIntersection(gpintersection, (level, index), gpk, gpl) tlevel, tindex = tuple(level), tuple(index) if (tlevel, tindex) not in intersections: intersections[tlevel, tindex] = HashGridPoint( gpintersection) if (tlevel, tindex) not in alreadyChecked: alreadyChecked[tlevel, tindex] = True if tlevel not in nextSubspaces: nextSubspaces[tlevel] = [(tlevel, tindex)] else: nextSubspaces[tlevel].append( (tlevel, tindex)) costs += 1 currentSubspaces = nextSubspaces return list(intersections.values()), costs
def insertTruncatedBorder(grid, gp): """ insert points on the border recursively for grids with border @param grid: Grid @param gp: HashGridPoint @return: list of HashGridPoint, contains all the newly added grid points """ gs = grid.getStorage() gps = [gp] numDims = gp.getDimension() ans = [] while len(gps) > 0: gpi = gps.pop() for d in range(numDims): # right border in d rgp = HashGridPoint(gpi) rgp.getRightLevelZero(d) # insert the point if not gs.isContaining(rgp): added_grid_points = insertPoint(grid, rgp) if len(added_grid_points) > 0: ans += added_grid_points gps.append(rgp) # left border in d lgp = HashGridPoint(gpi) lgp.getLeftLevelZero(d) # insert the point if not gs.isContaining(lgp): added_grid_points = insertPoint(grid, lgp) if len(added_grid_points) > 0: ans += added_grid_points gps.append(lgp) return ans
def balance(grid): gs = grid.getStorage() newgps = [] for gp in [gs.getPoint(i) for i in range(gs.getSize())]: for dim in range(gs.getDimension()): # left child in dimension dim lgp = HashGridPoint(gp) lgp.getLeftChild(dim) # right child in dimension dim rgp = HashGridPoint(gp) rgp.getRightChild(dim) if gs.isContaining(lgp) and not gs.isContaining(rgp): inserted = insertPoint(grid, rgp) elif gs.isContaining(rgp) and not gs.isContaining(lgp): inserted = insertPoint(grid, lgp) else: inserted = [] newgps += inserted gs.recalcLeafProperty() return newgps
def findCandidates(self, grid, alpha): gs = grid.getStorage() candidates = {} # lookup dimension-wise for d in range(gs.getDimension()): # compute starting points by level sum anchors = [] for i in range(gs.getSize()): accLevel = gs.getPoint(i).getLevel(d) if accLevel == 1: anchors.append(i) while len(anchors) > 0: # get next starting node ix = anchors.pop(0) gp = gs.getPoint(ix) acc = [] self.findCandidatesSweep1d(d, gp, alpha, grid, acc, False) # store candidates for gp in acc: ix = gs.getSequenceNumber(gp) if ix not in candidates: candidates[ix] = HashGridPoint(gp) return list(candidates.values())
def findCandidates(self, grid, alpha, addedGridPoints): """ collect all leaf nodes with at least one negative hierarchical ancestor """ # collect all leaf nodes with at least one negative hierarchical # ancestor refinementCandidates = [] gs = grid.getStorage() numDims, numGridPoints = gs.getDimension(), gs.getSize() maxLevel = gs.getMaxLevel() self.costs = 0 if self.iteration == 0: candidates = [] for i in range(numGridPoints): self.costs += 1 gp = gs.getPoint(i) if alpha[i] < 0.0: candidates.append(HashGridPoint(gp)) self.minLevelSum = min(self.minLevelSum, gp.getLevelSum()) self.maxLevelSum = max(self.maxLevelSum, gp.getLevelSum()) # refine all the grid points up to the maximum level sum # -> let the search progressing uniformly such that # we look at grid points with the same level sum at most once # to achieve the minimum amount of grid points # this corresponds basically to the search of all leaf nodes with # an ancestor of negative coefficient refinementCandidates = [] for gp in candidates: diff = self.maxLevelSum - gp.getLevelSum() if diff == 0: refinementCandidates.append(gp) else: newCandidates = [gp] for i in range(diff): while len(newCandidates) > 0: candidate = newCandidates.pop() children = self.getAllChildrenNodesUpToMaxLevel( candidate, maxLevel, grid) for childCandidate in list(children.values()): if childCandidate.getLevelSum( ) == self.maxLevelSum: refinementCandidates.append(childCandidate) elif childCandidate.getLevelSum( ) < self.maxLevelSum: newCandidates.append(childCandidate) else: refinementCandidates = list(self.newCandidates.values()) self.newCandidates = {} self.candidates = [] for gp in refinementCandidates: children = self.getAllChildrenNodesUpToMaxLevel(gp, maxLevel, grid) for (level, index), ngp in list(children.items()): if (level, index) not in self.newCandidates: if not gs.isContaining(ngp): self.candidates.append(ngp) self.newCandidates[level, index] = ngp
def checkPositivity(grid, alpha): # define a full grid of maxlevel of the grid gs = grid.getStorage() fullGrid = Grid.createLinearGrid(gs.getDimension()) fullGrid.getGenerator().full(gs.getMaxLevel()) fullHashGridStorage = fullGrid.getStorage() A = np.ndarray( (fullHashGridStorage.getSize(), fullHashGridStorage.getDimension())) p = DataVector(gs.getDimension()) for i in range(fullHashGridStorage.getSize()): fullHashGridStorage.getCoordinates(fullHashGridStorage.getPoint(i), p) A[i, :] = p.array() negativeGridPoints = {} res = evalSGFunctionMulti(grid, alpha, A) ymin, ymax, cnt = 0, -1e10, 0 for i, yi in enumerate(res): # print( A[i, :], yi ) if yi < -1e-11: cnt += 1 negativeGridPoints[i] = yi, HashGridPoint( fullHashGridStorage.getPoint(i)) ymin = min(ymin, yi) ymax = max(ymax, yi) # print( " %s = %g" % (A[i, :], yi) ) if cnt > 0: print("warning: function is not positive") print("%i/%i: [%g, %g]" % (cnt, fullHashGridStorage.getSize(), ymin, ymax)) return negativeGridPoints
def getAllChildrenNodesUpToMaxLevel(self, gp, maxLevel, grid): children = {} gs = grid.getStorage() for idim in range(gp.getDimension()): if gp.getLevel(idim) < maxLevel: self.costs += 1 gpl = HashGridPoint(gp) gp.getLeftChild(idim) level, index = tuple(getLevel(gpl)), tuple(getIndex(gpl)) children[level, index] = gpl # get right child self.costs += 1 gpr = HashGridPoint(gp) gpr.getRightChild(idim) level, index = tuple(getLevel(gpr)), tuple(getIndex(gpr)) children[level, index] = gpr return children
def getMaxLevelOfChildrenUpToMaxLevel(self, gp, grid, idim): gs = grid.getStorage() children = [] gps = [gp] while len(gps) > 0: currentgp = gps.pop() children.append(getLevel(currentgp)) if currentgp.getLevel(idim) < self.maxLevel: gpl = HashGridPoint(currentgp) gpl.getLeftChild(idim) if gs.isContaining(gpl): gps.append(gpl) # get right child gpr = HashGridPoint(currentgp) gs.right_child(gpr, idim) if gs.isContaining(gpr): gps.append(gpr) return children
def extend_grid_1d(grid, *args, **kws): gs = grid.getStorage() accLevel = gs.getMaxLevel() dim = gs.getDimension() # create dim+1 dimensional grid of level 0 new_grid = createGrid(grid, dim + 1, *args, **kws) # create 1 dimensional reference grid of level accLevel ref_grid = createGrid(grid, 1) ref_grid.getGenerator().regular(accLevel) # == full grid in dim = 1 ref_gs = ref_grid.getStorage() # create cross product between the 1d and the dimd-grid for i in range(gs.getSize()): gp = gs.getPoint(i) new_gp = HashGridPoint(dim + 1) # copy level index vectors from old grid to the new one for d in range(gs.getDimension()): new_gp.set(d, gp.getLevel(d), gp.getIndex(d)) # get the indices in the missing dimension for j in range(ref_gs.getSize()): ref_gp = ref_gs.getPoint(j) new_gp.set(dim, ref_gp.getLevel(0), ref_gp.getIndex(0)) insertPoint(new_grid, new_gp) return new_grid
def hasChildren(grid, gp): gs = grid.getStorage() d = 0 gpn = HashGridPoint(gp) while d < gs.getDimension(): # load level index level, index = gp.getLevel(d), gp.getIndex(d) # check left child in d gp.getLeftChild(d) if gs.isContaining(gpn): return True # check right child in d gp.set(d, level, index) gp.getRightChild(d) if gs.isContaining(gpn): return True gpn.set(d, level, index) d += 1 return False
def projectList(gps, dims): """ Project all grid points to the given dimensions @param gps: list of grid points @param dims: list dimensions to which the grid points are projected """ # create a new empty grid dim = len(dims) projected_gps = [None] * len(gps) # run over all grid points in grid and # project them to the dimensions dims for i, gp in enumerate(gps): projected_gp = HashGridPoint(dim) # copy level index to new grid point for k, d in enumerate(dims): projected_gp.set(k, gp.getLevel(d), gp.getIndex(d)) # insert it to the list of projected grid points projected_gps[i] = projected_gp return projected_gps
def addChildren(self, grid, gp): gs = grid.getStorage() for d in range(gs.getDimension()): # check left child in d gpl = HashGridPoint(gp) gpl.getLeftChild(d) if not gs.isContaining(gpl) and isValid(grid, gpl) and \ self.checkRange(gpl, self.maxLevel): self.addCollocationNode(grid, gpl) # check right child in d gpr = HashGridPoint(gp) gpr.getRightChild(d) if not gs.isContaining(gpr) and isValid(grid, gpr) and \ self.checkRange(gpr, self.maxLevel): self.addCollocationNode(grid, gpr)
def findCandidates(self, grid, alpha, addedGridPoints): fullGridStorage = self.fullGrid.getStorage() gs = grid.getStorage() if self.iteration == 0: self.costs += fullGridStorage.getSize() elif len(addedGridPoints) == 0: return opEval = createOperationEval(grid) for i in range(fullGridStorage.getSize()): gp = fullGridStorage.getPoint(i) if not gs.isContaining(gp): self.candidates.append(HashGridPoint(gp))
def isRefineable(grid, gp): gs = grid.getStorage() for d in range(gs.getDimension()): # left child in dimension dim gpl = HashGridPoint(gp) gpl.getLeftChild(d) if not gs.isContaining(gpl) and isValid(grid, gpl): return True # right child in dimension dim gpr = HashGridPoint(gp) gpr.getRightChild(d) if not gs.isContaining(gpr) and isValid(grid, gpr): return True return False
def findIntersectionsOfOverlappingSuppportsForOneGridPoint( self, i, gpi, gpsj, overlap, grid, alpha): numDims = gpi.getDimension() gs = grid.getStorage() gpintersection = HashGridPoint(self.numDims) # find all possible intersections of grid points comparisonCosts = fullGridCosts = 0 for j, gpj in list(gpsj.items()): comparisonCosts += 1 idim = 0 ranges = [] while idim < numDims: # get level index lid, iid = gpi.getLevel(idim), gpi.getIndex(idim) ljd, ijd = gpj.getLevel(idim), gpj.getIndex(idim) # check if they have overlapping support xlowi, xhighi = getBoundsOfSupport(lid, iid) xlowj, xhighj = getBoundsOfSupport(ljd, ijd) xlow = max(xlowi, xlowj) xhigh = min(xhighi, xhighj) # different level but not ancestors if xlow >= xhigh: break else: ranges.append([xlow, xhigh]) idim += 1 # check whether the supports are overlapping # in all dimensions if idim == numDims: ancestors_gpj = [(0, gpj)] + getHierarchicalAncestors( grid, gpj) for _, ancestor_gpj in ancestors_gpj: fullGridCosts += 1 level, index = self.findIntersection(gpi, ancestor_gpj) gpintersection = HashGridPoint(self.numDims) for idim in range(self.numDims): gpintersection.set(idim, level[idim], index[idim]) if not gs.isContaining(gpintersection): if self.plot and self.numDims == 2: self.plotDebug(grid, alpha, {1: gpintersection}, gpi, gpj, overlap) overlap[level, index] = gpintersection return comparisonCosts, fullGridCosts
def insert_children(grid, gp, d): cnt = [] gs = grid.getStorage() # left child in dimension dim gpl = HashGridPoint(gp) gpl.getLeftChild(d) if not gs.isContaining(gpl) and isValid(grid, gpl): success = gs.insert(gpl) > -1 cnt += 1 if success else 0 # right child in dimension dim gpr = HashGridPoint(gp) gpr.getRightChild(d) if not gs.isContaining(gpr) and isValid(grid, gpr): success = gs.insert(gpr) > -1 cnt += 1 if success else 0 return cnt
def insertPoint(grid, gp): """ insert a grid point to the storage if it is valid. Returns the sequence number of the new grid point in the storage """ gs = grid.getStorage() if gs.isContaining(gp) or not isValid(grid, gp): return [] added_grid_points = SizeVector() gs.insert(HashGridPoint(gp), added_grid_points) > -1 ans = [] for i in added_grid_points: ans.append(gs.getPoint(i)) return ans
def copyGrid(grid, level=0, deg=1): # create new grid gs = grid.getStorage() dim = gs.getDimension() newGrid = createGrid(grid, dim, deg) if level > 0: newGrid.getGenerator().regular(level) newGs = newGrid.getStorage() # insert grid points for i in range(gs.getSize()): gp = gs.getPoint(i) # insert grid point if not newGs.isContaining(gp): newGs.insert(HashGridPoint(gp)) newGs.recalcLeafProperty() return newGrid
def refine(self, grid, gp): ans = [] gs = grid.getStorage() for d in range(gs.getDimension()): gpl = HashGridPoint(gp) gpl.getLeftChild(d) if isValid(grid, gpl): ans += insertPoint(grid, gpl) if hasBorder(grid.getType()): ans += insertTruncatedBorder(grid, gpl) gpr = HashGridPoint(gp) gpr.getRightChild(d) if isValid(grid, gpr): ans += insertPoint(grid, gpr) if hasBorder(grid.getType()): ans += insertTruncatedBorder(grid, gpr) gs.recalcLeafProperty() return ans
def getLocalMaxLevel(self, dup, levels, indices, grid): gp = HashGridPoint(self.numDims) for idim, (level, index) in enumerate(zip(levels, indices)): gp.set(idim, level, index) # up in direction d to the root node diffLevels = np.zeros(self.numDims) for idim in range(self.numDims): # search for children # as long as the corresponding grid point exist in the grid gp.set(idim, 1, 1) if self.verbose: print(" %i: root (%i) = %s" % (dup, idim, (tuple(getLevel(gp)), tuple(getIndex(gp)), tuple([gp.getCoord(i) for i in range(self.numDims)])))) currentgp = HashGridPoint(gp) diffLevels[idim] = self.getMaxLevelOfChildrenUpToMaxLevel( currentgp, grid, idim) return diffLevels
def test_freeRefineSubspaceIsotropic(self): """Refine the isotropic middle subspace""" alpha = DataVector(self.grid.getSize()) alpha.setAll(1.0) for i in [13, 14, 15, 16]: alpha[i] = 2. #refinement stuff refinement = HashRefinement() decorator = SubspaceRefinement(refinement) # refine a single grid point each time functor = SurplusRefinementFunctor(alpha, 1) decorator.free_refine(self.HashGridStorage, functor) for i in range(self.grid.getSize()): HashGridPoint = self.HashGridStorage.getPoint(i) self.assertEqual(self.grid.getSize(), 33) for i in range(self.grid.getSize()): HashGridPoint = self.HashGridStorage.getPoint(i) levelIndex = eval(HashGridPoint.toString()) self.assertFalse(levelIndex[0] == 4 or levelIndex[2] == 4)
def split(self, idim): # split the current grid up into three new ones gs = self.grid.getStorage() # central grid centralFullGrid = LocalFullGrid.copy(self) centralFullGrid.fullGridLevels[idim] = 1 # left grid gpLeft = HashGridPoint(self.gp) gpLeft.getLeftChild(idim) fullGridLevels = np.array(self.fullGridLevels) fullGridLevels[idim] -= 1 leftFullGrid = LocalFullGrid(self.grid, gpLeft, fullGridLevels) # right grid gpRight = HashGridPoint(self.gp) gpRight.getRightChild(idim) fullGridLevels = np.array(self.fullGridLevels) fullGridLevels[idim] -= 1 rightFullGrid = LocalFullGrid(self.grid, gpRight, fullGridLevels) return centralFullGrid, leftFullGrid, rightFullGrid
def getLocalMaxLevel(self, dup, levels, indices, grid): gp = HashGridPoint(self.numDims) for idim, (level, index) in enumerate(zip(levels, indices)): gp.set(idim, level, index) # up in direction d to the root node gp.set(dup, 1, 1) # down as far as possible in direction d + 1 mod D ddown = (dup + 1) % self.numDims # search for children # as long as the corresponding grid point exist in the grid children = self.getMaxLevelOfChildrenUpToMaxLevel(gp, grid, ddown) maxLevel = int(max(1, np.max(children))) return maxLevel, ddown