package at.demo.optimization.model; import java.io.Serializable; import java.util.List; /** * This class holds an numeric interval. * It is not general purpose (yet) and only solves very * specific problem in the optimization area. * * @author demo * */ public class NumericInterval implements Serializable, Comparable { private static final long serialVersionUID = 7771510784144574442L; private final int lower; private final int upper; public NumericInterval(int lower, int upper) { if (upper - lower < 0) { throw new IllegalStateException("Interval has to be length > 0"); } this.lower = lower; this.upper = upper; } /** * returns the lower value of the interval * @return */ public int getLower() { return this.lower; } /** * returns the upper value of the interval * @return */ public int getUpper() { return this.upper; } /** * checks if intervals overlap. * * @param interval * @return */ public boolean overlaps(NumericInterval interval) { int thisStart = getLower(); int thisEnd = getUpper(); if (interval == null) { return false; } else { int otherStart = interval.getLower(); int otherEnd = interval.getUpper(); return (thisStart < otherEnd && otherStart < thisEnd); } } /** * returns the overlapping interval * * @param interval * @return */ public NumericInterval overlap(NumericInterval interval) { if (!overlaps(interval)) { return null; } int start = Math.max(getLower(), interval.getLower()); int end = Math.min(getUpper(), interval.getUpper()); return new NumericInterval(start, end); } public boolean containsAny(List intervals) { boolean retval = false; for (NumericInterval interval : intervals) { if (contains(interval)) { retval = true; break; } } return retval; } public boolean containsAnyRate(List rates) { boolean retval = false; for (Integer rate : rates) { if (contains(rate)) { retval = true; break; } } return retval; } /** * is the interval contained? * * @param interval * @return */ public boolean contains(NumericInterval interval) { if (interval == null) { return false; } int otherStart = interval.getLower(); int otherEnd = interval.getUpper(); int thisStart = getLower(); int thisEnd = getUpper(); return (thisStart <= otherStart && otherStart < thisEnd && otherEnd <= thisEnd); } public boolean contains(Integer num) { if (num == null) { return false; } int other = num; int thisStart = getLower(); int thisEnd = getUpper(); return (thisStart <= other && other <= thisEnd); } /** * the the gap interval * * @param interval * @return */ public NumericInterval gap(NumericInterval interval) { int otherStart = interval.getLower(); int otherEnd = interval.getUpper(); int thisStart = getLower(); int thisEnd = getUpper(); if (thisStart > otherEnd) { return new NumericInterval(otherEnd+1, thisStart-1); } else if (otherStart > thisEnd) { return new NumericInterval(thisEnd+1, otherStart-1); } else { return null; } } /** * do the intervals "touch" but not overlap? * @param interval * @return */ public boolean abuts(NumericInterval interval) { if (interval == null) { return false; } else { return (interval.getUpper()+1 == getLower() || getUpper()+1 == interval.getLower()); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + lower; result = prime * result + upper; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; NumericInterval other = (NumericInterval) obj; if (lower != other.lower) return false; if (upper != other.upper) return false; return true; } @Override public String toString() { return "NumericInterval [lower=" + lower + ", upper=" + upper + "]"; } /** * we compare the lower value on the interval only */ @Override public int compareTo(NumericInterval o1) { if (lower < o1.lower) { return -1; } if (lower > o1.lower) { return 1; } return 0; } }