Commit 542d3891 authored by Lukas Jelonek's avatar Lukas Jelonek
Browse files

Wrote definitions for interval operations and adapted the...

Wrote definitions for interval operations and adapted the IntegerIntervalOperations to these definitions.
parent cc80fa4b
......@@ -24,6 +24,9 @@ public class IntegerIntervalOperations implements IntervalOperations<Integer> {
@Override
public boolean overlap(Interval<Integer> fst, Interval<Integer> snd) {
if (fst.isEmpty() || snd.isEmpty()) {
return false;
}
// normalize
fst = fst.as(Interval.Type.ZeroOpen);
snd = snd.as(Interval.Type.ZeroOpen);
......@@ -34,8 +37,7 @@ public class IntegerIntervalOperations implements IntervalOperations<Integer> {
snd = tmp;
}
return !(fst.getEnd() - 1 < snd.getStart());
return fst.equals(snd) || !(fst.getEnd() - 1 < snd.getStart());
}
@Override
......@@ -44,6 +46,10 @@ public class IntegerIntervalOperations implements IntervalOperations<Integer> {
fst = fst.as(Interval.Type.ZeroOpen);
snd = snd.as(Interval.Type.ZeroOpen);
if (overlap(fst, snd)) {
return false;
}
// sort by start
if (fst.getStart() > snd.getStart()) {
Interval<Integer> tmp = fst;
......@@ -51,7 +57,7 @@ public class IntegerIntervalOperations implements IntervalOperations<Integer> {
snd = tmp;
}
return fst.getEnd() == snd.getStart();
return distance(fst, snd) == 0;
}
@Override
......@@ -59,10 +65,34 @@ public class IntegerIntervalOperations implements IntervalOperations<Integer> {
return overlap(fst, snd) || adjacent(fst, snd);
}
@Override
public Integer distance(Interval<Integer> fst, Interval<Integer> snd) {
int startDist = fst.getStart() - snd.getStart();
int endDist = fst.getEnd() - snd.getEnd();
int startEndDist = fst.getStart() - snd.getEnd();
int endStartDist = fst.getEnd() - snd.getStart();
int min = Integer.MAX_VALUE;
if (Math.abs(startDist) < Math.abs(min)) {
min = startDist;
}
if (Math.abs(endDist) < Math.abs(min)) {
min = endDist;
}
if (Math.abs(startEndDist) < Math.abs(min)) {
min = startEndDist;
}
if (Math.abs(endStartDist) < Math.abs(min)) {
min = endStartDist;
}
return min;
}
@Override
public Interval<Integer> union(Interval<Integer> fst, Interval<Integer> snd) {
if (!overlapOrAdjacent(fst, snd)) {
throw new IllegalArgumentException("Can't union non overlapping intervals. " + fst + "; " + snd);
throw new IllegalArgumentException("Can't union the non overlapping and non adjacent intervals. " + fst + "; " + snd);
}
// normalize
fst = fst.as(Interval.Type.OneClosed);
......
......@@ -17,30 +17,89 @@
package de.cebitec.common.sequencetools.intervals;
/**
* This class defines operations on intervals. Internally the operations should operate on ZeroOpen intervals to allow
* the handling of empty intervals.
*
* @author Lukas Jelonek <ljelonek at cebitec.uni-bielefeld.de>
*/
public interface IntervalOperations<L extends Number> {
/**
* Checks whether the two intervals overlap each other. Overlap is defined such that two intervals have a common
* subinterval that has a length larger than zero. This means that empty intervals do never overlap to any other
* interval.
*
* @param fst
* @param snd
* @return
*/
public boolean overlap(Interval<L> fst, Interval<L> snd);
/**
* Checks whether the two intervals are adjacent to each other. Adjacency is defined such that two intervals are
* adjacent when they do not overlap and the distance between them is zero.
*
* @param fst
* @param snd
* @return
*/
public boolean adjacent(Interval<L> fst, Interval<L> snd);
/**
* Checks whether the two intervals overlap or are adjacent.
*
* @param fst
* @param snd
* @return
*/
public boolean overlapOrAdjacent(Interval<L> fst, Interval<L> snd);
/**
* The distance between two intervals is defined as the minimal distance that is needed to shift the second
* intervals such that either the starts or ends are equal or that a start and an end are equal.
*
* @param fst
* @param snd
* @return
*/
public L distance(Interval<L> fst, Interval<L> snd);
/**
* Shifts an interval by a given length, e.g. [2,3] shift by -2 results in [0,1].
*
*
* @param i
* @param by
* @return
* @return
*/
public Interval<L> shift(Interval<L> i, L by);
/* ********* Operations on overlapping or adjacent intervals ************ */
/**
* Calculates the union of two adjacent or overlapping intervals.
*
* @param fst
* @param snd
* @return
* @throws IllegalArgumentException If the intervals do not overlap.
*/
public Interval<L> union(Interval<L> fst, Interval<L> snd);
/**
* Calculates the intersection of two intervals i.e. the interval common to both.
*
* @param fst
* @param snd The intersection or an empty interval if they do not overlap.
* @return
*/
public Interval<L> intersection(Interval<L> fst, Interval<L> snd);
/**
* Calculates the complement of two intervals i.e. the interval that is contained in the first interval, but not in
* the second interval.
*
* @param fst
* @param snd
* @return
*/
public Interval<L> complement(Interval<L> fst, Interval<L> snd);
}
/*
* Copyright (C) 2013 Lukas Jelonek <ljelonek at cebitec.uni-bielefeld.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.cebitec.common.sequencetools.intervals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/**
*
* @author Lukas Jelonek <ljelonek at cebitec.uni-bielefeld.de>
*/
@RunWith(Parameterized.class)
public class IntegerIntervalAdjacentOperationTest {
private IntegerIntervalOperations ops = new IntegerIntervalOperations();
private Interval<Integer> fst;
private Interval<Integer> snd;
private boolean adjacent;
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
// ZeroOpen intervals
// both empty nonadjacent
{Intervals.createInterval(0, 0), Intervals.createInterval(1, 1), false},
// both empty adjacent
{Intervals.createInterval(0, 0), Intervals.createInterval(0, 0), true},
// fst emtpy nonadjacent
{Intervals.createInterval(0, 0), Intervals.createInterval(1, 2), false},
// fst emtpy adjacent
{Intervals.createInterval(0, 0), Intervals.createInterval(0, 2), true},
// snd emtpy nonadjacent
{Intervals.createInterval(1, 2), Intervals.createInterval(0, 0), false},
// snd emtpy adjacent
{Intervals.createInterval(0, 2), Intervals.createInterval(0, 0), true},
// snd below fst nonadjacent
{Intervals.createInterval(0, 2), Intervals.createInterval(-2, -1), false},
// snd above fst nonadjacent
{Intervals.createInterval(0, 2), Intervals.createInterval(3, 5), false},
// snd below fst adjacent
{Intervals.createInterval(0, 2), Intervals.createInterval(-2, 0), true},
// snd above fst adjacent
{Intervals.createInterval(0, 2), Intervals.createInterval(2, 5), true},
// OneClosed intervals
{Intervals.createInterval(0, 0, Interval.Type.OneClosed), Intervals.createInterval(1, 1, Interval.Type.OneClosed), true},
{Intervals.createInterval(0, 1, Interval.Type.OneClosed), Intervals.createInterval(3, 3, Interval.Type.OneClosed), false},
{Intervals.createInterval(0, 2, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), false}
});
}
public IntegerIntervalAdjacentOperationTest(Interval<Integer> fst, Interval<Integer> snd, boolean adjacent) {
this.fst = fst;
this.snd = snd;
this.adjacent = adjacent;
}
@Test
public void testAdjacent() {
assertThat(ops.adjacent(fst, snd), is(adjacent));
}
}
\ No newline at end of file
/*
* Copyright (C) 2013 Lukas Jelonek <ljelonek at cebitec.uni-bielefeld.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.cebitec.common.sequencetools.intervals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/**
*
* @author Lukas Jelonek <ljelonek at cebitec.uni-bielefeld.de>
*/
@RunWith(Parameterized.class)
public class IntegerIntervalDistanceOperationTest {
private IntegerIntervalOperations ops = new IntegerIntervalOperations();
private Interval<Integer> fst;
private Interval<Integer> snd;
private Integer distance;
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
// ZeroOpen intervals
// equal
{Intervals.createInterval(0, 2), Intervals.createInterval(0, 2), 0},
// below overlapping
{Intervals.createInterval(0, 2), Intervals.createInterval(-1, 1), 1},
// above overlapping
{Intervals.createInterval(0, 2), Intervals.createInterval(1, 3), -1},
// below non-overlapping
{Intervals.createInterval(0, 2), Intervals.createInterval(-2, -1), 1},
// above non-overlapping
{Intervals.createInterval(0, 2), Intervals.createInterval(3, 4), -1},
// contained
{Intervals.createInterval(0, 4), Intervals.createInterval(2, 3), 1},
{Intervals.createInterval(0, 1), Intervals.createInterval(2, 3), -1},
{Intervals.createInterval(0, 2), Intervals.createInterval(2, 3), 0},
{Intervals.createInterval(0, 3), Intervals.createInterval(2, 3), 0},
// OneClosed intervals
{Intervals.createInterval(0, 0, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), -1},
{Intervals.createInterval(0, 1, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), 0},
{Intervals.createInterval(0, 2, Interval.Type.OneClosed), Intervals.createInterval(2, 4, Interval.Type.OneClosed), 1}
});
}
public IntegerIntervalDistanceOperationTest(Interval<Integer> fst, Interval<Integer> snd, Integer distance) {
this.fst = fst;
this.snd = snd;
this.distance = distance;
}
@Test
public void testDistance() {
assertThat(ops.distance(fst, snd), is(distance));
}
}
\ No newline at end of file
......@@ -29,32 +29,47 @@ import org.junit.runners.Parameterized;
* @author Lukas Jelonek <ljelonek at cebitec.uni-bielefeld.de>
*/
@RunWith(Parameterized.class)
public class IntegerIntervalCompareOperationsTest {
public class IntegerIntervalOverlapOperationTest {
private IntegerIntervalOperations ops = new IntegerIntervalOperations();
private Interval<Integer> fst;
private Interval<Integer> snd;
private boolean adjacent;
private boolean overlap;
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
// ZeroOpen intervals
{Intervals.createInterval(0, 1), Intervals.createInterval(2, 3), false, false},
{Intervals.createInterval(0, 2), Intervals.createInterval(2, 3), true, false},
{Intervals.createInterval(0, 3), Intervals.createInterval(2, 3), false, true},
// empty intervals
{Intervals.createInterval(0, 0), Intervals.createInterval(0, 0), false},
{Intervals.createInterval(0, 0), Intervals.createInterval(1, 1), false},
// fst emtpy
{Intervals.createInterval(0, 0), Intervals.createInterval(0, 1), false},
// snd empty
{Intervals.createInterval(0, 1), Intervals.createInterval(0, 0), false},
// no overlap snd below fst
{Intervals.createInterval(0, 1), Intervals.createInterval(-2, -1), false},
// no overlap snd above fst
{Intervals.createInterval(0, 1), Intervals.createInterval(1, 2), false},
// overlap snd below fst
{Intervals.createInterval(0, 2), Intervals.createInterval(-1, 1), true},
// overlap snd above fst
{Intervals.createInterval(0, 2), Intervals.createInterval(1, 3), true},
// snd contained in fst
{Intervals.createInterval(0, 4), Intervals.createInterval(1, 3), true},
// fst contained in snd
{Intervals.createInterval(1, 3), Intervals.createInterval(0, 4), true},
// OneClosed intervals
{Intervals.createInterval(0, 0, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), false, false},
{Intervals.createInterval(0, 1, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), true, false},
{Intervals.createInterval(0, 2, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), false, true}
{Intervals.createInterval(0, 0, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), false},
{Intervals.createInterval(0, 1, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), false},
{Intervals.createInterval(0, 2, Interval.Type.OneClosed), Intervals.createInterval(2, 3, Interval.Type.OneClosed), true}
});
}
public IntegerIntervalCompareOperationsTest(Interval<Integer> fst, Interval<Integer> snd, boolean adjacent, boolean overlap) {
public IntegerIntervalOverlapOperationTest(Interval<Integer> fst, Interval<Integer> snd, boolean overlap) {
this.fst = fst;
this.snd = snd;
this.adjacent = adjacent;
this.overlap = overlap;
}
......@@ -62,14 +77,4 @@ public class IntegerIntervalCompareOperationsTest {
public void testOverlap() {
assertThat(ops.overlap(fst, snd), is(overlap));
}
@Test
public void testAdjacent() {
assertThat(ops.adjacent(fst, snd), is(adjacent));
}
@Test
public void testAdjacentOrOverlap() {
assertThat(ops.overlapOrAdjacent(fst, snd), is(adjacent || overlap));
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment