/* * Copyright (c) 2011-2015 EPFL DATA Laboratory * Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE) * * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ch.epfl.data.squall.ewh.algorithms; import ch.epfl.data.squall.ewh.algorithms.optimality.WeightFunction; import ch.epfl.data.squall.ewh.data_structures.Region; import ch.epfl.data.squall.ewh.data_structures.SimpleMatrix; // p^2 points of rounded matrix precomputed // coordinates of a region are coarsened // kind of densePrecomputation public class PWeightPrecomputation implements WeightPrecomputation { private WeightFunction _wf; private ShallowCoarsener _coarsener; // p^2 is for last point in each 2D // bucket from _sc (pxp matrix) private int[][] _prefixSum; private int _xSize, _ySize; // dimensions of the prefixSum int[][] public PWeightPrecomputation(WeightFunction wf, ShallowCoarsener sc, WeightPrecomputation samplePrecomputation) { _wf = wf; _coarsener = sc; _xSize = _coarsener.getNumXCoarsenedPoints(); _ySize = _coarsener.getNumYCoarsenedPoints(); _prefixSum = new int[_xSize][_ySize]; precomputePSquare(samplePrecomputation); } @Override public WeightFunction getWeightFunction() { return _wf; } @Override public int getXSize() { return _xSize; } @Override public int getYSize() { return _ySize; } // no need for further optimizations, because p is rather small // samplePrecomputation: n_s x n_s precomputation (possibly monotonic) private void precomputePSquare(WeightPrecomputation samplePrecomputation) { for (int ci = 0; ci < _xSize; ci++) { int i = _coarsener.getOriginalXCoordinate(ci, true); for (int cj = 0; cj < _ySize; cj++) { int j = _coarsener.getOriginalYCoordinate(cj, true); int prefix = samplePrecomputation.getPrefixSum(i, j); _prefixSum[ci][cj] = prefix; } } } public void addDeltaMatrix(SimpleMatrix deltaMatrix) { // compute prefix sum of the delta matrix DenseWeightPrecomputation deltaWP = new DenseWeightPrecomputation(_wf, deltaMatrix); // add the delta prefix sum to our prefix sum for (int i = 0; i < _xSize; i++) { for (int j = 0; j < _ySize; j++) { _prefixSum[i][j] += deltaWP.getPrefixSum(i, j); } } } @Override public int getPrefixSum(int coarsenedX, int coarsenedY) { if (coarsenedX < 0 || coarsenedY < 0) { return 0; } else { // both joinMatrix and prefixSum with originalToCoarsened // translation proved time-inefficient return _prefixSum[coarsenedX][coarsenedY]; } } // this is an exception: Region is an originalRegion!!!!!!!!!!!! // this is not a bottleneck (isEmpty is), and if we did not want to put many // "if (SystemParameters.COARSE_PRECOMPUTATION)"s all around the code @Override public double getWeight(Region originalRegion) { Region coarsenedRegion = _coarsener .translateOriginalToCoarsenedRegion(originalRegion); return _wf.getWeight(originalRegion.getHalfPerimeter(), getFrequency(coarsenedRegion)); } @Override public int getFrequency(Region region) { int corner0x = region.getCorner(0).get_x() - 1; int corner0y = region.getCorner(0).get_y() - 1; int corner1x = region.getCorner(1).get_x() - 1; int corner1y = region.getCorner(1).get_y(); int corner2x = region.getCorner(2).get_x(); int corner2y = region.getCorner(2).get_y() - 1; int corner3x = region.getCorner(3).get_x(); // this point is inclusive int corner3y = region.getCorner(3).get_y(); return getPrefixSum(corner3x, corner3y) - getPrefixSum(corner2x, corner2y) - getPrefixSum(corner1x, corner1y) + getPrefixSum(corner0x, corner0y); } // this was the motivation for using coarsened representation // this dominates the whole execution as it is invoked from // Region.minimizeToNotEmptyCoarsened // which is invoked for each splitter within a rectangle in BSP @Override public boolean isEmpty(Region region) { return getFrequency(region) == 0; } @Override public int getTotalFrequency() { return getPrefixSum(_xSize - 1, _ySize - 1); } @Override public int getMinHalfPerimeterForWeight(double maxWeight) { throw new RuntimeException("Not implemented for now!"); } @Override public String toString() { return _wf.toString(); } }