@Override public boolean equals(Object thata) { // check for self-comparison if (this == thata) return true; // use instanceof instead of getClass here for two reasons // 1. if need be, it can match any supertype, and not just one class; // 2. it renders an explicit check for "that == null" redundant, since // it does the check for null already - "null instanceof [type]" always // returns false. (See Effective Java by Joshua Bloch.) if (!(thata instanceof Box)) return false; // Alternative to the above line : // if ( aThat == null || aThat.getClass() != this.getClass() ) return false; // cast to native object is now safe Box that = (Box) thata; // now a proper field-by-field evaluation can be made if (this.getDimension() != that.getDimension()) return false; if (!this.functionValue.equals(that.functionValue)) return false; for (int i = getDimension() - 1; i >= 0; i--) { if (!getInterval(i).equals(that.getInterval(i))) return false; } return true; }
/* * returns true if this box has at least one common edge point * with @box@. Used in screening by derivative in @Screener@ */ public boolean hasAtLeastOneCommonSide(Box box) { final int dim = getDimension(); assert (dim == box.getDimension()); for (int i = 0; i < dim; i++) { RealInterval a = this.getInterval(i); RealInterval b = box.getInterval(i); if (a.isIntersects(b)) return true; } return false; }
@Override public Box clone() { int dim = this.getDimension(); Box b = new Box(dim); for (int i = 0; i < dim; i++) { b.intervals[i] = (RealInterval) intervals[i].clone(); } b.functionValue = (RealInterval) functionValue.clone(); return b; }
/** * FIRST derivative A point could be a minimum or a maximum if and only if the derivative is equal * to zero in this point. Therefore interval extensions of all partial derivatives have to contain * zero. The only exception are border points. Consider the following case: f(x) = x, * min_{0<x<1}(f) = f(0), but f'(x) != 0. BUT instead of performing such checks each time we just * have to add all ages to the working list from the very beginning! Much simple and less code: ) * Because of this it doesn't screen out boxes with at least one side width = 0 */ protected boolean check1Derivative(Box box) { Function function = FunctionFactory.getTargetFunction(); for (int i = box.getDimension() - 1; i >= 0; --i) { // A workaround for edges. Worklist adds zero-width // edges for initial search area. // See Worklist.addAreaAndAllEges() if (box.getInterval(i).wid() == 0) { return true; } RealInterval f1d = function.calculate1Derivative(box, i); if (f1d == null) break; if (!f1d.contains(0)) return false; } return true; // check passed }
private Box[] splitSideByPoint(int sideNum, double cutPoint) { RealInterval side = getInterval(sideNum); assert (side.contains(cutPoint)); Box one = this.clone(); Box two = this.clone(); one.setFunctionValue(unset); // Flush function values. two.setFunctionValue(unset); // On new sub-boxes it is not calculated yet. RealInterval left = new RealInterval(side.lo(), cutPoint); RealInterval right = new RealInterval(cutPoint, side.hi()); one.setInterval(sideNum, left); two.setInterval(sideNum, right); Box result[] = {one, two}; return result; }
/* * in some cases we could suspect that some point inside the box is an optimum * that we are looking for. (For example when a point algorithm found it). * Than we want to check this. To do this we cut the box on a small box * around this point and everything else */ public Box[] cutOutBoxAroundThisPoint(double[] potentialOptPoint) { final double epsilon = 5e-4; final int dim = getDimension(); assert (potentialOptPoint.length == dim); if (!this.contains(potentialOptPoint)) { // probably it is due to rounding error and it is close // save original point for diagnostic double[] origPoint = potentialOptPoint.clone(); if (setToClosestAreaPoint(potentialOptPoint) < epsilon * dim) { // let it be "close enough" // continue } else { Box arr[] = new Box[1]; arr[0] = this; // possible bug. Lets fail in debug. See origPoint[]. assert (false); return arr; } } ArrayList<Box> parts = new ArrayList<>(); Box boxOfInterest = this; Box boxes[] = null; for (int i = 0; i < dim; i++) { double cutPoint = potentialOptPoint[i] - epsilon; if (boxOfInterest.getInterval(i).contains(cutPoint)) { boxes = boxOfInterest.splitSideByPoint(i, cutPoint); assert (boxes[1].contains(potentialOptPoint)); // "our" box is right parts.add(boxes[0]); boxOfInterest = boxes[1]; } cutPoint = potentialOptPoint[i] + epsilon; // < if (boxOfInterest.getInterval(i).contains(cutPoint)) { boxes = boxOfInterest.splitSideByPoint(i, cutPoint); assert (boxes[0].contains(potentialOptPoint)); // "our" box is left now parts.add(boxes[1]); boxOfInterest = boxes[0]; } } assert (boxOfInterest.contains(potentialOptPoint)); parts.add(boxOfInterest); return parts.toArray(new Box[parts.size()]); }
/** * Compare two Boxes for order. * * @return -1 if box1 has lower lo bound of function value than box2, 1 otherwise, 0 is returned * ONLY IF BOX ARE EQUALS!! otherwise TreeSet will treat all such boxes as equal items and * will keep only one of them!!!!!!!!!! */ @Override public int compare(Box b1, Box b2) { assert (b1.getDimension() == b2.getDimension()); if (b1 == b2) return 0; double lo1 = b1.getFunctionValue().lo(); double lo2 = b2.getFunctionValue().lo(); if (lo1 == lo2) { if (b1.equals(b2)) return 0; double hi1 = b1.getFunctionValue().hi(); double hi2 = b2.getFunctionValue().hi(); if (hi1 == hi2) { double sumWid1 = 0, sumWid2 = 0; for (int i = b1.getDimension() - 1; i >= 0; i--) { sumWid1 += b1.getInterval(i).wid(); sumWid2 += b2.getInterval(i).wid(); } if (sumWid1 == sumWid2) { // ok. everything is absolutely equals, but these boxes are different. // lets distinguish them somehow for (int i = b1.getDimension() - 1; i >= 0; i--) { if (b1.getInterval(i).lo() < b2.getInterval(i).lo() || b1.getInterval(i).hi() < b2.getInterval(i).hi()) return -1; if (b1.getInterval(i).lo() > b2.getInterval(i).lo() || b1.getInterval(i).hi() > b2.getInterval(i).hi()) return 1; } } else return sumWid1 > sumWid2 ? -1 : 1; // wider boxes goes first } else return hi1 > hi2 ? -1 : 1; // offer boxes with wider function estimation first } return (lo1 < lo2) ? -1 : 1; }