From f83f77b33312e044280dc19f08f5949e77c5ee5f Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Mon, 16 Apr 2018 19:13:14 +0200 Subject: [PATCH 001/131] init interval graphs, implemented centered interval tree --- .../intervalgraph/CenteredIntervalTree.java | 110 ++++++++++++++++++ .../jgrapht/intervalgraph/IntervalGraph.java | 14 +++ .../interval/IntegerInterval.java | 11 ++ .../intervalgraph/interval/Interval.java | 65 +++++++++++ .../CenteredIntervalTreeTest.java | 37 ++++++ .../interval/IntegerIntervalTest.java | 41 +++++++ 6 files changed, 278 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java new file mode 100644 index 00000000000..4baa4610259 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -0,0 +1,110 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.Graph; +import org.jgrapht.intervalgraph.interval.Interval; +import org.omg.SendingContext.RunTime; + +import java.util.*; + +public class CenteredIntervalTree> implements IntervalGraph{ + private T centerPoint; + private CenteredIntervalTree leftTree; // contains all the intervals *completely* to the left of the center point + private CenteredIntervalTree rightTree; // contains all the intervals *completely* to the right of the center point + private List> intersectionsByStart = new LinkedList<>(); // intervals intersecting center point, sorted by start point + private List> intersectionsByEnd = new LinkedList<>(); // ..., sorted by end point + + public CenteredIntervalTree(T centerPoint, List> intervals) { + this.centerPoint = centerPoint; + compute(intervals); + } + + public CenteredIntervalTree(List> intervals) { + this.centerPoint = intervals.get(0).getEnd(); // TODO replace this with something, its arbitrary + compute(intervals); + } + + private void compute( List> intervals) { + List> leftIntervals = new LinkedList<>(); // containing the intervals completely to the left of the center point + List> rightIntervals = new LinkedList<>(); // ... to the right + List> intersectingIntervals = new LinkedList<>(); // intervals intersecting the center point + + for (Interval interval: intervals) { + if (interval.contains(centerPoint)) { + intersectingIntervals.add(interval); + } + + if (interval.relativeDistance(centerPoint) < 0) { // is completely left to center point + leftIntervals.add(interval); + } else if (interval.relativeDistance(centerPoint) > 0) { // completely right + rightIntervals.add(interval); + } + } + + + // sorting the intervals according to start/end point + intersectionsByStart = new LinkedList<>(intersectingIntervals); + intersectionsByStart.sort(Comparator.comparing(Interval::getStart)); + + intersectionsByEnd = intersectingIntervals; + intersectionsByEnd.sort(Comparator.comparing(Interval::getStart)); + + + // add children to the left and right + if (!leftIntervals.isEmpty()){ + leftTree = new CenteredIntervalTree<>(leftIntervals); + } + + if (!rightIntervals.isEmpty()){ + rightTree = new CenteredIntervalTree<>(rightIntervals); + } + } + + @Override + public Collection> intersections(T point) { + Set> result = new HashSet<>(); // TODO Be aware, that I dont know if using sets guarantees linear run time + intersections(point, result); + return result; + } + + @Override + public Collection> intersections(Interval queryInterval) { + throw new RuntimeException(); + } + + private void intersections(T point, Set> result) { + if (point.equals(centerPoint)){ + result.addAll(intersectionsByEnd); // or intersectionsByStart + } else if (point.compareTo(centerPoint) < 0) { + // add all intervals with start point <= center point + for (Interval interval: intersectionsByStart) { + if (interval.getStart().compareTo(point) > 0) { + break; + } + result.add(interval); + } + + // recursion to child in tree + if (leftTree != null) { + leftTree.intersections(point, result); + } + } else { // point > centerPoint + // add all intervals with end point >= center point + for (Interval interval: intersectionsByEnd) { + if (interval.getEnd().compareTo(point) < 0) { + continue; + } + result.add(interval); + } + + // recursion to child in tree + if (rightTree != null) { + rightTree.intersections(point, result); + } + } + } + + @Override + public Graph asGraph() { + throw new RuntimeException(); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java new file mode 100644 index 00000000000..e06dcf8a452 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -0,0 +1,14 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.Graph; +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.Collection; + +public interface IntervalGraph> { + Collection> intersections(T queryInterval); + + Collection> intersections(Interval queryInterval); + + Graph asGraph(); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java new file mode 100644 index 00000000000..e463e70c1e9 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java @@ -0,0 +1,11 @@ +package org.jgrapht.intervalgraph.interval; + +public class IntegerInterval extends Interval { + public IntegerInterval(int start, int end) { + super(start, end); + } + + public int length() { + return getEnd() - getStart(); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java new file mode 100644 index 00000000000..41a423d59a2 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -0,0 +1,65 @@ +package org.jgrapht.intervalgraph.interval; + +public class Interval> implements Comparable> { + private T start; + private T end; + + public Interval(T start, T end) { + this.start = start; + this.end = end; + if (!isValid()) + throw new RuntimeException(); + } + + public T getStart() { + return start; + } + public T getEnd() { + return end; + } + + public boolean isIntersecting(Interval other) { + return other.getStart().compareTo(this.getEnd()) <= 0 || this.getStart().compareTo(other.getEnd()) <= 0; + } + + public boolean contains(T point) { + boolean result = point.compareTo(getStart()) >= 0 && point.compareTo(getEnd()) <= 0; + assert result == (relativeDistance(point) == 0); + return result; + } + + + public int relativeDistance(T o) { + int relativeStart = getStart().compareTo(o); + int relativeEnd = getEnd().compareTo(o); + + if (relativeStart <= 0 && relativeEnd >= 0) { + return 0; + } else if (relativeStart > 0) { + return relativeStart; + } else { + return relativeEnd; + } + } + + + @Override + public int compareTo(Interval o) { + int isLeft = getEnd().compareTo(o.getStart()); // < 0 if this ends before other starts + int isRight = getStart().compareTo(o.getEnd()); // > 0 if this starts before other ends + + if (isLeft >= 0 && isRight <= 0) { + return 0; + } else if (isLeft < 0) { + return isLeft; + } else { + return isRight; + } + } + + public boolean isValid() { + return getStart().compareTo(getEnd()) <= 0; + } + + +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java new file mode 100644 index 00000000000..770835cd98a --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java @@ -0,0 +1,37 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.jgrapht.intervalgraph.interval.Interval; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class CenteredIntervalTreeTest { + + IntegerInterval i00 = new IntegerInterval(0,0); + IntegerInterval i01 = new IntegerInterval(0,1); + IntegerInterval i56 = new IntegerInterval(5,6); + + List> list; + + + @Test + public void intersections() { + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(2).size()); + assertEquals(2, tree.intersections(0).size()); + } + + @Before + public void setUp() throws Exception { + list = new LinkedList<>(); + list.add(i00); + list.add(i01); + list.add(i56); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java new file mode 100644 index 00000000000..a0cd7680129 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java @@ -0,0 +1,41 @@ +package org.jgrapht.intervalgraph.interval; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class IntegerIntervalTest { + IntegerInterval i00 = new IntegerInterval(0,0); + IntegerInterval i01 = new IntegerInterval(0,1); + IntegerInterval i56 = new IntegerInterval(5,6); + + @Test + public void isIntersecting() { + } + + @Test + public void contains() { + assertEquals(i00.contains(0), true); + assertEquals(i01.contains(0), true); + assertEquals(i00.contains(1), false); + } + + @Test + public void relativeDistance() { + } + + @Test + public void compareTo() { + assertEquals(i00.compareTo(i01), 0); + assertEquals(i01.compareTo(i00), 0); + assertEquals(i56.compareTo(i01), 1); + assertEquals(i00.compareTo(i56), -1); + } + + @Test + public void isValid() { + assertEquals(i00.isValid(), true); + assertEquals(i01.isValid(), true); + } +} \ No newline at end of file From b782f9250014392aa0869e94661035d704ce61c3 Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Tue, 17 Apr 2018 00:03:09 +0200 Subject: [PATCH 002/131] updated --- .../intervalgraph/CenteredIntervalTree.java | 66 +++++++++++-------- .../jgrapht/intervalgraph/IntervalGraph.java | 4 +- .../intervalgraph/interval/Interval.java | 17 +++-- .../CenteredIntervalTreeTest.java | 8 +-- .../interval/IntegerIntervalTest.java | 15 +++-- 5 files changed, 64 insertions(+), 46 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java index 4baa4610259..4d27d2d67df 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -1,10 +1,10 @@ package org.jgrapht.intervalgraph; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + import org.jgrapht.Graph; import org.jgrapht.intervalgraph.interval.Interval; -import org.omg.SendingContext.RunTime; - -import java.util.*; public class CenteredIntervalTree> implements IntervalGraph{ private T centerPoint; @@ -12,18 +12,32 @@ public class CenteredIntervalTree> implements IntervalGr private CenteredIntervalTree rightTree; // contains all the intervals *completely* to the right of the center point private List> intersectionsByStart = new LinkedList<>(); // intervals intersecting center point, sorted by start point private List> intersectionsByEnd = new LinkedList<>(); // ..., sorted by end point + private boolean isEmpty = true; + + public CenteredIntervalTree(){} - public CenteredIntervalTree(T centerPoint, List> intervals) { - this.centerPoint = centerPoint; - compute(intervals); - } public CenteredIntervalTree(List> intervals) { - this.centerPoint = intervals.get(0).getEnd(); // TODO replace this with something, its arbitrary - compute(intervals); + initialize(intervals); } - private void compute( List> intervals) { + private void initialize(List> intervals) { + if (intervals == null){ + throw new IllegalArgumentException(); + } + + if (intervals.isEmpty()) { + return; + } + isEmpty = false; + + Interval randomInterval = intervals.get(ThreadLocalRandom.current().nextInt(intervals.size())); + if (ThreadLocalRandom.current().nextBoolean()) { + this.centerPoint = randomInterval.getStart(); + } else { + this.centerPoint = randomInterval.getEnd(); + } + List> leftIntervals = new LinkedList<>(); // containing the intervals completely to the left of the center point List> rightIntervals = new LinkedList<>(); // ... to the right List> intersectingIntervals = new LinkedList<>(); // intervals intersecting the center point @@ -40,23 +54,19 @@ private void compute( List> intervals) { } } - // sorting the intervals according to start/end point intersectionsByStart = new LinkedList<>(intersectingIntervals); intersectionsByStart.sort(Comparator.comparing(Interval::getStart)); intersectionsByEnd = intersectingIntervals; - intersectionsByEnd.sort(Comparator.comparing(Interval::getStart)); - + intersectionsByEnd.sort(Collections.reverseOrder(Comparator.comparing(Interval::getStart))); // add children to the left and right - if (!leftIntervals.isEmpty()){ - leftTree = new CenteredIntervalTree<>(leftIntervals); - } + leftTree = new CenteredIntervalTree<>(); + leftTree.initialize(leftIntervals); - if (!rightIntervals.isEmpty()){ - rightTree = new CenteredIntervalTree<>(rightIntervals); - } + rightTree = new CenteredIntervalTree<>(); + leftTree.initialize(rightIntervals); } @Override @@ -68,10 +78,14 @@ public Collection> intersections(T point) { @Override public Collection> intersections(Interval queryInterval) { - throw new RuntimeException(); + throw new RuntimeException("Method not implemented."); } private void intersections(T point, Set> result) { + if (isEmpty) { + return; + } + if (point.equals(centerPoint)){ result.addAll(intersectionsByEnd); // or intersectionsByStart } else if (point.compareTo(centerPoint) < 0) { @@ -84,27 +98,23 @@ private void intersections(T point, Set> result) { } // recursion to child in tree - if (leftTree != null) { - leftTree.intersections(point, result); - } + leftTree.intersections(point, result); } else { // point > centerPoint // add all intervals with end point >= center point for (Interval interval: intersectionsByEnd) { if (interval.getEnd().compareTo(point) < 0) { - continue; + break; } result.add(interval); } // recursion to child in tree - if (rightTree != null) { - rightTree.intersections(point, result); - } + rightTree.intersections(point, result); } } @Override public Graph asGraph() { - throw new RuntimeException(); + throw new RuntimeException("Method not implemented."); } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index e06dcf8a452..6accde1abb8 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -1,10 +1,10 @@ package org.jgrapht.intervalgraph; +import java.util.Collection; + import org.jgrapht.Graph; import org.jgrapht.intervalgraph.interval.Interval; -import java.util.Collection; - public interface IntervalGraph> { Collection> intersections(T queryInterval); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 41a423d59a2..4416a004ab2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -7,8 +7,9 @@ public class Interval> implements Comparable public Interval(T start, T end) { this.start = start; this.end = end; - if (!isValid()) - throw new RuntimeException(); + + if (start == null || end == null || !isValid()) + throw new IllegalArgumentException(); } public T getStart() { @@ -19,10 +20,14 @@ public T getEnd() { } public boolean isIntersecting(Interval other) { - return other.getStart().compareTo(this.getEnd()) <= 0 || this.getStart().compareTo(other.getEnd()) <= 0; + return this.contains(other.getStart()) || this.contains(other.getEnd()) || other.contains(this.getStart()); } public boolean contains(T point) { + if (point == null) { + throw new IllegalArgumentException(); + } + boolean result = point.compareTo(getStart()) >= 0 && point.compareTo(getEnd()) <= 0; assert result == (relativeDistance(point) == 0); return result; @@ -30,6 +35,10 @@ public boolean contains(T point) { public int relativeDistance(T o) { + if (o == null) { + throw new IllegalArgumentException(); + } + int relativeStart = getStart().compareTo(o); int relativeEnd = getEnd().compareTo(o); @@ -60,6 +69,4 @@ public int compareTo(Interval o) { public boolean isValid() { return getStart().compareTo(getEnd()) <= 0; } - - } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java index 770835cd98a..584e9dde857 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java @@ -25,13 +25,11 @@ public void intersections() { CenteredIntervalTree tree = new CenteredIntervalTree<>(list); assertEquals(0, tree.intersections(2).size()); assertEquals(2, tree.intersections(0).size()); + assertEquals(0, new CenteredIntervalTree(new LinkedList<>()).intersections(0).size()); } @Before - public void setUp() throws Exception { + public void setUp() { list = new LinkedList<>(); - list.add(i00); - list.add(i01); - list.add(i56); } -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java index a0cd7680129..0ce6e35a274 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java @@ -12,13 +12,16 @@ public class IntegerIntervalTest { @Test public void isIntersecting() { + assertTrue(i00.isIntersecting(i01)); + assertTrue(i01.isIntersecting(i01)); + assertFalse(i56.isIntersecting(i01)); } @Test public void contains() { - assertEquals(i00.contains(0), true); - assertEquals(i01.contains(0), true); - assertEquals(i00.contains(1), false); + assertTrue(i00.contains(0)); + assertTrue(i01.contains(0)); + assertFalse(i00.contains(1)); } @Test @@ -35,7 +38,7 @@ public void compareTo() { @Test public void isValid() { - assertEquals(i00.isValid(), true); - assertEquals(i01.isValid(), true); + assertTrue(i00.isValid()); + assertTrue(i01.isValid()); } -} \ No newline at end of file +} From 129f592ed7137dfa975c0e2e30854270bcbb8bf9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 16:01:28 +0200 Subject: [PATCH 003/131] init IntervalGraphInterface --- .../intervalgraph/IntervalGraphInterface.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java new file mode 100644 index 00000000000..77ff37a7092 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java @@ -0,0 +1,14 @@ +package org.jgrapht.intervalgraph; + +import java.util.Collection; + +import org.jgrapht.Graph; +import org.jgrapht.intervalgraph.interval.Interval; + +public interface IntervalGraphInterface> { + Collection> intersections(T queryInterval); + + Collection> intersections(Interval queryInterval); + + Graph asGraph(); +} From 59b9261b41abcbf564a7fe04476312b4f1ec0522 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 16:03:32 +0200 Subject: [PATCH 004/131] init BinarySearchTree --- .../intervalgraph/BinarySearchTree.java | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java new file mode 100644 index 00000000000..763b3466f89 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -0,0 +1,173 @@ +package org.jgrapht.intervalgraph; + +public interface BinarySearchTree { + + /******************************************************************************************************************* + * Search Operations * + ******************************************************************************************************************/ + + /** + * Returns the value associated with the given key + * + * @param key the key + * @return the value associated with the given key. If the key is not in the tree, null is returned. + * @throws IllegalArgumentException if key is null + */ + V get(K key); + + /** + * Returns whether a key is contained in the tree + * + * @param key the key + * @return true if tree contains key, false otherwise + * @throws IllegalArgumentException if key is null + */ + boolean contains(K key); + + + /******************************************************************************************************************* + * Insertion Operations * + ******************************************************************************************************************/ + + /** + * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * it overwrites the old value with the new. + * + * @param key the key + * @param val the value + * @throws IllegalArgumentException if key is null + */ + void insert(K key, V val); + + + /******************************************************************************************************************* + * Deletion Operations * + ******************************************************************************************************************/ + + /** + * Removes the specified key and its associated value from this tree + * + * @param key the key + * @throws IllegalArgumentException if key is null + */ + void delete(K key); + + /** + * Removes the smallest key and associated value from the tree. + * @throws NoSuchElementException if the tree is empty + */ + void deleteMin(); + + /** + * Removes the largest key and associated value from the tree. + * @throws NoSuchElementException if the tree is empty + */ + void deleteMax(); + + + /******************************************************************************************************************* + * Utility Operations * + ******************************************************************************************************************/ + + /** + * Returns the height of the BST. + * @return the height of the BST (a tree with 1 node has height 0) + */ + int height(); + + + /******************************************************************************************************************* + * Special Search Operations * + ******************************************************************************************************************/ + + /** + * Returns the smallest key in the tree. + * @return the smallest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + K min(); + /** + * Returns the largest key in the tree. + * @return the largest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + K max(); + + /** + * Returns the largest key in the tree less than or equal to key. + * + * @param key the key + * @return the largest key in the tree less than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + K floor(K key); + + /** + * Returns the smallest key in the tree greater than or equal to key. + * + * @param key the key + * @return the smallest key in the tree greater than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + K ceiling(K key); + + /** + * Return the key in the tree whose rank is k. + * This is the (k+1)st smallest key in the tree. + * + * @param k the position + * @return the key in the tree of rank k + * @throws IllegalArgumentException if k not in {0, ..., n-1} + */ + K select(int k); + + /** + * Return the number of keys in the tree strictly less than key. + * + * @param key the key + * @return the number of keys in the tree strictly less than key + * @throws IllegalArgumentException if key is null + */ + int rank(K key); + + + /******************************************************************************************************************* + * Range Search Operations * + ******************************************************************************************************************/ + + /** + * Returns all keys in the symbol table as an Iterable. + * To iterate over all of the keys in the symbol table named st, + * use the foreach notation: for (Key key : st.keys()). + * + * @return all keys in the symbol table as an Iterable + */ + Iterable keys(); + + /** + * Returns all keys in the symbol table in the given range, + * as an Iterable. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return all keys in the sybol table between min + * (inclusive) and max (inclusive) as an Iterable + * @throws IllegalArgumentException if either min or max + * is null + */ + Iterable keys(K min, K max); + + /** + * Returns the number of keys in the symbol table in the given range. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return the number of keys in the sybol table between min + * (inclusive) and max (inclusive) + * @throws IllegalArgumentException if either min or max + * is null + */ + int size(K min, K max); +} \ No newline at end of file From fe728c3c831cc7726bef5c8a9e8e50dd3f7f0d66 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 16:04:24 +0200 Subject: [PATCH 005/131] added class Node and RedBlackTree --- .../java/org/jgrapht/intervalgraph/Node.java | 17 ++ .../jgrapht/intervalgraph/RedBlackTree.java | 200 ++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java new file mode 100644 index 00000000000..4c1c084a5ae --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -0,0 +1,17 @@ +package org.jgrapht.intervalgraph; + +// BST helper node data type +private class Node { + private Key key; // key + private Value val; // associated data + private Node left, right; // links to left and right subtrees + private boolean color; // color of parent link + private int size; // subtree count + + public Node(Key key, Value val, boolean color, int size) { + this.key = key; + this.val = val; + this.color = color; + this.size = size; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java new file mode 100644 index 00000000000..58b093ad111 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -0,0 +1,200 @@ +package org.jgrapht.intervalgraph; + +public class RedBlackTree implements BinarySearchTree { + + private Node root; + + /** + * Returns the value associated with the given key + * + * @param key the key + * @return the value associated with the given key. If the key is not in the tree, null is returned. + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public V get(K key) { + return null; + } + + /** + * Returns whether a key is contained in the tree + * + * @param key the key + * @return true if tree contains key, false otherwise + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public boolean contains(K key) { + return false; + } + + /** + * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * it overwrites the old value with the new. + * + * @param key the key + * @param val the value + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public void insert(K key, V val) { + + } + + /** + * Removes the specified key and its associated value from this tree + * + * @param key the key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public void delete(K key) { + + } + + /** + * Removes the smallest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + @Override + public void deleteMin() { + + } + + /** + * Removes the largest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + @Override + public void deleteMax() { + + } + + /** + * Returns the height of the BST. + * + * @return the height of the BST (a tree with 1 node has height 0) + */ + @Override + public int height() { + return 0; + } + + /** + * Returns the smallest key in the tree. + * + * @return the smallest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + @Override + public K min() { + return null; + } + + /** + * Returns the largest key in the tree. + * + * @return the largest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + @Override + public K max() { + return null; + } + + /** + * Returns the largest key in the tree less than or equal to {@code key}. + * + * @param key the key + * @return the largest key in the tree less than or equal to {@code key} + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public K floor(K key) { + return null; + } + + /** + * Returns the smallest key in the tree greater than or equal to {@code key}. + * + * @param key the key + * @return the smallest key in the tree greater than or equal to {@code key} + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public K ceiling(K key) { + return null; + } + + /** + * Return the key in the tree whose rank is {@code k}. + * This is the (k+1)st smallest key in the tree. + * + * @param k the position + * @return the key in the tree of rank {@code k} + * @throws IllegalArgumentException if {@code k} not in {0, ..., n-1} + */ + @Override + public K select(int k) { + return null; + } + + /** + * Return the number of keys in the tree strictly less than {@code key}. + * + * @param key the key + * @return the number of keys in the tree strictly less than {@code key} + * @throws IllegalArgumentException if {@code key} is {@code null} + */ + @Override + public int rank(K key) { + return 0; + } + + /** + * Returns all keys in the symbol table as an {@code Iterable}. + * To iterate over all of the keys in the symbol table named {@code st}, + * use the foreach notation: {@code for (Key key : st.keys())}. + * + * @return all keys in the symbol table as an {@code Iterable} + */ + @Override + public Iterable keys() { + return null; + } + + /** + * Returns all keys in the symbol table in the given range, + * as an {@code Iterable}. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return all keys in the sybol table between {@code lo} + * (inclusive) and {@code hi} (inclusive) as an {@code Iterable} + * @throws IllegalArgumentException if either {@code lo} or {@code hi} + * is {@code null} + */ + @Override + public Iterable keys(K min, K max) { + return null; + } + + /** + * Returns the number of keys in the symbol table in the given range. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return the number of keys in the sybol table between {@code lo} + * (inclusive) and {@code hi} (inclusive) + * @throws IllegalArgumentException if either {@code lo} or {@code hi} + * is {@code null} + */ + @Override + public int size(K min, K max) { + return 0; + } +} From 89ef8dab32019aba54054c6dd77ad9eab0bc80c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 16:05:06 +0200 Subject: [PATCH 006/131] modified existing implemntations --- .../intervalgraph/CenteredIntervalTree.java | 2 +- .../jgrapht/intervalgraph/IntervalGraph.java | 503 +++++++++++++++++- 2 files changed, 498 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java index 4d27d2d67df..6ea6243d9a4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -6,7 +6,7 @@ import org.jgrapht.Graph; import org.jgrapht.intervalgraph.interval.Interval; -public class CenteredIntervalTree> implements IntervalGraph{ +public class CenteredIntervalTree> implements IntervalGraphInterface { private T centerPoint; private CenteredIntervalTree leftTree; // contains all the intervals *completely* to the left of the center point private CenteredIntervalTree rightTree; // contains all the intervals *completely* to the right of the center point diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 6accde1abb8..545e16c7ec5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -1,14 +1,505 @@ package org.jgrapht.intervalgraph; +import org.jgrapht.EdgeFactory; +import org.jgrapht.Graph; +import org.jgrapht.GraphType; + import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; -import org.jgrapht.Graph; -import org.jgrapht.intervalgraph.interval.Interval; +public class IntervalGraph implements Graph { + /** + * Returns a set of all edges connecting source vertex to target vertex if such vertices exist + * in this graph. If any of the vertices does not exist or is null, returns + * null. If both vertices exist but no edges found, returns an empty set. + * + *

+ * In undirected graphs, some of the returned edges may have their source and target vertices in + * the opposite order. In simple graphs the returned set is either singleton set or empty set. + *

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @return a set of all edges connecting source vertex to target vertex. + */ + @Override + public Set getAllEdges(V sourceVertex, V targetVertex) { + return null; + } + + /** + * Returns an edge connecting source vertex to target vertex if such vertices and such edge + * exist in this graph. Otherwise returns + * null. If any of the specified vertices is null returns null + * + *

+ * In undirected graphs, the returned edge may have its source and target vertices in the + * opposite order. + *

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @return an edge connecting source vertex to target vertex. + */ + @Override + public E getEdge(V sourceVertex, V targetVertex) { + return null; + } + + /** + * Returns the edge factory using which this graph creates new edges. The edge factory is + * defined when the graph is constructed and must not be modified. + * + * @return the edge factory using which this graph creates new edges. + */ + @Override + public EdgeFactory getEdgeFactory() { + return null; + } + + /** + * Creates a new edge in this graph, going from the source vertex to the target vertex, and + * returns the created edge. Some graphs do not allow edge-multiplicity. In such cases, if the + * graph already contains an edge from the specified source to the specified target, than this + * method does not change the graph and returns null. + * + *

+ * The source and target vertices must already be contained in this graph. If they are not found + * in graph IllegalArgumentException is thrown. + *

+ * + *

+ * This method creates the new edge e using this graph's EdgeFactory. + * For the new edge to be added e must not be equal to any other edge the + * graph (even if the graph allows edge-multiplicity). More formally, the graph must not contain + * any edge e2 such that e2.equals(e). If such + * e2 is found then the newly created edge e is abandoned, the method leaves + * this graph unchanged returns + * null. + *

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @return The newly created edge if added to the graph, otherwise + * null. + * @throws IllegalArgumentException if source or target vertices are not found in the graph. + * @throws NullPointerException if any of the specified vertices is + * null. + * @see #getEdgeFactory() + */ + @Override + public E addEdge(V sourceVertex, V targetVertex) { + return null; + } + + /** + * Adds the specified edge to this graph, going from the source vertex to the target vertex. + * More formally, adds the specified edge, + * e, to this graph if this graph contains no edge e2 such that + * e2.equals(e). If this graph already contains such an edge, the call leaves this + * graph unchanged and returns false. Some graphs do not allow edge-multiplicity. In + * such cases, if the graph already contains an edge from the specified source to the specified + * target, than this method does not change the graph and returns + * false. If the edge was added to the graph, returns + * true. + * + *

+ * The source and target vertices must already be contained in this graph. If they are not found + * in graph IllegalArgumentException is thrown. + *

+ * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @param e edge to be added to this graph. + * @return true if this graph did not already contain the specified edge. + * @throws IllegalArgumentException if source or target vertices are not found in the graph. + * @throws ClassCastException if the specified edge is not assignment compatible with the class + * of edges produced by the edge factory of this graph. + * @throws NullPointerException if any of the specified vertices is + * null. + * @see #addEdge(Object, Object) + * @see #getEdgeFactory() + */ + @Override + public boolean addEdge(V sourceVertex, V targetVertex, E e) { + return false; + } + + /** + * Adds the specified vertex to this graph if not already present. More formally, adds the + * specified vertex, v, to this graph if this graph contains no vertex + * u such that + * u.equals(v). If this graph already contains such vertex, the call leaves this graph + * unchanged and returns false. In combination with the restriction on constructors, + * this ensures that graphs never contain duplicate vertices. + * + * @param v vertex to be added to this graph. + * @return true if this graph did not already contain the specified vertex. + * @throws NullPointerException if the specified vertex is + * null. + */ + @Override + public boolean addVertex(V v) { + return false; + } + + /** + * Returns true if and only if this graph contains an edge going from the source vertex + * to the target vertex. In undirected graphs the same result is obtained when source and target + * are inverted. If any of the specified vertices does not exist in the graph, or if is + * null, returns false. + * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @return true if this graph contains the specified edge. + */ + @Override + public boolean containsEdge(V sourceVertex, V targetVertex) { + return false; + } + + /** + * Returns true if this graph contains the specified edge. More formally, returns + * true if and only if this graph contains an edge e2 such that + * e.equals(e2). If the specified edge is null returns + * false. + * + * @param e edge whose presence in this graph is to be tested. + * @return true if this graph contains the specified edge. + */ + @Override + public boolean containsEdge(E e) { + return false; + } + + /** + * Returns true if this graph contains the specified vertex. More formally, returns + * true if and only if this graph contains a vertex u such that + * u.equals(v). If the specified vertex is null returns + * false. + * + * @param v vertex whose presence in this graph is to be tested. + * @return true if this graph contains the specified vertex. + */ + @Override + public boolean containsVertex(V v) { + return false; + } + + /** + * Returns a set of the edges contained in this graph. The set is backed by the graph, so + * changes to the graph are reflected in the set. If the graph is modified while an iteration + * over the set is in progress, the results of the iteration are undefined. + * + *

+ * The graph implementation may maintain a particular set ordering (e.g. via + * {@link LinkedHashSet}) for deterministic iteration, but this is not required. It is + * the responsibility of callers who rely on this behavior to only use graph implementations + * which support it. + *

+ * + * @return a set of the edges contained in this graph. + */ + @Override + public Set edgeSet() { + return null; + } + + /** + * Returns the degree of the specified vertex. + *

+ *

+ * A degree of a vertex in an undirected graph is the number of edges touching that vertex. + * Edges with same source and target vertices (self-loops) are counted twice. + *

+ *

+ * In directed graphs this method returns the sum of the "in degree" and the "out degree". + * + * @param vertex vertex whose degree is to be calculated. + * @return the degree of the specified vertex. + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + @Override + public int degreeOf(V vertex) { + return 0; + } + + /** + * Returns a set of all edges touching the specified vertex. If no edges are touching the + * specified vertex returns an empty set. + * + * @param vertex the vertex for which a set of touching edges is to be returned. + * @return a set of all edges touching the specified vertex. + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + @Override + public Set edgesOf(V vertex) { + return null; + } + + /** + * Returns the "in degree" of the specified vertex. + *

+ *

+ * The "in degree" of a vertex in a directed graph is the number of inward directed edges from + * that vertex. See + * http://mathworld.wolfram.com/Indegree.html. + *

+ *

+ * In the case of undirected graphs this method returns the number of edges touching the vertex. + * Edges with same source and target vertices (self-loops) are counted twice. + * + * @param vertex vertex whose degree is to be calculated. + * @return the degree of the specified vertex. + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + @Override + public int inDegreeOf(V vertex) { + return 0; + } + + /** + * Returns a set of all edges incoming into the specified vertex. + *

+ *

+ * In the case of undirected graphs this method returns all edges touching the vertex, thus, + * some of the returned edges may have their source and target vertices in the opposite order. + * + * @param vertex the vertex for which the list of incoming edges to be returned. + * @return a set of all edges incoming into the specified vertex. + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + @Override + public Set incomingEdgesOf(V vertex) { + return null; + } + + /** + * Returns the "out degree" of the specified vertex. + *

+ *

+ * The "out degree" of a vertex in a directed graph is the number of outward directed edges from + * that vertex. See + * http://mathworld.wolfram.com/Outdegree.html. + *

+ *

+ * In the case of undirected graphs this method returns the number of edges touching the vertex. + * Edges with same source and target vertices (self-loops) are counted twice. + * + * @param vertex vertex whose degree is to be calculated. + * @return the degree of the specified vertex. + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + @Override + public int outDegreeOf(V vertex) { + return 0; + } + + /** + * Returns a set of all edges outgoing from the specified vertex. + *

+ *

+ * In the case of undirected graphs this method returns all edges touching the vertex, thus, + * some of the returned edges may have their source and target vertices in the opposite order. + * + * @param vertex the vertex for which the list of outgoing edges to be returned. + * @return a set of all edges outgoing from the specified vertex. + * @throws IllegalArgumentException if vertex is not found in the graph. + * @throws NullPointerException if vertex is null. + */ + @Override + public Set outgoingEdgesOf(V vertex) { + return null; + } + + /** + * Removes all the edges in this graph that are also contained in the specified edge collection. + * After this call returns, this graph will contain no edges in common with the specified edges. + * This method will invoke the {@link #removeEdge(Object)} method. + * + * @param edges edges to be removed from this graph. + * @return true if this graph changed as a result of the call + * @throws NullPointerException if the specified edge collection is + * null. + * @see #removeEdge(Object) + * @see #containsEdge(Object) + */ + @Override + public boolean removeAllEdges(Collection edges) { + return false; + } + + /** + * Removes all the edges going from the specified source vertex to the specified target vertex, + * and returns a set of all removed edges. Returns null if any of the specified + * vertices does not exist in the graph. If both vertices exist but no edge is found, returns an + * empty set. This method will either invoke the {@link #removeEdge(Object)} method, or the + * {@link #removeEdge(Object, Object)} method. + * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @return the removed edges, or null if either vertex is not part of graph + */ + @Override + public Set removeAllEdges(V sourceVertex, V targetVertex) { + return null; + } + + /** + * Removes all the vertices in this graph that are also contained in the specified vertex + * collection. After this call returns, this graph will contain no vertices in common with the + * specified vertices. This method will invoke the {@link #removeVertex(Object)} method. + * + * @param vertices vertices to be removed from this graph. + * @return true if this graph changed as a result of the call + * @throws NullPointerException if the specified vertex collection is + * null. + * @see #removeVertex(Object) + * @see #containsVertex(Object) + */ + @Override + public boolean removeAllVertices(Collection vertices) { + return false; + } + + /** + * Removes an edge going from source vertex to target vertex, if such vertices and such edge + * exist in this graph. Returns the edge if removed or null otherwise. + * + * @param sourceVertex source vertex of the edge. + * @param targetVertex target vertex of the edge. + * @return The removed edge, or null if no edge removed. + */ + @Override + public E removeEdge(V sourceVertex, V targetVertex) { + return null; + } + + /** + * Removes the specified edge from the graph. Removes the specified edge from this graph if it + * is present. More formally, removes an edge + * e2 such that e2.equals(e), if the graph contains such edge. Returns + * true if the graph contained the specified edge. (The graph will not contain the + * specified edge once the call returns). + * + *

+ * If the specified edge is null returns + * false. + *

+ * + * @param e edge to be removed from this graph, if present. + * @return true if and only if the graph contained the specified edge. + */ + @Override + public boolean removeEdge(E e) { + return false; + } + + /** + * Removes the specified vertex from this graph including all its touching edges if present. + * More formally, if the graph contains a vertex + * u such that u.equals(v), the call removes all edges that touch + * u and then removes u itself. If no such u is found, + * the call leaves the graph unchanged. Returns true if the graph contained the + * specified vertex. (The graph will not contain the specified vertex once the call returns). + * + *

+ * If the specified vertex is null returns + * false. + *

+ * + * @param v vertex to be removed from this graph, if present. + * @return true if the graph contained the specified vertex; false + * otherwise. + */ + @Override + public boolean removeVertex(V v) { + return false; + } + + /** + * Returns a set of the vertices contained in this graph. The set is backed by the graph, so + * changes to the graph are reflected in the set. If the graph is modified while an iteration + * over the set is in progress, the results of the iteration are undefined. + * + *

+ * The graph implementation may maintain a particular set ordering (e.g. via + * {@link LinkedHashSet}) for deterministic iteration, but this is not required. It is + * the responsibility of callers who rely on this behavior to only use graph implementations + * which support it. + *

+ * + * @return a set view of the vertices contained in this graph. + */ + @Override + public Set vertexSet() { + return null; + } + + /** + * Returns the source vertex of an edge. For an undirected graph, source and target are + * distinguishable designations (but without any mathematical meaning). + * + * @param e edge of interest + * @return source vertex + */ + @Override + public V getEdgeSource(E e) { + return null; + } + + /** + * Returns the target vertex of an edge. For an undirected graph, source and target are + * distinguishable designations (but without any mathematical meaning). + * + * @param e edge of interest + * @return target vertex + */ + @Override + public V getEdgeTarget(E e) { + return null; + } + + /** + * Get the graph type. The graph type can be used to query for additional metadata such as + * whether the graph supports directed or undirected edges, self-loops, multiple (parallel) + * edges, weights, etc. + * + * @return the graph type + */ + @Override + public GraphType getType() { + return null; + } -public interface IntervalGraph> { - Collection> intersections(T queryInterval); + /** + * Returns the weight assigned to a given edge. Unweighted graphs return 1.0 (as defined by + * {@link #DEFAULT_EDGE_WEIGHT}), allowing weighted-graph algorithms to apply to them when + * meaningful. + * + * @param e edge of interest + * @return edge weight + */ + @Override + public double getEdgeWeight(E e) { + return 0; + } - Collection> intersections(Interval queryInterval); + /** + * Assigns a weight to an edge. + * + * @param e edge on which to set weight + * @param weight new weight for edge + * @throws UnsupportedOperationException if the graph does not support weights + */ + @Override + public void setEdgeWeight(E e, double weight) { - Graph asGraph(); + } } From 337de7a034ab8447e4c519797beb7f7575d7ff47 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 16:56:47 +0200 Subject: [PATCH 007/131] small changes --- .../intervalgraph/BinarySearchTree.java | 9 + .../jgrapht/intervalgraph/IntervalGraph.java | 491 ++++-------------- .../java/org/jgrapht/intervalgraph/Node.java | 20 +- .../jgrapht/intervalgraph/RedBlackTree.java | 88 ++-- 4 files changed, 179 insertions(+), 429 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java index 763b3466f89..522c8a644d2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -1,5 +1,14 @@ package org.jgrapht.intervalgraph; +/** + * Interface for Binary Search Trees + * + * @param the key + * @param the value + * + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ public interface BinarySearchTree { /******************************************************************************************************************* diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 545e16c7ec5..52cc91b181a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -3,503 +3,210 @@ import org.jgrapht.EdgeFactory; import org.jgrapht.Graph; import org.jgrapht.GraphType; +import org.jgrapht.graph.AbstractBaseGraph; +import org.jgrapht.graph.AbstractGraph; +import org.jgrapht.graph.IntrusiveEdgesSpecifics; +import org.jgrapht.graph.SimpleWeightedGraph; +import org.jgrapht.graph.specifics.Specifics; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; -public class IntervalGraph implements Graph { - /** - * Returns a set of all edges connecting source vertex to target vertex if such vertices exist - * in this graph. If any of the vertices does not exist or is null, returns - * null. If both vertices exist but no edges found, returns an empty set. - * - *

- * In undirected graphs, some of the returned edges may have their source and target vertices in - * the opposite order. In simple graphs the returned set is either singleton set or empty set. - *

- * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @return a set of all edges connecting source vertex to target vertex. - */ - @Override - public Set getAllEdges(V sourceVertex, V targetVertex) { - return null; - } +/** + * Implementation of an Interval Graph + * + * @param the vertex type + * @param the edge type + * + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ +public class IntervalGraph extends SimpleWeightedGraph { + + private static final String INTERVAL_GRAPH_ADD_EDGE = "Intervals of nodes define edges in interval graphs and cannot be modified manually"; /** - * Returns an edge connecting source vertex to target vertex if such vertices and such edge - * exist in this graph. Otherwise returns - * null. If any of the specified vertices is null returns null - * - *

- * In undirected graphs, the returned edge may have its source and target vertices in the - * opposite order. - *

+ * Creates a new simple weighted graph with the specified edge factory. * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @return an edge connecting source vertex to target vertex. + * @param ef the edge factory of the new graph. */ - @Override - public E getEdge(V sourceVertex, V targetVertex) { - return null; + public IntervalGraph(EdgeFactory ef) { + super(ef); } /** - * Returns the edge factory using which this graph creates new edges. The edge factory is - * defined when the graph is constructed and must not be modified. + * Creates a new simple weighted graph. * - * @return the edge factory using which this graph creates new edges. + * @param edgeClass class on which to base factory for edges */ - @Override - public EdgeFactory getEdgeFactory() { - return null; + public IntervalGraph(Class edgeClass) { + super(edgeClass); } /** - * Creates a new edge in this graph, going from the source vertex to the target vertex, and - * returns the created edge. Some graphs do not allow edge-multiplicity. In such cases, if the - * graph already contains an edge from the specified source to the specified target, than this - * method does not change the graph and returns null. - * - *

- * The source and target vertices must already be contained in this graph. If they are not found - * in graph IllegalArgumentException is thrown. - *

- * - *

- * This method creates the new edge e using this graph's EdgeFactory. - * For the new edge to be added e must not be equal to any other edge the - * graph (even if the graph allows edge-multiplicity). More formally, the graph must not contain - * any edge e2 such that e2.equals(e). If such - * e2 is found then the newly created edge e is abandoned, the method leaves - * this graph unchanged returns - * null. - *

+ * {@inheritDoc} * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @return The newly created edge if added to the graph, otherwise - * null. - * @throws IllegalArgumentException if source or target vertices are not found in the graph. - * @throws NullPointerException if any of the specified vertices is - * null. - * @see #getEdgeFactory() + * @param sourceVertex + * @param targetVertex */ @Override public E addEdge(V sourceVertex, V targetVertex) { - return null; + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** - * Adds the specified edge to this graph, going from the source vertex to the target vertex. - * More formally, adds the specified edge, - * e, to this graph if this graph contains no edge e2 such that - * e2.equals(e). If this graph already contains such an edge, the call leaves this - * graph unchanged and returns false. Some graphs do not allow edge-multiplicity. In - * such cases, if the graph already contains an edge from the specified source to the specified - * target, than this method does not change the graph and returns - * false. If the edge was added to the graph, returns - * true. + * {@inheritDoc} * - *

- * The source and target vertices must already be contained in this graph. If they are not found - * in graph IllegalArgumentException is thrown. - *

- * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @param e edge to be added to this graph. - * @return true if this graph did not already contain the specified edge. - * @throws IllegalArgumentException if source or target vertices are not found in the graph. - * @throws ClassCastException if the specified edge is not assignment compatible with the class - * of edges produced by the edge factory of this graph. - * @throws NullPointerException if any of the specified vertices is - * null. - * @see #addEdge(Object, Object) - * @see #getEdgeFactory() + * @param sourceVertex + * @param targetVertex + * @param e */ @Override public boolean addEdge(V sourceVertex, V targetVertex, E e) { - return false; + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** - * Adds the specified vertex to this graph if not already present. More formally, adds the - * specified vertex, v, to this graph if this graph contains no vertex - * u such that - * u.equals(v). If this graph already contains such vertex, the call leaves this graph - * unchanged and returns false. In combination with the restriction on constructors, - * this ensures that graphs never contain duplicate vertices. + * {@inheritDoc} * - * @param v vertex to be added to this graph. - * @return true if this graph did not already contain the specified vertex. - * @throws NullPointerException if the specified vertex is - * null. + * @param v */ @Override public boolean addVertex(V v) { - return false; - } - - /** - * Returns true if and only if this graph contains an edge going from the source vertex - * to the target vertex. In undirected graphs the same result is obtained when source and target - * are inverted. If any of the specified vertices does not exist in the graph, or if is - * null, returns false. - * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @return true if this graph contains the specified edge. - */ - @Override - public boolean containsEdge(V sourceVertex, V targetVertex) { - return false; + return super.addVertex(v); } /** - * Returns true if this graph contains the specified edge. More formally, returns - * true if and only if this graph contains an edge e2 such that - * e.equals(e2). If the specified edge is null returns - * false. + * {@inheritDoc} * - * @param e edge whose presence in this graph is to be tested. - * @return true if this graph contains the specified edge. + * @param sourceVertex + * @param targetVertex */ @Override - public boolean containsEdge(E e) { - return false; - } - - /** - * Returns true if this graph contains the specified vertex. More formally, returns - * true if and only if this graph contains a vertex u such that - * u.equals(v). If the specified vertex is null returns - * false. - * - * @param v vertex whose presence in this graph is to be tested. - * @return true if this graph contains the specified vertex. - */ - @Override - public boolean containsVertex(V v) { - return false; - } - - /** - * Returns a set of the edges contained in this graph. The set is backed by the graph, so - * changes to the graph are reflected in the set. If the graph is modified while an iteration - * over the set is in progress, the results of the iteration are undefined. - * - *

- * The graph implementation may maintain a particular set ordering (e.g. via - * {@link LinkedHashSet}) for deterministic iteration, but this is not required. It is - * the responsibility of callers who rely on this behavior to only use graph implementations - * which support it. - *

- * - * @return a set of the edges contained in this graph. - */ - @Override - public Set edgeSet() { - return null; - } - - /** - * Returns the degree of the specified vertex. - *

- *

- * A degree of a vertex in an undirected graph is the number of edges touching that vertex. - * Edges with same source and target vertices (self-loops) are counted twice. - *

- *

- * In directed graphs this method returns the sum of the "in degree" and the "out degree". - * - * @param vertex vertex whose degree is to be calculated. - * @return the degree of the specified vertex. - * @throws IllegalArgumentException if vertex is not found in the graph. - * @throws NullPointerException if vertex is null. - */ - @Override - public int degreeOf(V vertex) { - return 0; + public E removeEdge(V sourceVertex, V targetVertex) { + return super.removeEdge(sourceVertex, targetVertex); } /** - * Returns a set of all edges touching the specified vertex. If no edges are touching the - * specified vertex returns an empty set. + * {@inheritDoc} * - * @param vertex the vertex for which a set of touching edges is to be returned. - * @return a set of all edges touching the specified vertex. - * @throws IllegalArgumentException if vertex is not found in the graph. - * @throws NullPointerException if vertex is null. + * @param e */ @Override - public Set edgesOf(V vertex) { - return null; + public boolean removeEdge(E e) { + return super.removeEdge(e); } /** - * Returns the "in degree" of the specified vertex. - *

- *

- * The "in degree" of a vertex in a directed graph is the number of inward directed edges from - * that vertex. See - * http://mathworld.wolfram.com/Indegree.html. - *

- *

- * In the case of undirected graphs this method returns the number of edges touching the vertex. - * Edges with same source and target vertices (self-loops) are counted twice. + * {@inheritDoc} * - * @param vertex vertex whose degree is to be calculated. - * @return the degree of the specified vertex. - * @throws IllegalArgumentException if vertex is not found in the graph. - * @throws NullPointerException if vertex is null. + * @param v */ @Override - public int inDegreeOf(V vertex) { - return 0; + public boolean removeVertex(V v) { + return super.removeVertex(v); } /** - * Returns a set of all edges incoming into the specified vertex. - *

- *

- * In the case of undirected graphs this method returns all edges touching the vertex, thus, - * some of the returned edges may have their source and target vertices in the opposite order. - * - * @param vertex the vertex for which the list of incoming edges to be returned. - * @return a set of all edges incoming into the specified vertex. - * @throws IllegalArgumentException if vertex is not found in the graph. - * @throws NullPointerException if vertex is null. + * {@inheritDoc} */ @Override - public Set incomingEdgesOf(V vertex) { - return null; + public GraphType getType() { + return super.getType(); } /** - * Returns the "out degree" of the specified vertex. - *

- *

- * The "out degree" of a vertex in a directed graph is the number of outward directed edges from - * that vertex. See - * http://mathworld.wolfram.com/Outdegree.html. - *

- *

- * In the case of undirected graphs this method returns the number of edges touching the vertex. - * Edges with same source and target vertices (self-loops) are counted twice. + * Create the specifics for this graph. Subclasses can override this method in order to adjust + * the specifics and thus the space-time tradeoffs of the graph implementation. * - * @param vertex vertex whose degree is to be calculated. - * @return the degree of the specified vertex. - * @throws IllegalArgumentException if vertex is not found in the graph. - * @throws NullPointerException if vertex is null. + * @param directed if true the specifics should adjust the behavior to a directed graph + * otherwise undirected + * @return the specifics used by this graph */ @Override - public int outDegreeOf(V vertex) { - return 0; + protected Specifics createSpecifics(boolean directed) { + return super.createSpecifics(directed); } /** - * Returns a set of all edges outgoing from the specified vertex. - *

- *

- * In the case of undirected graphs this method returns all edges touching the vertex, thus, - * some of the returned edges may have their source and target vertices in the opposite order. + * Create the specifics for the edges set of the graph. * - * @param vertex the vertex for which the list of outgoing edges to be returned. - * @return a set of all edges outgoing from the specified vertex. - * @throws IllegalArgumentException if vertex is not found in the graph. - * @throws NullPointerException if vertex is null. + * @param weighted if true the specifics should support weighted edges + * @return the specifics used for the edge set of this graph */ @Override - public Set outgoingEdgesOf(V vertex) { - return null; + protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) { + return super.createIntrusiveEdgesSpecifics(weighted); } /** - * Removes all the edges in this graph that are also contained in the specified edge collection. - * After this call returns, this graph will contain no edges in common with the specified edges. - * This method will invoke the {@link #removeEdge(Object)} method. - * - * @param edges edges to be removed from this graph. - * @return true if this graph changed as a result of the call - * @throws NullPointerException if the specified edge collection is - * null. - * @see #removeEdge(Object) - * @see #containsEdge(Object) + * @param edges + * @see Graph#removeAllEdges(Collection) */ @Override public boolean removeAllEdges(Collection edges) { - return false; + return super.removeAllEdges(edges); } /** - * Removes all the edges going from the specified source vertex to the specified target vertex, - * and returns a set of all removed edges. Returns null if any of the specified - * vertices does not exist in the graph. If both vertices exist but no edge is found, returns an - * empty set. This method will either invoke the {@link #removeEdge(Object)} method, or the - * {@link #removeEdge(Object, Object)} method. - * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @return the removed edges, or null if either vertex is not part of graph + * @param sourceVertex + * @param targetVertex + * @see Graph#removeAllEdges(Object, Object) */ @Override public Set removeAllEdges(V sourceVertex, V targetVertex) { - return null; + return super.removeAllEdges(sourceVertex, targetVertex); } /** - * Removes all the vertices in this graph that are also contained in the specified vertex - * collection. After this call returns, this graph will contain no vertices in common with the - * specified vertices. This method will invoke the {@link #removeVertex(Object)} method. - * - * @param vertices vertices to be removed from this graph. - * @return true if this graph changed as a result of the call - * @throws NullPointerException if the specified vertex collection is - * null. - * @see #removeVertex(Object) - * @see #containsVertex(Object) + * @param vertices + * @see Graph#removeAllVertices(Collection) */ @Override public boolean removeAllVertices(Collection vertices) { - return false; - } - - /** - * Removes an edge going from source vertex to target vertex, if such vertices and such edge - * exist in this graph. Returns the edge if removed or null otherwise. - * - * @param sourceVertex source vertex of the edge. - * @param targetVertex target vertex of the edge. - * @return The removed edge, or null if no edge removed. - */ - @Override - public E removeEdge(V sourceVertex, V targetVertex) { - return null; - } - - /** - * Removes the specified edge from the graph. Removes the specified edge from this graph if it - * is present. More formally, removes an edge - * e2 such that e2.equals(e), if the graph contains such edge. Returns - * true if the graph contained the specified edge. (The graph will not contain the - * specified edge once the call returns). - * - *

- * If the specified edge is null returns - * false. - *

- * - * @param e edge to be removed from this graph, if present. - * @return true if and only if the graph contained the specified edge. - */ - @Override - public boolean removeEdge(E e) { - return false; + return super.removeAllVertices(vertices); } /** - * Removes the specified vertex from this graph including all its touching edges if present. - * More formally, if the graph contains a vertex - * u such that u.equals(v), the call removes all edges that touch - * u and then removes u itself. If no such u is found, - * the call leaves the graph unchanged. Returns true if the graph contained the - * specified vertex. (The graph will not contain the specified vertex once the call returns). - * - *

- * If the specified vertex is null returns - * false. - *

+ * Ensures that the specified vertex exists in this graph, or else throws exception. * - * @param v vertex to be removed from this graph, if present. - * @return true if the graph contained the specified vertex; false - * otherwise. + * @param v vertex + * @return true if this assertion holds. + * @throws NullPointerException if specified vertex is null. + * @throws IllegalArgumentException if specified vertex does not exist in this graph. */ @Override - public boolean removeVertex(V v) { - return false; + protected boolean assertVertexExist(V v) { + return super.assertVertexExist(v); } /** - * Returns a set of the vertices contained in this graph. The set is backed by the graph, so - * changes to the graph are reflected in the set. If the graph is modified while an iteration - * over the set is in progress, the results of the iteration are undefined. - * - *

- * The graph implementation may maintain a particular set ordering (e.g. via - * {@link LinkedHashSet}) for deterministic iteration, but this is not required. It is - * the responsibility of callers who rely on this behavior to only use graph implementations - * which support it. - *

- * - * @return a set view of the vertices contained in this graph. - */ - @Override - public Set vertexSet() { - return null; - } - - /** - * Returns the source vertex of an edge. For an undirected graph, source and target are - * distinguishable designations (but without any mathematical meaning). - * - * @param e edge of interest - * @return source vertex - */ - @Override - public V getEdgeSource(E e) { - return null; - } - - /** - * Returns the target vertex of an edge. For an undirected graph, source and target are - * distinguishable designations (but without any mathematical meaning). - * - * @param e edge of interest - * @return target vertex - */ - @Override - public V getEdgeTarget(E e) { - return null; - } - - /** - * Get the graph type. The graph type can be used to query for additional metadata such as - * whether the graph supports directed or undirected edges, self-loops, multiple (parallel) - * edges, weights, etc. - * - * @return the graph type - */ - @Override - public GraphType getType() { - return null; - } - - /** - * Returns the weight assigned to a given edge. Unweighted graphs return 1.0 (as defined by - * {@link #DEFAULT_EDGE_WEIGHT}), allowing weighted-graph algorithms to apply to them when - * meaningful. + * Removes all the edges in this graph that are also contained in the specified edge array. + * After this call returns, this graph will contain no edges in common with the specified edges. + * This method will invoke the {@link Graph#removeEdge(Object)} method. * - * @param e edge of interest - * @return edge weight + * @param edges edges to be removed from this graph. + * @return true if this graph changed as a result of the call. + * @see Graph#removeEdge(Object) + * @see Graph#containsEdge(Object) */ @Override - public double getEdgeWeight(E e) { - return 0; + protected boolean removeAllEdges(E[] edges) { + return super.removeAllEdges(edges); } /** - * Assigns a weight to an edge. + * Helper for subclass implementations of toString( ). * - * @param e edge on which to set weight - * @param weight new weight for edge - * @throws UnsupportedOperationException if the graph does not support weights + * @param vertexSet the vertex set V to be printed + * @param edgeSet the edge set E to be printed + * @param directed true to use parens for each edge (representing directed); false to use curly + * braces (representing undirected) + * @return a string representation of (V,E) */ @Override - public void setEdgeWeight(E e, double weight) { - + protected String toStringFromSets(Collection vertexSet, Collection edgeSet, boolean directed) { + return super.toStringFromSets(vertexSet, edgeSet, directed); } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 4c1c084a5ae..fd05ddc9304 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -1,17 +1,21 @@ package org.jgrapht.intervalgraph; // BST helper node data type -private class Node { - private Key key; // key - private Value val; // associated data - private Node left, right; // links to left and right subtrees - private boolean color; // color of parent link - private int size; // subtree count +public class Node { + private K key; + private V val; + private Node leftChild, rightChild; + private boolean red; + private int size; - public Node(Key key, Value val, boolean color, int size) { + public Node(K key, V val, boolean red, int size) { this.key = key; this.val = val; - this.color = color; + this.red = red; this.size = size; } + + public boolean isRed() { + return red; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 58b093ad111..543a7f0d1ac 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -1,5 +1,17 @@ package org.jgrapht.intervalgraph; +import java.util.NoSuchElementException; + +/** + * Implementation of a Red-Black-Tree + * + * @param the key + * @param the value + * + * @author Daniel Mock (danielmock) + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ public class RedBlackTree implements BinarySearchTree { private Node root; @@ -9,7 +21,7 @@ public class RedBlackTree implements BinarySearchTree { * * @param key the key * @return the value associated with the given key. If the key is not in the tree, null is returned. - * @throws IllegalArgumentException if {@code key} is {@code null} + * @throws IllegalArgumentException if key is null */ @Override public V get(K key) { @@ -21,7 +33,7 @@ public V get(K key) { * * @param key the key * @return true if tree contains key, false otherwise - * @throws IllegalArgumentException if {@code key} is {@code null} + * @throws IllegalArgumentException if key is null */ @Override public boolean contains(K key) { @@ -34,7 +46,7 @@ public boolean contains(K key) { * * @param key the key * @param val the value - * @throws IllegalArgumentException if {@code key} is {@code null} + * @throws IllegalArgumentException if key is null */ @Override public void insert(K key, V val) { @@ -45,7 +57,7 @@ public void insert(K key, V val) { * Removes the specified key and its associated value from this tree * * @param key the key - * @throws IllegalArgumentException if {@code key} is {@code null} + * @throws IllegalArgumentException if key is null */ @Override public void delete(K key) { @@ -105,12 +117,12 @@ public K max() { } /** - * Returns the largest key in the tree less than or equal to {@code key}. + * Returns the largest key in the tree less than or equal to key. * * @param key the key - * @return the largest key in the tree less than or equal to {@code key} + * @return the largest key in the tree less than or equal to key * @throws NoSuchElementException if there is no such key - * @throws IllegalArgumentException if {@code key} is {@code null} + * @throws IllegalArgumentException if key is null */ @Override public K floor(K key) { @@ -118,12 +130,12 @@ public K floor(K key) { } /** - * Returns the smallest key in the tree greater than or equal to {@code key}. + * Returns the smallest key in the tree greater than or equal to key. * * @param key the key - * @return the smallest key in the tree greater than or equal to {@code key} + * @return the smallest key in the tree greater than or equal to key * @throws NoSuchElementException if there is no such key - * @throws IllegalArgumentException if {@code key} is {@code null} + * @throws IllegalArgumentException if key is null */ @Override public K ceiling(K key) { @@ -131,12 +143,12 @@ public K ceiling(K key) { } /** - * Return the key in the tree whose rank is {@code k}. + * Return the key in the tree whose rank is k. * This is the (k+1)st smallest key in the tree. * * @param k the position - * @return the key in the tree of rank {@code k} - * @throws IllegalArgumentException if {@code k} not in {0, ..., n-1} + * @return the key in the tree of rank k + * @throws IllegalArgumentException if k not in {0, ..., n-1} */ @Override public K select(int k) { @@ -144,11 +156,11 @@ public K select(int k) { } /** - * Return the number of keys in the tree strictly less than {@code key}. + * Return the number of keys in the tree strictly less than key. * * @param key the key - * @return the number of keys in the tree strictly less than {@code key} - * @throws IllegalArgumentException if {@code key} is {@code null} + * @return the number of keys in the tree strictly less than key + * @throws IllegalArgumentException if key is null */ @Override public int rank(K key) { @@ -156,11 +168,11 @@ public int rank(K key) { } /** - * Returns all keys in the symbol table as an {@code Iterable}. - * To iterate over all of the keys in the symbol table named {@code st}, - * use the foreach notation: {@code for (Key key : st.keys())}. + * Returns all keys in the symbol table as an Iterable. + * To iterate over all of the keys in the symbol table named st, + * use the foreach notation: for (Key key : st.keys()). * - * @return all keys in the symbol table as an {@code Iterable} + * @return all keys in the symbol table as an Iterable */ @Override public Iterable keys() { @@ -169,14 +181,14 @@ public Iterable keys() { /** * Returns all keys in the symbol table in the given range, - * as an {@code Iterable}. + * as an Iterable. * * @param min minimum endpoint * @param max maximum endpoint - * @return all keys in the sybol table between {@code lo} - * (inclusive) and {@code hi} (inclusive) as an {@code Iterable} - * @throws IllegalArgumentException if either {@code lo} or {@code hi} - * is {@code null} + * @return all keys in the sybol table between min + * (inclusive) and max (inclusive) as an Iterable + * @throws IllegalArgumentException if either min or max + * is null */ @Override public Iterable keys(K min, K max) { @@ -188,13 +200,31 @@ public Iterable keys(K min, K max) { * * @param min minimum endpoint * @param max maximum endpoint - * @return the number of keys in the sybol table between {@code lo} - * (inclusive) and {@code hi} (inclusive) - * @throws IllegalArgumentException if either {@code lo} or {@code hi} - * is {@code null} + * @return the number of keys in the sybol table between min + * (inclusive) and max (inclusive) + * @throws IllegalArgumentException if either min or max + * is null */ @Override public int size(K min, K max) { return 0; } + + /******************************************************************************************************************* + * HELPER METHODS * + ******************************************************************************************************************/ + + private Node rotateLeft(Node node) { + //TODO implementation: Christoph + return null; + } + + private Node rotateRight(Node node) { + //TODO implementation: Christoph + return null; + } + + private void changeColor(Node node) { + //TODO implementation: Christoph + } } From 63c42b8ea788174a850c47f1cafa1ffc333a969c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 17:05:40 +0200 Subject: [PATCH 008/131] first implementations of the interval graph data structure --- .../jgrapht/intervalgraph/IntervalGraph.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 52cc91b181a..49fc03f5b60 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -74,6 +74,7 @@ public boolean addEdge(V sourceVertex, V targetVertex, E e) { */ @Override public boolean addVertex(V v) { + //TODO implementation: Christoph return super.addVertex(v); } @@ -85,7 +86,7 @@ public boolean addVertex(V v) { */ @Override public E removeEdge(V sourceVertex, V targetVertex) { - return super.removeEdge(sourceVertex, targetVertex); + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** @@ -95,7 +96,7 @@ public E removeEdge(V sourceVertex, V targetVertex) { */ @Override public boolean removeEdge(E e) { - return super.removeEdge(e); + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** @@ -105,6 +106,7 @@ public boolean removeEdge(E e) { */ @Override public boolean removeVertex(V v) { + //TODO implementation: Christoph return super.removeVertex(v); } @@ -113,6 +115,8 @@ public boolean removeVertex(V v) { */ @Override public GraphType getType() { + //TODO implementation: Christoph + //TODO there ahs to be the property "interval graph" return super.getType(); } @@ -126,6 +130,7 @@ public GraphType getType() { */ @Override protected Specifics createSpecifics(boolean directed) { + //TODO implementation: Christoph return super.createSpecifics(directed); } @@ -137,6 +142,8 @@ protected Specifics createSpecifics(boolean directed) { */ @Override protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) { + //TODO implementation: Christoph + //TODO interval graphs have non-removable edges?! return super.createIntrusiveEdgesSpecifics(weighted); } @@ -146,7 +153,7 @@ protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean we */ @Override public boolean removeAllEdges(Collection edges) { - return super.removeAllEdges(edges); + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** @@ -156,7 +163,7 @@ public boolean removeAllEdges(Collection edges) { */ @Override public Set removeAllEdges(V sourceVertex, V targetVertex) { - return super.removeAllEdges(sourceVertex, targetVertex); + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** @@ -165,6 +172,8 @@ public Set removeAllEdges(V sourceVertex, V targetVertex) { */ @Override public boolean removeAllVertices(Collection vertices) { + //TODO implementation Christoph + //TODO then the graph is empty... return super.removeAllVertices(vertices); } @@ -178,6 +187,7 @@ public boolean removeAllVertices(Collection vertices) { */ @Override protected boolean assertVertexExist(V v) { + //TODO implementation Christoph return super.assertVertexExist(v); } @@ -193,7 +203,7 @@ protected boolean assertVertexExist(V v) { */ @Override protected boolean removeAllEdges(E[] edges) { - return super.removeAllEdges(edges); + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** @@ -207,6 +217,8 @@ protected boolean removeAllEdges(E[] edges) { */ @Override protected String toStringFromSets(Collection vertexSet, Collection edgeSet, boolean directed) { + //TODO implementation: Christoph + //TODO I do not know waht we have to do here?! return super.toStringFromSets(vertexSet, edgeSet, directed); } } From d5ee23639ea64718203fb3da82b6d697fc5cd181 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Wed, 18 Apr 2018 19:12:54 +0200 Subject: [PATCH 009/131] Added GraphTests.isIntervalGraph(graph) as an interface for the interval graph recognition algorithm and added documentation for this method Also: Added TODO since interval graph recognition algorithm class is missing right now. --- .../src/main/java/org/jgrapht/GraphTests.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java index 447bc1094c9..7fa433998a9 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java +++ b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java @@ -495,6 +495,23 @@ public static boolean isChordal(Graph graph){ Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL); return new ChordalityInspector<>(graph).isChordal(); } + + /** + * Tests whether a graph is an interval graph. + * Interval graphs are a familiy of graphs, which can be represented as intersections of intervals. + * The vertex are intervals on the real line and two vertices are connected if and only if the intervals of + * these vertices intersect each other. + * + * @param graph the input graph + * @param the graph vertex type + * @param the graph edge type + * @return true if the graph is an interval graph, false otherwise + * @see TODO + * + */ + public static boolean isIntervalGraph(Graph graph) { + throw new UnsupportedOperationException("Not yet implemented!"); //TODO: Implement + } /** * Tests whether an undirected graph meets Ore's condition to be Hamiltonian. From 939d68a9e3e5d66bc0e0076694805e3ab1dc91ce Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Wed, 18 Apr 2018 19:31:50 +0200 Subject: [PATCH 010/131] Added complete graph, circle graph and an arbitrary graph for testing the interval graph tester --- .../alg/interval/IntervalGraphTester.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java b/jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java new file mode 100644 index 00000000000..ace4dcc5715 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java @@ -0,0 +1,104 @@ +/* + * (C) Copyright 2017-2018, by TODO and Contributors. + * + * JGraphT : a free Java graph-theory library + * + * This program and the accompanying materials are dual-licensed under + * either + * + * (a) the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation, or (at your option) any + * later version. + * + * or (per the licensee's choosing) + * + * (b) the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation. + */ +package org.jgrapht.alg.interval; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.cycle.*; +import org.jgrapht.alg.util.*; +import org.jgrapht.generate.*; +import org.jgrapht.graph.*; +import org.junit.*; + +/** + * Test that correct interval graphs are detected and presentation is correct as well + * + * @author Ira Justus Fesefeldt + */ +public class IntervalGraphTester +{ + + @Test + public void completeGraphTest() + { + for(int i=0; i<10; i++) { + CompleteGraphGenerator cgg = + new CompleteGraphGenerator(i); + Graph cg = + new SimpleGraph<>(DefaultEdge.class); + cgg.generateGraph(cg, new IntegerVertexFactory(), null); + + //Every complete Graph is an interval graph + assertTrue(GraphTests.isIntervalGraph(cgg)); + } + + } + + @Test + public void circleGraphTest() + { + for(int i=4; i<10; i++) { + Graph graph = new SimpleGraph<>(DefaultEdge.class); + Graphs.addEdgeWithVertices(graph, 0, 1); + Graphs.addEdgeWithVertices(graph, 1, 2); + Graphs.addEdgeWithVertices(graph, 2, 3); + Graphs.addEdgeWithVertices(graph, 3, 4); + Graphs.addEdgeWithVertices(graph, 4, 5); + Graphs.addEdgeWithVertices(graph, 5, 0); + + //Every circle graph bigger than 4 is not an interval graph + assertFalse(GraphTests.isIntervalGraph(graph)); + } + } + + @Test + public void complexGraphTest() { + /* + * 0: [0,2], 1: [1,4], 2: [3,8], 3: [3,6], 4: [3,8], 5: [5,8], 6: [9,10] + * An arbitrary example for an interval graph + * + */ + + Graph graph = new SimpleGraph<>(DefaultEdge.class); + Graphs.addEdgeWithVertices(graph, 0, 1); + Graphs.addEdgeWithVertices(graph, 1, 2); + Graphs.addEdgeWithVertices(graph, 1, 3); + Graphs.addEdgeWithVertices(graph, 1, 4); + Graphs.addEdgeWithVertices(graph, 2, 3); + Graphs.addEdgeWithVertices(graph, 2, 4); + Graphs.addEdgeWithVertices(graph, 2, 5); + Graphs.addEdgeWithVertices(graph, 3, 4); + Graphs.addEdgeWithVertices(graph, 3, 5); + Graphs.addEdgeWithVertices(graph, 4, 5); + graph.addVertex(6); + + + assertTrue(GraphTests.isIntervalGraph(graph)); + + //Adding (5,6) and (6,0) creates an circle + graph.addEdge(5, 6); + graph.addEdge(6, 0); + assertFalse(GraphTests.isIntervalGraph(graph)); + } + +} From fb352880ad204781d47d89d48c8031325427342f Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Wed, 18 Apr 2018 19:37:04 +0200 Subject: [PATCH 011/131] changed real line to number line (since we actually use integers and finite graphs) --- jgrapht-core/src/main/java/org/jgrapht/GraphTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java index 7fa433998a9..83d8aa92f5c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java +++ b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java @@ -499,7 +499,7 @@ public static boolean isChordal(Graph graph){ /** * Tests whether a graph is an interval graph. * Interval graphs are a familiy of graphs, which can be represented as intersections of intervals. - * The vertex are intervals on the real line and two vertices are connected if and only if the intervals of + * The vertex are intervals on the number line and two vertices are connected if and only if the intervals of * these vertices intersect each other. * * @param graph the input graph From da72c33b283771ef5529da130b0f0f4aa3a0ce13 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Wed, 18 Apr 2018 19:44:16 +0200 Subject: [PATCH 012/131] typo --- jgrapht-core/src/main/java/org/jgrapht/GraphTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java index 83d8aa92f5c..a8f0b722b82 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java +++ b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java @@ -499,7 +499,7 @@ public static boolean isChordal(Graph graph){ /** * Tests whether a graph is an interval graph. * Interval graphs are a familiy of graphs, which can be represented as intersections of intervals. - * The vertex are intervals on the number line and two vertices are connected if and only if the intervals of + * The vertices are intervals on the number line and two vertices are connected if and only if the intervals of * these vertices intersect each other. * * @param graph the input graph From 9e4309296c80d8cfcb12e8efbfbd9029f94ddab7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Apr 2018 21:26:19 +0200 Subject: [PATCH 013/131] added IntervalSpecifics (not finished), finished IntervalGraph --- .../graph/specifics/IntervalSpecifics.java | 76 ++++++++++++ .../jgrapht/intervalgraph/IntervalGraph.java | 110 ++++-------------- 2 files changed, 98 insertions(+), 88 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java new file mode 100644 index 00000000000..bdfa9ec334f --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -0,0 +1,76 @@ +package org.jgrapht.graph.specifics; + +import org.jgrapht.EdgeFactory; +import org.jgrapht.graph.AbstractBaseGraph; +import org.jgrapht.graph.EdgeSetFactory; +import org.jgrapht.graph.specifics.ArrayUnenforcedSetEdgeSetFactory; +import org.jgrapht.graph.specifics.Specifics; +import org.jgrapht.graph.specifics.UndirectedEdgeContainer; +import org.jgrapht.intervalgraph.IntervalGraph; +import sun.jvm.hotspot.utilities.IntervalTree; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +public class IntervalSpecifics extends UndirectedSpecifics implements Specifics { + + //TODO implement interval specifics with IntervalTree + + protected IntervalGraph abstractBaseGraph; + protected IntervalTree vertexIntervalTree; //TODO anpassen + protected Map> vertexMapUndirected; + protected EdgeSetFactory edgeSetFactory; + + /** + * Construct a new interval specifics. + * + * @param abstractBaseGraph the graph for which these specifics are for + */ + public IntervalSpecifics(IntervalGraph abstractBaseGraph) { + super(abstractBaseGraph, new LinkedHashMap<>(), new ArrayUnenforcedSetEdgeSetFactory<>()); + this.vertexIntervalTree = new IntervalTree<>(); + } + + /** + * Construct a new interval specifics. + * + * @param abstractBaseGraph the graph for which these specifics are for + * @param edgeSetFactory factory for the creation of vertex edge sets + */ + public IntervalSpecifics(IntervalGraph abstractBaseGraph, EdgeSetFactory edgeSetFactory) { + super(abstractBaseGraph, new LinkedHashMap<>(), edgeSetFactory); + this.vertexIntervalTree = new IntervalTree<>(); + } + + /** + * Adds a vertex. + * + * @param vertex vertex to be added. + */ + @Override + public void addVertex(V vertex) { + getEdgeContainer(vertex); + vertexIntervalTree.add(vertex); + } + + /** + * Adds the specified edge to the edge containers of its source and target vertices. + * + * @param e the edge + */ + @Override + public void addEdgeToTouchingVertices(E e) { + throw new IllegalArgumentException(); + } + + /** + * Removes the specified edge from the edge containers of its source and target vertices. + * + * @param e the edge + */ + @Override + public void removeEdgeFromTouchingVertices(E e) { + throw new IllegalArgumentException(); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 49fc03f5b60..0e62c71d853 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -4,13 +4,13 @@ import org.jgrapht.Graph; import org.jgrapht.GraphType; import org.jgrapht.graph.AbstractBaseGraph; -import org.jgrapht.graph.AbstractGraph; import org.jgrapht.graph.IntrusiveEdgesSpecifics; -import org.jgrapht.graph.SimpleWeightedGraph; +import org.jgrapht.graph.specifics.IntervalSpecifics; import org.jgrapht.graph.specifics.Specifics; +import org.jgrapht.intervalgraph.interval.Interval; +import java.util.ArrayList; import java.util.Collection; -import java.util.LinkedHashSet; import java.util.Set; /** @@ -22,26 +22,23 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class IntervalGraph extends SimpleWeightedGraph { +public class IntervalGraph extends AbstractBaseGraph { - private static final String INTERVAL_GRAPH_ADD_EDGE = "Intervals of nodes define edges in interval graphs and cannot be modified manually"; + private static final long serialVersionUID = 7835287075273098344L; - /** - * Creates a new simple weighted graph with the specified edge factory. - * - * @param ef the edge factory of the new graph. - */ - public IntervalGraph(EdgeFactory ef) { - super(ef); - } + private static final String INTERVAL_GRAPH_ADD_EDGE = "Intervals of nodes define edges in interval graphs and cannot be modified manually"; /** - * Creates a new simple weighted graph. + * Construct a new graph. The graph can either be directed or undirected, depending on the + * specified edge factory. * - * @param edgeClass class on which to base factory for edges + * @param ef the edge factory of the new graph. + * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * @throws NullPointerException if the specified edge factory is + * null. */ - public IntervalGraph(Class edgeClass) { - super(edgeClass); + protected IntervalGraph(EdgeFactory ef, boolean weighted) { + super(ef, false, false, false, weighted); } /** @@ -67,17 +64,6 @@ public boolean addEdge(V sourceVertex, V targetVertex, E e) { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } - /** - * {@inheritDoc} - * - * @param v - */ - @Override - public boolean addVertex(V v) { - //TODO implementation: Christoph - return super.addVertex(v); - } - /** * {@inheritDoc} * @@ -106,8 +92,12 @@ public boolean removeEdge(E e) { */ @Override public boolean removeVertex(V v) { - //TODO implementation: Christoph - return super.removeVertex(v); + if (containsVertex(v)) { + super.removeVertex(v); // remove the vertex itself + return true; + } else { + return false; + } } /** @@ -115,8 +105,7 @@ public boolean removeVertex(V v) { */ @Override public GraphType getType() { - //TODO implementation: Christoph - //TODO there ahs to be the property "interval graph" + //TODO is that correct? -> Probably, we have to add a new mwtho to the DefaultGraphType class. return super.getType(); } @@ -130,21 +119,7 @@ public GraphType getType() { */ @Override protected Specifics createSpecifics(boolean directed) { - //TODO implementation: Christoph - return super.createSpecifics(directed); - } - - /** - * Create the specifics for the edges set of the graph. - * - * @param weighted if true the specifics should support weighted edges - * @return the specifics used for the edge set of this graph - */ - @Override - protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) { - //TODO implementation: Christoph - //TODO interval graphs have non-removable edges?! - return super.createIntrusiveEdgesSpecifics(weighted); + return new IntervalSpecifics<>(this); } /** @@ -166,31 +141,6 @@ public Set removeAllEdges(V sourceVertex, V targetVertex) { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } - /** - * @param vertices - * @see Graph#removeAllVertices(Collection) - */ - @Override - public boolean removeAllVertices(Collection vertices) { - //TODO implementation Christoph - //TODO then the graph is empty... - return super.removeAllVertices(vertices); - } - - /** - * Ensures that the specified vertex exists in this graph, or else throws exception. - * - * @param v vertex - * @return true if this assertion holds. - * @throws NullPointerException if specified vertex is null. - * @throws IllegalArgumentException if specified vertex does not exist in this graph. - */ - @Override - protected boolean assertVertexExist(V v) { - //TODO implementation Christoph - return super.assertVertexExist(v); - } - /** * Removes all the edges in this graph that are also contained in the specified edge array. * After this call returns, this graph will contain no edges in common with the specified edges. @@ -205,20 +155,4 @@ protected boolean assertVertexExist(V v) { protected boolean removeAllEdges(E[] edges) { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } - - /** - * Helper for subclass implementations of toString( ). - * - * @param vertexSet the vertex set V to be printed - * @param edgeSet the edge set E to be printed - * @param directed true to use parens for each edge (representing directed); false to use curly - * braces (representing undirected) - * @return a string representation of (V,E) - */ - @Override - protected String toStringFromSets(Collection vertexSet, Collection edgeSet, boolean directed) { - //TODO implementation: Christoph - //TODO I do not know waht we have to do here?! - return super.toStringFromSets(vertexSet, edgeSet, directed); - } } From 24e8f309714a332ccdadb028f267774f6c6c3fbc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 12:48:34 +0200 Subject: [PATCH 014/131] finished first implementation of interval graph, added intervalGraphVertexContainer as container for vertices --- .../graph/specifics/IntervalSpecifics.java | 235 ++++++++-- .../jgrapht/intervalgraph/IntervalGraph.java | 404 +++++++++++++++--- .../IntervalGraphVertexContainer.java | 32 ++ .../jgrapht/intervalgraph/IntervalTree.java | 7 + .../intervalgraph/IntervalVertexTree.java | 43 ++ .../java/org/jgrapht/intervalgraph/Node.java | 7 +- .../jgrapht/intervalgraph/RedBlackTree.java | 5 +- 7 files changed, 633 insertions(+), 100 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index bdfa9ec334f..5934be39740 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -1,76 +1,233 @@ package org.jgrapht.graph.specifics; -import org.jgrapht.EdgeFactory; -import org.jgrapht.graph.AbstractBaseGraph; import org.jgrapht.graph.EdgeSetFactory; -import org.jgrapht.graph.specifics.ArrayUnenforcedSetEdgeSetFactory; -import org.jgrapht.graph.specifics.Specifics; -import org.jgrapht.graph.specifics.UndirectedEdgeContainer; import org.jgrapht.intervalgraph.IntervalGraph; -import sun.jvm.hotspot.utilities.IntervalTree; +import org.jgrapht.intervalgraph.IntervalGraphVertexContainer; +import org.jgrapht.intervalgraph.IntervalVertexTree; +import org.jgrapht.util.ArrayUnenforcedSet; -import java.util.LinkedHashMap; -import java.util.Map; +import java.io.Serializable; import java.util.Set; -public class IntervalSpecifics extends UndirectedSpecifics implements Specifics { +public class IntervalSpecifics implements Specifics, Serializable { - //TODO implement interval specifics with IntervalTree + private static final long serialVersionUID = 1112673663745687843L; - protected IntervalGraph abstractBaseGraph; - protected IntervalTree vertexIntervalTree; //TODO anpassen - protected Map> vertexMapUndirected; + protected IntervalGraph intervalGraph; + protected IntervalGraphVertexContainer intervalGraphVertexContainer; //TODO anpassen protected EdgeSetFactory edgeSetFactory; /** * Construct a new interval specifics. * - * @param abstractBaseGraph the graph for which these specifics are for + * @param intervalGraph the graph for which these specifics are for */ - public IntervalSpecifics(IntervalGraph abstractBaseGraph) { - super(abstractBaseGraph, new LinkedHashMap<>(), new ArrayUnenforcedSetEdgeSetFactory<>()); - this.vertexIntervalTree = new IntervalTree<>(); + public IntervalSpecifics(IntervalGraph intervalGraph) { + this.intervalGraph = intervalGraph; + this.intervalGraphVertexContainer = new IntervalVertexTree<>(); + this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); } /** - * Construct a new interval specifics. - * - * @param abstractBaseGraph the graph for which these specifics are for - * @param edgeSetFactory factory for the creation of vertex edge sets + * {@inheritDoc} */ - public IntervalSpecifics(IntervalGraph abstractBaseGraph, EdgeSetFactory edgeSetFactory) { - super(abstractBaseGraph, new LinkedHashMap<>(), edgeSetFactory); - this.vertexIntervalTree = new IntervalTree<>(); + @Override + public void addVertex(V v) + { + getEdgeContainer(v); } /** - * Adds a vertex. * - * @param vertex vertex to be added. + */ + public void removeVertex(V v) { + //TODO + } + + /** + * {@inheritDoc} */ @Override - public void addVertex(V vertex) { - getEdgeContainer(vertex); - vertexIntervalTree.add(vertex); + public Set getVertexSet() + { + return intervalGraphVertexContainer.getVertexSet(); } /** - * Adds the specified edge to the edge containers of its source and target vertices. - * - * @param e the edge + * {@inheritDoc} */ @Override - public void addEdgeToTouchingVertices(E e) { - throw new IllegalArgumentException(); + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set edges = null; + + if (intervalGraph.containsVertex(sourceVertex) + && intervalGraph.containsVertex(targetVertex)) + { + edges = new ArrayUnenforcedSet<>(); + + for (E e : getEdgeContainer(sourceVertex).vertexEdges) { + boolean equal = isEqualsStraightOrInverted(sourceVertex, targetVertex, e); + + if (equal) { + edges.add(e); + } + } + } + + return edges; } /** - * Removes the specified edge from the edge containers of its source and target vertices. - * - * @param e the edge + * {@inheritDoc} + */ + @Override + public E getEdge(V sourceVertex, V targetVertex) + { + if (intervalGraph.containsVertex(sourceVertex) + && intervalGraph.containsVertex(targetVertex)) + { + + for (E e : getEdgeContainer(sourceVertex).vertexEdges) { + boolean equal = isEqualsStraightOrInverted(sourceVertex, targetVertex, e); + + if (equal) { + return e; + } + } + } + + return null; + } + + private boolean isEqualsStraightOrInverted(Object sourceVertex, Object targetVertex, E e) + { + boolean equalStraight = sourceVertex.equals(intervalGraph.getEdgeSource(e)) + && targetVertex.equals(intervalGraph.getEdgeTarget(e)); + + boolean equalInverted = sourceVertex.equals(intervalGraph.getEdgeTarget(e)) + && targetVertex.equals(intervalGraph.getEdgeSource(e)); + return equalStraight || equalInverted; + } + + /** + * {@inheritDoc} + */ + @Override + public void addEdgeToTouchingVertices(E e) + { + V source = intervalGraph.getEdgeSource(e); + V target = intervalGraph.getEdgeTarget(e); + + getEdgeContainer(source).addEdge(e); + + if (!source.equals(target)) { + getEdgeContainer(target).addEdge(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public int degreeOf(V vertex) + { + if (intervalGraph.isAllowingLoops()) { // then we must count, and add loops twice + int degree = 0; + Set edges = getEdgeContainer(vertex).vertexEdges; + + for (E e : edges) { + if (intervalGraph.getEdgeSource(e).equals(intervalGraph.getEdgeTarget(e))) { + degree += 2; + } else { + degree += 1; + } + } + + return degree; + } else { + return getEdgeContainer(vertex).edgeCount(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public Set edgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * {@inheritDoc} */ @Override - public void removeEdgeFromTouchingVertices(E e) { - throw new IllegalArgumentException(); + public int inDegreeOf(V vertex) + { + return degreeOf(vertex); } + + /** + * {@inheritDoc} + */ + @Override + public Set incomingEdgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * {@inheritDoc} + */ + @Override + public int outDegreeOf(V vertex) + { + return degreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set outgoingEdgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeEdgeFromTouchingVertices(E e) + { + V source = intervalGraph.getEdgeSource(e); + V target = intervalGraph.getEdgeTarget(e); + + getEdgeContainer(source).removeEdge(e); + + if (!source.equals(target)) { + getEdgeContainer(target).removeEdge(e); + } + } + + /** + * Get the edge container for a specified vertex. + * + * @param vertex a vertex in this graph + * + * @return an edge container + */ + protected UndirectedEdgeContainer getEdgeContainer(V vertex) + { + UndirectedEdgeContainer ec = intervalGraphVertexContainer.get(vertex); + + if (ec == null) { + ec = new UndirectedEdgeContainer<>(edgeSetFactory, vertex); + intervalGraphVertexContainer.put(vertex, ec); + } + + return ec; + } + } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 0e62c71d853..6dffe5b4997 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -3,15 +3,17 @@ import org.jgrapht.EdgeFactory; import org.jgrapht.Graph; import org.jgrapht.GraphType; -import org.jgrapht.graph.AbstractBaseGraph; -import org.jgrapht.graph.IntrusiveEdgesSpecifics; +import org.jgrapht.Graphs; +import org.jgrapht.graph.*; +import org.jgrapht.graph.specifics.FastLookupDirectedSpecifics; +import org.jgrapht.graph.specifics.FastLookupUndirectedSpecifics; import org.jgrapht.graph.specifics.IntervalSpecifics; import org.jgrapht.graph.specifics.Specifics; import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.util.TypeUtil; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Set; +import java.io.Serializable; +import java.util.*; /** * Implementation of an Interval Graph @@ -22,78 +24,331 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class IntervalGraph extends AbstractBaseGraph { +public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { private static final long serialVersionUID = 7835287075273098344L; private static final String INTERVAL_GRAPH_ADD_EDGE = "Intervals of nodes define edges in interval graphs and cannot be modified manually"; + private static final String GRAPH_SPECIFICS_MUST_NOT_BE_NULL = "Graph specifics must not be null"; + + private EdgeFactory edgeFactory; + private transient Set unmodifiableVertexSet = null; + + private IntervalSpecifics specifics; + private IntrusiveEdgesSpecifics intrusiveEdgesSpecifics; + + private boolean directed; + private boolean weighted; + private boolean allowingMultipleEdges; + private boolean allowingLoops; /** * Construct a new graph. The graph can either be directed or undirected, depending on the * specified edge factory. * - * @param ef the edge factory of the new graph. - * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * @param ef the edge factory of the new graph. + * @param directed if true the graph will be directed, otherwise undirected + * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. + * @param allowLoops whether to allow edges that are self-loops or not. + * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * * @throws NullPointerException if the specified edge factory is - * null. + * null. */ - protected IntervalGraph(EdgeFactory ef, boolean weighted) { - super(ef, false, false, false, weighted); + protected IntervalGraph( + EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, + boolean weighted) + { + Objects.requireNonNull(ef); + + this.edgeFactory = ef; + this.allowingLoops = allowLoops; + this.allowingMultipleEdges = allowMultipleEdges; + this.directed = directed; + this.specifics = + Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + this.weighted = weighted; + this.intrusiveEdgesSpecifics = Objects.requireNonNull( + createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); } + /** * {@inheritDoc} + */ + @Override + public Set getAllEdges(V sourceVertex, V targetVertex) + { + return specifics.getAllEdges(sourceVertex, targetVertex); + } + + /** + * Returns true if and only if self-loops are allowed in this graph. A self loop is + * an edge that its source and target vertices are the same. * - * @param sourceVertex - * @param targetVertex + * @return true if and only if graph loops are allowed. + */ + public boolean isAllowingLoops() + { + return allowingLoops; + } + + /** + * Returns true if and only if multiple (parallel) edges are allowed in this graph. The + * meaning of multiple edges is that there can be many edges going from vertex v1 to vertex v2. + * + * @return true if and only if multiple (parallel) edges are allowed. + */ + public boolean isAllowingMultipleEdges() + { + return allowingMultipleEdges; + } + + /** + * Returns true if and only if the graph supports edge weights. + * + * @return true if the graph supports edge weights, false otherwise. + */ + public boolean isWeighted() + { + return weighted; + } + + /** + * Returns true if the graph is directed, false if undirected. + * + * @return true if the graph is directed, false if undirected. + */ + public boolean isDirected() + { + return directed; + } + + /** + * {@inheritDoc} + */ + @Override + public E getEdge(V sourceVertex, V targetVertex) + { + return specifics.getEdge(sourceVertex, targetVertex); + } + + /** + * {@inheritDoc} + */ + @Override + public EdgeFactory getEdgeFactory() + { + return edgeFactory; + } + + /** + * {@inheritDoc} */ @Override - public E addEdge(V sourceVertex, V targetVertex) { + public E addEdge(V sourceVertex, V targetVertex) + { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** * {@inheritDoc} - * - * @param sourceVertex - * @param targetVertex - * @param e */ @Override - public boolean addEdge(V sourceVertex, V targetVertex, E e) { + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** * {@inheritDoc} + */ + @Override + public boolean addVertex(V v) + { + if (v == null) { + throw new NullPointerException(); + } else if (containsVertex(v)) { + return false; + } else { + specifics.addVertex(v); + + return true; + } + } + + /** + * {@inheritDoc} + */ + @Override + public V getEdgeSource(E e) + { + return intrusiveEdgesSpecifics.getEdgeSource(e); + } + + /** + * {@inheritDoc} + */ + @Override + public V getEdgeTarget(E e) + { + return intrusiveEdgesSpecifics.getEdgeTarget(e); + } + + /** + * Returns a shallow copy of this graph instance. Neither edges nor vertices are cloned. + * + * @return a shallow copy of this graph. * - * @param sourceVertex - * @param targetVertex + * @throws RuntimeException in case the clone is not supported + * + * @see java.lang.Object#clone() + */ + @Override + public Object clone() + { + try { + IntervalGraph newGraph = TypeUtil.uncheckedCast(super.clone()); + + newGraph.edgeFactory = this.edgeFactory; + newGraph.unmodifiableVertexSet = null; + + // NOTE: it's important for this to happen in an object + // method so that the new inner class instance gets associated with + // the right outer class instance + newGraph.specifics = newGraph.createSpecifics(this.directed); + newGraph.intrusiveEdgesSpecifics = + newGraph.createIntrusiveEdgesSpecifics(this.weighted); + + Graphs.addGraph(newGraph, this); + + return newGraph; + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + throw new RuntimeException(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean containsEdge(E e) + { + return intrusiveEdgesSpecifics.containsEdge(e); + } + + /** + * {@inheritDoc} */ @Override - public E removeEdge(V sourceVertex, V targetVertex) { + public boolean containsVertex(V v) + { + return specifics.getVertexSet().contains(v); + } + + /** + * {@inheritDoc} + */ + @Override + public int degreeOf(V vertex) + { + assertVertexExist(vertex); + return specifics.degreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set edgeSet() + { + return intrusiveEdgesSpecifics.getEdgeSet(); + } + + /** + * {@inheritDoc} + */ + @Override + public Set edgesOf(V vertex) + { + assertVertexExist(vertex); + return specifics.edgesOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public int inDegreeOf(V vertex) + { + assertVertexExist(vertex); + return specifics.inDegreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set incomingEdgesOf(V vertex) + { + assertVertexExist(vertex); + return specifics.incomingEdgesOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public int outDegreeOf(V vertex) + { + assertVertexExist(vertex); + return specifics.outDegreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set outgoingEdgesOf(V vertex) + { + assertVertexExist(vertex); + return specifics.outgoingEdgesOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public E removeEdge(V sourceVertex, V targetVertex) + { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** * {@inheritDoc} - * - * @param e */ @Override - public boolean removeEdge(E e) { + public boolean removeEdge(E e) + { throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); } /** * {@inheritDoc} - * - * @param v */ @Override - public boolean removeVertex(V v) { + public boolean removeVertex(V v) + { if (containsVertex(v)) { - super.removeVertex(v); // remove the vertex itself + Set touchingEdgesList = edgesOf(v); + + // cannot iterate over list - will cause + // ConcurrentModificationException + removeAllEdges(new ArrayList<>(touchingEdgesList)); + + specifics.removeVertex(v);// remove the vertex itself + return true; } else { return false; @@ -104,55 +359,86 @@ public boolean removeVertex(V v) { * {@inheritDoc} */ @Override - public GraphType getType() { - //TODO is that correct? -> Probably, we have to add a new mwtho to the DefaultGraphType class. - return super.getType(); + public Set vertexSet() + { + if (unmodifiableVertexSet == null) { + unmodifiableVertexSet = Collections.unmodifiableSet(specifics.getVertexSet()); + } + + return unmodifiableVertexSet; } /** - * Create the specifics for this graph. Subclasses can override this method in order to adjust - * the specifics and thus the space-time tradeoffs of the graph implementation. - * - * @param directed if true the specifics should adjust the behavior to a directed graph - * otherwise undirected - * @return the specifics used by this graph + * {@inheritDoc} */ @Override - protected Specifics createSpecifics(boolean directed) { - return new IntervalSpecifics<>(this); + public double getEdgeWeight(E e) + { + if (e == null) { + throw new NullPointerException(); + } + return intrusiveEdgesSpecifics.getEdgeWeight(e); } /** - * @param edges - * @see Graph#removeAllEdges(Collection) + * Set an edge weight. + * + * @param e the edge + * @param weight the weight + * @throws UnsupportedOperationException if the graph is not weighted */ @Override - public boolean removeAllEdges(Collection edges) { - throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + public void setEdgeWeight(E e, double weight) + { + if (e == null) { + throw new NullPointerException(); + } + intrusiveEdgesSpecifics.setEdgeWeight(e, weight); } /** - * @param sourceVertex - * @param targetVertex - * @see Graph#removeAllEdges(Object, Object) + * {@inheritDoc} */ @Override - public Set removeAllEdges(V sourceVertex, V targetVertex) { - throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + public GraphType getType() + { + //TODO + if (directed) { + return new DefaultGraphType.Builder() + .directed().weighted(weighted).allowMultipleEdges(allowingMultipleEdges) + .allowSelfLoops(allowingLoops).build(); + } else { + return new DefaultGraphType.Builder() + .undirected().weighted(weighted).allowMultipleEdges(allowingMultipleEdges) + .allowSelfLoops(allowingLoops).build(); + } } /** - * Removes all the edges in this graph that are also contained in the specified edge array. - * After this call returns, this graph will contain no edges in common with the specified edges. - * This method will invoke the {@link Graph#removeEdge(Object)} method. + * Create the specifics for this graph. Subclasses can override this method in order to adjust + * the specifics and thus the space-time tradeoffs of the graph implementation. * - * @param edges edges to be removed from this graph. - * @return true if this graph changed as a result of the call. - * @see Graph#removeEdge(Object) - * @see Graph#containsEdge(Object) + * @param directed if true the specifics should adjust the behavior to a directed graph + * otherwise undirected + * @return the specifics used by this graph */ - @Override - protected boolean removeAllEdges(E[] edges) { - throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + protected IntervalSpecifics createSpecifics(boolean directed) + { + return new IntervalSpecifics<>(this); + } + + /** + * Create the specifics for the edges set of the graph. + * + * @param weighted if true the specifics should support weighted edges + * @return the specifics used for the edge set of this graph + */ + protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) + { + if (weighted) { + return new WeightedIntrusiveEdgesSpecifics<>(); + } else { + return new UniformIntrusiveEdgesSpecifics<>(); + } } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java new file mode 100644 index 00000000000..14595818119 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -0,0 +1,32 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.graph.specifics.UndirectedEdgeContainer; + +import java.io.Serializable; +import java.util.Set; + +public interface IntervalGraphVertexContainer { + + /** + * Returns the whole vertex set of the graph. + * + * @return all vertices of the graph in a set + */ + Set getVertexSet(); + + /** + * Returns the edge container to the vertex + * + * @param vertex the vertex + * @return the edge container to the vertex + */ + UndirectedEdgeContainer get(V vertex); + + /** + * puts the given edge container to the data structure + * + * @param vertex the vertex + * @param ec the edge container + */ + void put(V vertex, UndirectedEdgeContainer ec); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java new file mode 100644 index 00000000000..0432344e851 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java @@ -0,0 +1,7 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; + +public class IntervalTree implements Serializable { + private static final long serialVersionUID = 2834567756342332325L; +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java new file mode 100644 index 00000000000..f9d0796003b --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java @@ -0,0 +1,43 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.graph.specifics.UndirectedEdgeContainer; + +import java.io.Serializable; +import java.util.Set; + +public class IntervalVertexTree implements IntervalGraphVertexContainer, Serializable { + + private static final long serialVersionUID = 7768940080894764546L; + + /** + * Returns the whole vertex set of the graph. + * + * @return all vertices of the graph in a set + */ + @Override + public Set getVertexSet() { + return null; + } + + /** + * Returns the edge container to the vertex + * + * @param vertex the vertex + * @return the edge container to the vertex + */ + @Override + public UndirectedEdgeContainer get(Object vertex) { + return null; + } + + /** + * puts the given edge container to the data structure + * + * @param vertex the vertex + * @param ec the edge container + */ + @Override + public void put(Object vertex, UndirectedEdgeContainer ec) { + + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index fd05ddc9304..9551d64fe34 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -1,7 +1,12 @@ package org.jgrapht.intervalgraph; +import java.io.Serializable; + // BST helper node data type -public class Node { +public class Node implements Serializable { + + private static final long serialVersionUID = 5674337686253743843L; + private K key; private V val; private Node leftChild, rightChild; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 543a7f0d1ac..c79147626e5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -1,5 +1,6 @@ package org.jgrapht.intervalgraph; +import java.io.Serializable; import java.util.NoSuchElementException; /** @@ -12,7 +13,9 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class RedBlackTree implements BinarySearchTree { +public class RedBlackTree implements BinarySearchTree, Serializable { + + private static final long serialVersionUID = 1199228564356373435L; private Node root; From fa76b5dd8de75f4ebe29dae9dcb5e8350faa3ae6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 14:19:39 +0200 Subject: [PATCH 015/131] modified interval graph data structures --- .../graph/specifics/IntervalSpecifics.java | 3 +- .../jgrapht/intervalgraph/IntervalGraph.java | 23 +++++++++++++++ .../IntervalGraphVertexContainer.java | 20 +++++++++++-- .../intervalgraph/IntervalVertexTree.java | 28 ++++++++++++++++++- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index 5934be39740..33b585fe58d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -35,13 +35,14 @@ public IntervalSpecifics(IntervalGraph intervalGraph) { public void addVertex(V v) { getEdgeContainer(v); + intervalGraph.addIntervalEdges(v, intervalGraphVertexContainer.getOverlappingIntervalVertices(v)); } /** * */ public void removeVertex(V v) { - //TODO + intervalGraphVertexContainer.remove(v); } /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 6dffe5b4997..24aa547c80a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -441,4 +441,27 @@ protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean we return new UniformIntrusiveEdgesSpecifics<>(); } } + + /** + * Adds edges between sourceVertex and every vertex from vertices + * This method should only be called from IntervalSpecifics, because interval graphs have by intervals defined edges. + * + * @param sourceVertex source vertex of all edges + * @param targetVertices target vertices of edges + */ + public boolean addIntervalEdges(V sourceVertex, Collection targetVertices) { + + assertVertexExist(sourceVertex); + + for(V targetVertex: targetVertices) { + assertVertexExist(targetVertex); + + E e = edgeFactory.createEdge(sourceVertex, targetVertex); + + if(intrusiveEdgesSpecifics.add(e, sourceVertex, targetVertex)) { + specifics.addEdgeToTouchingVertices(e); + } + } + return true; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 14595818119..2d12caa973d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -3,6 +3,7 @@ import org.jgrapht.graph.specifics.UndirectedEdgeContainer; import java.io.Serializable; +import java.util.List; import java.util.Set; public interface IntervalGraphVertexContainer { @@ -14,6 +15,13 @@ public interface IntervalGraphVertexContainer { */ Set getVertexSet(); + /** + * returns a list of all vertices with overlapping interval w.r.t v + * + * @param v the vertex with interval + */ + public List getOverlappingIntervalVertices(V v); + /** * Returns the edge container to the vertex * @@ -26,7 +34,15 @@ public interface IntervalGraphVertexContainer { * puts the given edge container to the data structure * * @param vertex the vertex - * @param ec the edge container + * @param ec the edge container + */ + public boolean put(V vertex, UndirectedEdgeContainer ec); + + /** + * Removes a vertex from the data structure if it is present. + * + * @param vertex the vertex to be removed + * @return true if this data structure contained the specified element */ - void put(V vertex, UndirectedEdgeContainer ec); + public boolean remove(V vertex); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java index f9d0796003b..1cdaee4e5e3 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java @@ -3,12 +3,17 @@ import org.jgrapht.graph.specifics.UndirectedEdgeContainer; import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Set; public class IntervalVertexTree implements IntervalGraphVertexContainer, Serializable { private static final long serialVersionUID = 7768940080894764546L; + private IntervalTree intervalTree; + private LinkedHashMap vertexSet; + /** * Returns the whole vertex set of the graph. * @@ -16,6 +21,16 @@ public class IntervalVertexTree implements IntervalGraphVertexContainer getVertexSet() { + return vertexSet.keySet(); + } + + /** + * returns a list of all vertices with overlapping interval w.r.t v + * + * @param v the vertex with interval + */ + @Override + public List getOverlappingIntervalVertices(V v) { return null; } @@ -37,7 +52,18 @@ public UndirectedEdgeContainer get(Object vertex) { * @param ec the edge container */ @Override - public void put(Object vertex, UndirectedEdgeContainer ec) { + public boolean put(V vertex, UndirectedEdgeContainer ec) { + return false; + } + /** + * Removes a vertex from the data structure if it is present. + * + * @param vertex the vertex to be removed + * @return true if this data structure contained the specified element + */ + @Override + public boolean remove(V vertex) { + return false; } } From 758458cba220e50de8998fd669c07378f2e46852 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 14:21:09 +0200 Subject: [PATCH 016/131] added constructor to IntervalVertexTree --- .../java/org/jgrapht/intervalgraph/IntervalVertexTree.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java index 1cdaee4e5e3..f56c442765a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java @@ -14,6 +14,11 @@ public class IntervalVertexTree implements IntervalGraphVertexContainer vertexSet; + public IntervalVertexTree() { + this.intervalTree = new IntervalTree(); + this.vertexSet = new LinkedHashMap<>(); + } + /** * Returns the whole vertex set of the graph. * From ce4a8903348b5d78a7c1bf574ff0f35c73211e25 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 14:34:48 +0200 Subject: [PATCH 017/131] implemented necessary getter and setter for node --- .../java/org/jgrapht/intervalgraph/Node.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 9551d64fe34..c9ca7f5a90a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -20,7 +20,43 @@ public Node(K key, V val, boolean red, int size) { this.size = size; } + public void setLeftChild(Node leftChild) { + this.leftChild = leftChild; + } + + public void setRightChild(Node rightChild) { + this.rightChild = rightChild; + } + + public void setRed(boolean red) { + this.red = red; + } + + public void setSize(int size) { + this.size = size; + } + public boolean isRed() { return red; } + + public K getKey() { + return key; + } + + public V getVal() { + return val; + } + + public Node getLeftChild() { + return leftChild; + } + + public Node getRightChild() { + return rightChild; + } + + public int getSize() { + return size; + } } From b34d408724f2ddaddfad472b404c482722402a7b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 14:35:31 +0200 Subject: [PATCH 018/131] added methods for rotation and color flipping to red black tree --- .../jgrapht/intervalgraph/RedBlackTree.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index c79147626e5..b0318af62a3 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -218,16 +218,30 @@ public int size(K min, K max) { ******************************************************************************************************************/ private Node rotateLeft(Node node) { - //TODO implementation: Christoph - return null; + Node rightChild = node.getRightChild(); + node.setRightChild(rightChild.getLeftChild()); + rightChild.setLeftChild(node); + rightChild.setRed(rightChild.getLeftChild().isRed()); + rightChild.getLeftChild().setRed(true); + rightChild.setSize(node.getSize()); + node.setSize(node.getLeftChild().getSize() + node.getRightChild().getSize() + 1); + return rightChild; } private Node rotateRight(Node node) { - //TODO implementation: Christoph - return null; + Node leftChild = node.getLeftChild(); + node.setLeftChild(leftChild.getRightChild()); + leftChild.setRightChild(node); + leftChild.setRed(leftChild.getRightChild().isRed()); + leftChild.getRightChild().setRed(true); + leftChild.setSize(node.getSize()); + node.setSize(node.getLeftChild().getSize() + node.getRightChild().getSize() + 1); + return leftChild; } private void changeColor(Node node) { - //TODO implementation: Christoph + node.setRed(!node.isRed()); + node.getRightChild().setRed(!node.getRightChild().isRed()); + node.getLeftChild().setRed(!node.getLeftChild().isRed()); } } From 2d6a6832a3da0ead3b31e15c4d5bed6173217fb2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 14:38:21 +0200 Subject: [PATCH 019/131] made methods of node protected --- .../java/org/jgrapht/intervalgraph/Node.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index c9ca7f5a90a..3c7a0a85316 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -20,43 +20,43 @@ public Node(K key, V val, boolean red, int size) { this.size = size; } - public void setLeftChild(Node leftChild) { + protected void setLeftChild(Node leftChild) { this.leftChild = leftChild; } - public void setRightChild(Node rightChild) { + protected void setRightChild(Node rightChild) { this.rightChild = rightChild; } - public void setRed(boolean red) { + protected void setRed(boolean red) { this.red = red; } - public void setSize(int size) { + protected void setSize(int size) { this.size = size; } - public boolean isRed() { + protected boolean isRed() { return red; } - public K getKey() { + protected K getKey() { return key; } - public V getVal() { + protected V getVal() { return val; } - public Node getLeftChild() { + protected Node getLeftChild() { return leftChild; } - public Node getRightChild() { + protected Node getRightChild() { return rightChild; } - public int getSize() { + protected int getSize() { return size; } } From bcf622a384b734ce5db4aa5302809804a8c1830d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 15:24:23 +0200 Subject: [PATCH 020/131] added interface for IntervalTree, modified implementations --- .../graph/specifics/IntervalSpecifics.java | 16 +++---- .../IntervalGraphVertexContainer.java | 44 ++++++++++++++++--- ...ntervalGraphVertexContainerInterface.java} | 38 +++------------- .../jgrapht/intervalgraph/IntervalTree.java | 38 +++++++++++++++- .../intervalgraph/IntervalTreeInterface.java | 32 ++++++++++++++ 5 files changed, 121 insertions(+), 47 deletions(-) rename jgrapht-core/src/main/java/org/jgrapht/intervalgraph/{IntervalVertexTree.java => IntervalGraphVertexContainerInterface.java} (51%) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index 33b585fe58d..d26f8100b27 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -2,8 +2,8 @@ import org.jgrapht.graph.EdgeSetFactory; import org.jgrapht.intervalgraph.IntervalGraph; +import org.jgrapht.intervalgraph.IntervalGraphVertexContainerInterface; import org.jgrapht.intervalgraph.IntervalGraphVertexContainer; -import org.jgrapht.intervalgraph.IntervalVertexTree; import org.jgrapht.util.ArrayUnenforcedSet; import java.io.Serializable; @@ -14,7 +14,7 @@ public class IntervalSpecifics implements Specifics, Serializable { private static final long serialVersionUID = 1112673663745687843L; protected IntervalGraph intervalGraph; - protected IntervalGraphVertexContainer intervalGraphVertexContainer; //TODO anpassen + protected IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; //TODO anpassen protected EdgeSetFactory edgeSetFactory; /** @@ -24,7 +24,7 @@ public class IntervalSpecifics implements Specifics, Serializable { */ public IntervalSpecifics(IntervalGraph intervalGraph) { this.intervalGraph = intervalGraph; - this.intervalGraphVertexContainer = new IntervalVertexTree<>(); + this.intervalGraphVertexContainerInterface = new IntervalGraphVertexContainer<>(); this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); } @@ -35,14 +35,14 @@ public IntervalSpecifics(IntervalGraph intervalGraph) { public void addVertex(V v) { getEdgeContainer(v); - intervalGraph.addIntervalEdges(v, intervalGraphVertexContainer.getOverlappingIntervalVertices(v)); + intervalGraph.addIntervalEdges(v, intervalGraphVertexContainerInterface.getOverlappingIntervalVertices(v)); } /** * */ public void removeVertex(V v) { - intervalGraphVertexContainer.remove(v); + intervalGraphVertexContainerInterface.remove(v); } /** @@ -51,7 +51,7 @@ public void removeVertex(V v) { @Override public Set getVertexSet() { - return intervalGraphVertexContainer.getVertexSet(); + return intervalGraphVertexContainerInterface.getVertexMap(); } /** @@ -221,11 +221,11 @@ public void removeEdgeFromTouchingVertices(E e) */ protected UndirectedEdgeContainer getEdgeContainer(V vertex) { - UndirectedEdgeContainer ec = intervalGraphVertexContainer.get(vertex); + UndirectedEdgeContainer ec = intervalGraphVertexContainerInterface.get(vertex); if (ec == null) { ec = new UndirectedEdgeContainer<>(edgeSetFactory, vertex); - intervalGraphVertexContainer.put(vertex, ec); + intervalGraphVertexContainerInterface.put(vertex, ec); } return ec; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 2d12caa973d..5f65321e314 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -1,26 +1,47 @@ package org.jgrapht.intervalgraph; import org.jgrapht.graph.specifics.UndirectedEdgeContainer; +import org.jgrapht.intervalgraph.interval.Interval; import java.io.Serializable; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; -public interface IntervalGraphVertexContainer { +public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { + + private static final long serialVersionUID = 7768940080894764546L; + + private IntervalTreeInterface intervalTree; + private Map> vertexMap; + + public IntervalGraphVertexContainer() { + this.intervalTree = new IntervalTree<>(); + this.vertexMap = new LinkedHashMap<>(); + } /** * Returns the whole vertex set of the graph. * * @return all vertices of the graph in a set */ - Set getVertexSet(); + @Override + public Set getVertexSet() { + return vertexMap.keySet(); + } /** * returns a list of all vertices with overlapping interval w.r.t v * * @param v the vertex with interval */ - public List getOverlappingIntervalVertices(V v); + @Override + public List getOverlappingIntervalVertices(V v) { + //TODO Daniel + // TODO Das sollte eigentlich wie unten angegeben funktionieren?! Man kann mit ClassBasedVertexFactory gerade solche erstellen?! + return intervalTree.overlapsWith(V); + } /** * Returns the edge container to the vertex @@ -28,7 +49,10 @@ public interface IntervalGraphVertexContainer { * @param vertex the vertex * @return the edge container to the vertex */ - UndirectedEdgeContainer get(V vertex); + @Override + public UndirectedEdgeContainer get(V vertex) { + return vertexMap.get(vertex); + } /** * puts the given edge container to the data structure @@ -36,7 +60,11 @@ public interface IntervalGraphVertexContainer { * @param vertex the vertex * @param ec the edge container */ - public boolean put(V vertex, UndirectedEdgeContainer ec); + @Override + public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec) { + intervalTree.add(vertex); + return vertexMap.put(vertex, ec); + } /** * Removes a vertex from the data structure if it is present. @@ -44,5 +72,9 @@ public interface IntervalGraphVertexContainer { * @param vertex the vertex to be removed * @return true if this data structure contained the specified element */ - public boolean remove(V vertex); + @Override + public UndirectedEdgeContainer remove(V vertex) { + intervalTree.remove(vertex); + return vertexMap.remove(vertex); + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java similarity index 51% rename from jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java rename to jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java index f56c442765a..84853f79f8b 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalVertexTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java @@ -3,41 +3,24 @@ import org.jgrapht.graph.specifics.UndirectedEdgeContainer; import java.io.Serializable; -import java.util.LinkedHashMap; import java.util.List; import java.util.Set; -public class IntervalVertexTree implements IntervalGraphVertexContainer, Serializable { - - private static final long serialVersionUID = 7768940080894764546L; - - private IntervalTree intervalTree; - private LinkedHashMap vertexSet; - - public IntervalVertexTree() { - this.intervalTree = new IntervalTree(); - this.vertexSet = new LinkedHashMap<>(); - } +public interface IntervalGraphVertexContainerInterface { /** * Returns the whole vertex set of the graph. * * @return all vertices of the graph in a set */ - @Override - public Set getVertexSet() { - return vertexSet.keySet(); - } + Set getVertexSet(); /** * returns a list of all vertices with overlapping interval w.r.t v * * @param v the vertex with interval */ - @Override - public List getOverlappingIntervalVertices(V v) { - return null; - } + public List getOverlappingIntervalVertices(V v); /** * Returns the edge container to the vertex @@ -45,10 +28,7 @@ public List getOverlappingIntervalVertices(V v) { * @param vertex the vertex * @return the edge container to the vertex */ - @Override - public UndirectedEdgeContainer get(Object vertex) { - return null; - } + UndirectedEdgeContainer get(V vertex); /** * puts the given edge container to the data structure @@ -56,10 +36,7 @@ public UndirectedEdgeContainer get(Object vertex) { * @param vertex the vertex * @param ec the edge container */ - @Override - public boolean put(V vertex, UndirectedEdgeContainer ec) { - return false; - } + public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec); /** * Removes a vertex from the data structure if it is present. @@ -67,8 +44,5 @@ public boolean put(V vertex, UndirectedEdgeContainer ec) { * @param vertex the vertex to be removed * @return true if this data structure contained the specified element */ - @Override - public boolean remove(V vertex) { - return false; - } + public UndirectedEdgeContainer remove(V vertex); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java index 0432344e851..1b415462255 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java @@ -1,7 +1,43 @@ package org.jgrapht.intervalgraph; +import org.jgrapht.intervalgraph.interval.Interval; + import java.io.Serializable; +import java.util.List; -public class IntervalTree implements Serializable { +public class IntervalTree> implements IntervalTreeInterface, Serializable { private static final long serialVersionUID = 2834567756342332325L; + + /** + * Returns all intervals that overlap with the given interval + * + * @param interval the interval + * @return all intervals that overlap with the given interval + */ + @Override + public List> overlapsWith(Interval interval) { + return null; + } + + /** + * adds an interval to the interval tree + * + * @param interval the interval + * @return + */ + @Override + public boolean add(Interval interval) { + return false; + } + + /** + * removes an interval from the tree + * + * @param interval the interval + * @return + */ + @Override + public boolean remove(Interval interval) { + return false; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java new file mode 100644 index 00000000000..e6e84567591 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -0,0 +1,32 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.List; + +public interface IntervalTreeInterface> { + + /** + * Returns all intervals that overlap with the given interval + * + * @param interval the interval + * @return all intervals that overlap with the given interval + */ + List> overlapsWith(Interval interval); + + /** + * adds an interval to the interval tree + * + * @param interval the interval + * @return + */ + boolean add(Interval interval); + + /** + * removes an interval from the tree + * + * @param interval the interval + * @return + */ + boolean remove(Interval interval); +} From 96523660d6e13d4888c464b3538eae1c8d6aebd7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 15:26:37 +0200 Subject: [PATCH 021/131] removed error --- .../jgrapht/intervalgraph/IntervalGraphVertexContainer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 5f65321e314..af11020cba0 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -39,8 +39,8 @@ public Set getVertexSet() { @Override public List getOverlappingIntervalVertices(V v) { //TODO Daniel - // TODO Das sollte eigentlich wie unten angegeben funktionieren?! Man kann mit ClassBasedVertexFactory gerade solche erstellen?! - return intervalTree.overlapsWith(V); + // TODO Das sollte eigentlich wie unten angegeben funktionieren?! Man kann mit ClassBasedVertexFactory gerade solche Vertices erstellen?! + return (List) intervalTree.overlapsWith(v); } /** From 84ecd645df75781c531a3869e59d2126bdc4325b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 15:29:06 +0200 Subject: [PATCH 022/131] added IntervalVertex as interface for vertices in interval graphs --- .../org/jgrapht/intervalgraph/interval/IntervalVertex.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java new file mode 100644 index 00000000000..cbcb83d692d --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java @@ -0,0 +1,7 @@ +package org.jgrapht.intervalgraph.interval; + +public interface IntervalVertex> { + + Interval getInterval(); + +} From 6187c21401310232941ebaa8238de47e2b604e1e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2018 15:43:25 +0200 Subject: [PATCH 023/131] added to all interval graph specific classes that vertices have to implement intervalVertex --- .../graph/specifics/IntervalSpecifics.java | 5 +++-- .../org/jgrapht/intervalgraph/IntervalGraph.java | 3 ++- .../IntervalGraphVertexContainer.java | 15 ++++++++------- .../IntervalGraphVertexContainerInterface.java | 7 ++++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index d26f8100b27..dfab4cd44e9 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -4,12 +4,13 @@ import org.jgrapht.intervalgraph.IntervalGraph; import org.jgrapht.intervalgraph.IntervalGraphVertexContainerInterface; import org.jgrapht.intervalgraph.IntervalGraphVertexContainer; +import org.jgrapht.intervalgraph.interval.IntervalVertex; import org.jgrapht.util.ArrayUnenforcedSet; import java.io.Serializable; import java.util.Set; -public class IntervalSpecifics implements Specifics, Serializable { +public class IntervalSpecifics implements Specifics, Serializable { private static final long serialVersionUID = 1112673663745687843L; @@ -51,7 +52,7 @@ public void removeVertex(V v) { @Override public Set getVertexSet() { - return intervalGraphVertexContainerInterface.getVertexMap(); + return intervalGraphVertexContainerInterface.getVertexSet(); } /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 24aa547c80a..5461cb98fff 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -10,6 +10,7 @@ import org.jgrapht.graph.specifics.IntervalSpecifics; import org.jgrapht.graph.specifics.Specifics; import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.intervalgraph.interval.IntervalVertex; import org.jgrapht.util.TypeUtil; import java.io.Serializable; @@ -24,7 +25,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { +public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { private static final long serialVersionUID = 7835287075273098344L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index af11020cba0..3b76fc9f3b0 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -2,6 +2,7 @@ import org.jgrapht.graph.specifics.UndirectedEdgeContainer; import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.intervalgraph.interval.IntervalVertex; import java.io.Serializable; import java.util.LinkedHashMap; @@ -9,7 +10,7 @@ import java.util.Map; import java.util.Set; -public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { +public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { private static final long serialVersionUID = 7768940080894764546L; @@ -34,13 +35,13 @@ public Set getVertexSet() { /** * returns a list of all vertices with overlapping interval w.r.t v * - * @param v the vertex with interval + * @param vertex the vertex with interval */ @Override - public List getOverlappingIntervalVertices(V v) { + public List getOverlappingIntervalVertices(V vertex) { //TODO Daniel - // TODO Das sollte eigentlich wie unten angegeben funktionieren?! Man kann mit ClassBasedVertexFactory gerade solche Vertices erstellen?! - return (List) intervalTree.overlapsWith(v); + // return intervalTree.overlapsWith(vertex.getInterval()); + return null; } /** @@ -62,7 +63,7 @@ public UndirectedEdgeContainer get(V vertex) { */ @Override public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec) { - intervalTree.add(vertex); + intervalTree.add(vertex.getInterval()); return vertexMap.put(vertex, ec); } @@ -74,7 +75,7 @@ public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer */ @Override public UndirectedEdgeContainer remove(V vertex) { - intervalTree.remove(vertex); + intervalTree.remove(vertex.getInterval()); return vertexMap.remove(vertex); } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java index 84853f79f8b..3a42c4afdaf 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java @@ -1,12 +1,13 @@ package org.jgrapht.intervalgraph; import org.jgrapht.graph.specifics.UndirectedEdgeContainer; +import org.jgrapht.intervalgraph.interval.IntervalVertex; import java.io.Serializable; import java.util.List; import java.util.Set; -public interface IntervalGraphVertexContainerInterface { +public interface IntervalGraphVertexContainerInterface { /** * Returns the whole vertex set of the graph. @@ -36,7 +37,7 @@ public interface IntervalGraphVertexContainerInterface { * @param vertex the vertex * @param ec the edge container */ - public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec); + public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec); /** * Removes a vertex from the data structure if it is present. @@ -44,5 +45,5 @@ public interface IntervalGraphVertexContainerInterface { * @param vertex the vertex to be removed * @return true if this data structure contained the specified element */ - public UndirectedEdgeContainer remove(V vertex); + public UndirectedEdgeContainer remove(V vertex); } From f2bb25322c95e9e40c11c860b53fa51bc4704f9b Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Thu, 19 Apr 2018 20:52:26 +0200 Subject: [PATCH 024/131] Implemented RBTree Implement most of the RBTree --- .../java/org/jgrapht/intervalgraph/Node.java | 16 ++ .../jgrapht/intervalgraph/RedBlackTree.java | 245 +++++++++++++++++- 2 files changed, 254 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 3c7a0a85316..3a29428e72b 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -32,6 +32,14 @@ protected void setRed(boolean red) { this.red = red; } + protected void setRed() { + this.red = true; + } + + protected void setBlack() { + this.red = false; + } + protected void setSize(int size) { this.size = size; } @@ -48,6 +56,10 @@ protected V getVal() { return val; } + public void setVal(V val) { + this.val = val; + } + protected Node getLeftChild() { return leftChild; } @@ -59,4 +71,8 @@ protected Node getRightChild() { protected int getSize() { return size; } + + public void setKey(K key) { + this.key = key; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index b0318af62a3..5acdd489f56 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -1,6 +1,7 @@ package org.jgrapht.intervalgraph; import java.io.Serializable; +import java.util.Comparator; import java.util.NoSuchElementException; /** @@ -13,11 +14,11 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class RedBlackTree implements BinarySearchTree, Serializable { +public class RedBlackTree, V> implements BinarySearchTree, Serializable { private static final long serialVersionUID = 1199228564356373435L; - private Node root; + private Node root; /** * Returns the value associated with the given key @@ -28,9 +29,14 @@ public class RedBlackTree implements BinarySearchTree, Serializable */ @Override public V get(K key) { - return null; + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + return searchNode(key).getVal(); } + /** * Returns whether a key is contained in the tree * @@ -40,7 +46,11 @@ public V get(K key) { */ @Override public boolean contains(K key) { - return false; + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + return searchNode(key) != null; } /** @@ -53,7 +63,41 @@ public boolean contains(K key) { */ @Override public void insert(K key, V val) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + root = insert(root, key, val); + root.setBlack(); + } + + private Node insert(Node current, K key, V val) { + if (current == null){ + return new Node<>(key, val, true, 1); + } + if (key.equals(current.getKey())) { + current.setVal(val); + } else if (key.compareTo(current.getKey()) < 0) { + current.setLeftChild(insert(current.getLeftChild(), key, val)); + } else { + current.setRightChild(insert(current.getRightChild(), key, val)); + } + + // Fixup + + if (current.getRightChild().isRed() && !current.getLeftChild().isRed()) { + current = rotateLeft(current); + } + if (current.getLeftChild().isRed() && current.getLeftChild().getLeftChild().isRed()) { + current = rotateRight(current); + } + if (current.getLeftChild().isRed() && current.getRightChild().isRed()) { + changeColor(current); + } + current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); + + return current; } /** @@ -64,7 +108,68 @@ public void insert(K key, V val) { */ @Override public void delete(K key) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + if (!contains(key)) { + return; + } + + if (!root.getLeftChild().isRed() && !root.getRightChild().isRed()) { + root.setRed(); + } + + root = delete(root, key); + if (!isEmpty()) { + root.setBlack(); + } + } + + private boolean isEmpty() { + return root == null; + } + + private Node delete(Node current, K key) { + if (key.compareTo(current.getKey()) < 0) { + if (!current.getLeftChild().isRed() && !current.getLeftChild().getLeftChild().isRed()) { + current = moveRedLeft(current); + } + current.setLeftChild(delete(current.getLeftChild(), key)); + } else { + if (current.getLeftChild().isRed()) { + current = rotateRight(current); + } + if (key.compareTo(current.getKey()) == 0 && current.getRightChild() == null) { + return null; + } + if (!current.getRightChild().isRed() && !current.getRightChild().getLeftChild().isRed()) { + current = moveRedRight(current); + } + if (key.compareTo(current.getKey()) == 0) { + Node node = min(current.getRightChild()); + current.setKey(node.getKey()); + current.setVal(node.getVal()); + current.setRightChild(deleteMin(current.getRightChild())); + } + else current.setRightChild(delete(current.getRightChild(), key)); + } + return balance(current); + } + + private Node balance(Node node) { + if (node.getRightChild().isRed()) { + node = rotateLeft(node); + } + if (node.getLeftChild().isRed() && node.getLeftChild().getLeftChild().isRed()) { + node = rotateRight(node); + } + if (node.getLeftChild().isRed() && node.getRightChild().isRed()) { + changeColor(node); + } + + node.setSize(size(node.getLeftChild()) + size(node.getRightChild() ) + 1); + return node; } /** @@ -74,7 +179,31 @@ public void delete(K key) { */ @Override public void deleteMin() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + if (!root.getLeftChild().isRed() && !root.getRightChild().isRed()) { + root.setRed(); + } + + root = deleteMin(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private Node deleteMin(Node node) { + if (node.getLeftChild() == null) { + return null; + } + if (!node.getLeftChild().isRed() && !node.getLeftChild().getLeftChild().isRed()) { + root = moveRedLeft(node); + } + + node.setLeftChild(deleteMin(node.getLeftChild())); + return balance(node); } /** @@ -84,7 +213,34 @@ public void deleteMin() { */ @Override public void deleteMax() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + + if (!root.getRightChild().isRed() && !root.getRightChild().isRed()) { + root.setRed(); + } + root = deleteMax(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private Node deleteMax(Node node) { + if (node.getLeftChild().isRed()) { + node = rotateRight(node); + } + if (node.getRightChild() == null) { + return null; + } + if (!node.getRightChild().isRed() && !node.getRightChild().getLeftChild().isRed()) { + node = moveRedRight(node); + } + + node.setRightChild(deleteMax(node.getRightChild())); + + return balance(node); } /** @@ -94,7 +250,15 @@ public void deleteMax() { */ @Override public int height() { - return 0; + return height(root); + } + + private int height(Node node) { + if (node == null) { + return -1; + } + + return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); } /** @@ -105,7 +269,18 @@ public int height() { */ @Override public K min() { - return null; + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return min(root).getKey(); + } + + private Node min(Node node) { + if (node.getLeftChild() == null) { + return node; + } + return max(node.getLeftChild()); } /** @@ -116,7 +291,19 @@ public K min() { */ @Override public K max() { - return null; + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return max(root.getRightChild()).getKey(); + } + + private Node max(Node node) { + if (node.getRightChild() == null) { + return node; + } + + return max(node.getRightChild()); } /** @@ -213,6 +400,14 @@ public int size(K min, K max) { return 0; } + public int size(Node node) { + if (node == null) { + return 0; + } + + return node.getSize(); + } + /******************************************************************************************************************* * HELPER METHODS * ******************************************************************************************************************/ @@ -244,4 +439,40 @@ private void changeColor(Node node) { node.getRightChild().setRed(!node.getRightChild().isRed()); node.getLeftChild().setRed(!node.getLeftChild().isRed()); } + + private Node searchNode(K key) { + Node current = root; + while (current != null) { + if (current.getKey().equals(key)) { + return current; + } else if (current.getKey().compareTo(key) < 0) { + current = current.getRightChild(); + } else { + current = current.getLeftChild(); + } + } + + return null; + } + + private Node moveRedRight(Node node) { + changeColor(node); + if (node.getLeftChild().getLeftChild().isRed()) { + node = rotateRight(node); + changeColor(node); + } + + return node; + } + + private Node moveRedLeft(Node node) { + changeColor(node); + if (node.getRightChild().getLeftChild().isRed()) { + node.setRightChild(rotateRight(node.getRightChild())); + node = rotateLeft(node); + changeColor(node); + } + + return node; + } } From 6b77b3211de14e44adf53f697fb8f911fb4bd273 Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Thu, 19 Apr 2018 20:52:26 +0200 Subject: [PATCH 025/131] Implemented RBTree Implement most of the RBTree --- .../java/org/jgrapht/intervalgraph/Node.java | 20 +- .../jgrapht/intervalgraph/RedBlackTree.java | 254 +++++++++++++++++- 2 files changed, 260 insertions(+), 14 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 3c7a0a85316..0d211200992 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -32,6 +32,14 @@ protected void setRed(boolean red) { this.red = red; } + protected void setRed() { + this.red = true; + } + + protected void setBlack() { + this.red = false; + } + protected void setSize(int size) { this.size = size; } @@ -48,15 +56,23 @@ protected V getVal() { return val; } - protected Node getLeftChild() { + public void setVal(V val) { + this.val = val; + } + + protected Node getLeftChild() { return leftChild; } - protected Node getRightChild() { + protected Node getRightChild() { return rightChild; } protected int getSize() { return size; } + + public void setKey(K key) { + this.key = key; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index b0318af62a3..8ff85ad7d07 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -13,11 +13,11 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class RedBlackTree implements BinarySearchTree, Serializable { +public class RedBlackTree, V> implements BinarySearchTree, Serializable { private static final long serialVersionUID = 1199228564356373435L; - private Node root; + private Node root; /** * Returns the value associated with the given key @@ -28,9 +28,14 @@ public class RedBlackTree implements BinarySearchTree, Serializable */ @Override public V get(K key) { - return null; + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + return searchNode(key).getVal(); } + /** * Returns whether a key is contained in the tree * @@ -40,7 +45,11 @@ public V get(K key) { */ @Override public boolean contains(K key) { - return false; + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + return searchNode(key) != null; } /** @@ -53,7 +62,41 @@ public boolean contains(K key) { */ @Override public void insert(K key, V val) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + root = insert(root, key, val); + root.setBlack(); + } + + private Node insert(Node current, K key, V val) { + if (current == null){ + return new Node<>(key, val, true, 1); + } + if (key.equals(current.getKey())) { + current.setVal(val); + } else if (key.compareTo(current.getKey()) < 0) { + current.setLeftChild(insert(current.getLeftChild(), key, val)); + } else { + current.setRightChild(insert(current.getRightChild(), key, val)); + } + + // Fixup + + if (current.getRightChild().isRed() && !current.getLeftChild().isRed()) { + current = rotateLeft(current); + } + if (current.getLeftChild().isRed() && current.getLeftChild().getLeftChild().isRed()) { + current = rotateRight(current); + } + if (current.getLeftChild().isRed() && current.getRightChild().isRed()) { + changeColor(current); + } + current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); + + return current; } /** @@ -64,7 +107,68 @@ public void insert(K key, V val) { */ @Override public void delete(K key) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + if (!contains(key)) { + return; + } + + if (!root.getLeftChild().isRed() && !root.getRightChild().isRed()) { + root.setRed(); + } + + root = delete(root, key); + if (!isEmpty()) { + root.setBlack(); + } + } + + private boolean isEmpty() { + return root == null; + } + + private Node delete(Node current, K key) { + if (key.compareTo(current.getKey()) < 0) { + if (!current.getLeftChild().isRed() && !current.getLeftChild().getLeftChild().isRed()) { + current = moveRedLeft(current); + } + current.setLeftChild(delete(current.getLeftChild(), key)); + } else { + if (current.getLeftChild().isRed()) { + current = rotateRight(current); + } + if (key.compareTo(current.getKey()) == 0 && current.getRightChild() == null) { + return null; + } + if (!current.getRightChild().isRed() && !current.getRightChild().getLeftChild().isRed()) { + current = moveRedRight(current); + } + if (key.compareTo(current.getKey()) == 0) { + Node node = min(current.getRightChild()); + current.setKey(node.getKey()); + current.setVal(node.getVal()); + current.setRightChild(deleteMin(current.getRightChild())); + } + else current.setRightChild(delete(current.getRightChild(), key)); + } + return balance(current); + } + + private Node balance(Node node) { + if (node.getRightChild().isRed()) { + node = rotateLeft(node); + } + if (node.getLeftChild().isRed() && node.getLeftChild().getLeftChild().isRed()) { + node = rotateRight(node); + } + if (node.getLeftChild().isRed() && node.getRightChild().isRed()) { + changeColor(node); + } + + node.setSize(size(node.getLeftChild()) + size(node.getRightChild() ) + 1); + return node; } /** @@ -74,7 +178,31 @@ public void delete(K key) { */ @Override public void deleteMin() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + if (!root.getLeftChild().isRed() && !root.getRightChild().isRed()) { + root.setRed(); + } + + root = deleteMin(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private Node deleteMin(Node node) { + if (node.getLeftChild() == null) { + return null; + } + if (!node.getLeftChild().isRed() && !node.getLeftChild().getLeftChild().isRed()) { + root = moveRedLeft(node); + } + + node.setLeftChild(deleteMin(node.getLeftChild())); + return balance(node); } /** @@ -84,7 +212,34 @@ public void deleteMin() { */ @Override public void deleteMax() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + + if (!root.getRightChild().isRed() && !root.getRightChild().isRed()) { + root.setRed(); + } + root = deleteMax(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private Node deleteMax(Node node) { + if (node.getLeftChild().isRed()) { + node = rotateRight(node); + } + if (node.getRightChild() == null) { + return null; + } + if (!node.getRightChild().isRed() && !node.getRightChild().getLeftChild().isRed()) { + node = moveRedRight(node); + } + + node.setRightChild(deleteMax(node.getRightChild())); + + return balance(node); } /** @@ -94,7 +249,15 @@ public void deleteMax() { */ @Override public int height() { - return 0; + return height(root); + } + + private int height(Node node) { + if (node == null) { + return -1; + } + + return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); } /** @@ -105,7 +268,18 @@ public int height() { */ @Override public K min() { - return null; + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return min(root).getKey(); + } + + private Node min(Node node) { + if (node.getLeftChild() == null) { + return node; + } + return max(node.getLeftChild()); } /** @@ -116,7 +290,19 @@ public K min() { */ @Override public K max() { - return null; + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return max(root.getRightChild()).getKey(); + } + + private Node max(Node node) { + if (node.getRightChild() == null) { + return node; + } + + return max(node.getRightChild()); } /** @@ -213,12 +399,20 @@ public int size(K min, K max) { return 0; } + public int size(Node node) { + if (node == null) { + return 0; + } + + return node.getSize(); + } + /******************************************************************************************************************* * HELPER METHODS * ******************************************************************************************************************/ - private Node rotateLeft(Node node) { - Node rightChild = node.getRightChild(); + private Node rotateLeft(Node node) { + Node rightChild = node.getRightChild(); node.setRightChild(rightChild.getLeftChild()); rightChild.setLeftChild(node); rightChild.setRed(rightChild.getLeftChild().isRed()); @@ -228,8 +422,8 @@ private Node rotateLeft(Node node) { return rightChild; } - private Node rotateRight(Node node) { - Node leftChild = node.getLeftChild(); + private Node rotateRight(Node node) { + Node leftChild = node.getLeftChild(); node.setLeftChild(leftChild.getRightChild()); leftChild.setRightChild(node); leftChild.setRed(leftChild.getRightChild().isRed()); @@ -239,9 +433,45 @@ private Node rotateRight(Node node) { return leftChild; } - private void changeColor(Node node) { + private void changeColor(Node node) { node.setRed(!node.isRed()); node.getRightChild().setRed(!node.getRightChild().isRed()); node.getLeftChild().setRed(!node.getLeftChild().isRed()); } + + private Node searchNode(K key) { + Node current = root; + while (current != null) { + if (current.getKey().equals(key)) { + return current; + } else if (current.getKey().compareTo(key) < 0) { + current = current.getRightChild(); + } else { + current = current.getLeftChild(); + } + } + + return null; + } + + private Node moveRedRight(Node node) { + changeColor(node); + if (node.getLeftChild().getLeftChild().isRed()) { + node = rotateRight(node); + changeColor(node); + } + + return node; + } + + private Node moveRedLeft(Node node) { + changeColor(node); + if (node.getRightChild().getLeftChild().isRed()) { + node.setRightChild(rotateRight(node.getRightChild())); + node = rotateLeft(node); + changeColor(node); + } + + return node; + } } From 0aa0a8751c6989daf5a4e1ccfed7c75fce1c9b77 Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Thu, 19 Apr 2018 23:14:37 +0200 Subject: [PATCH 026/131] Implemented LBFS/LBFS+ --- .../intervalgraph/LexBreathFirstSearch.java | 217 ++++++++++++++++++ .../alg/intervalgraph/package-info.java | 6 + 2 files changed, 223 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java new file mode 100644 index 00000000000..25b8dcc5e15 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java @@ -0,0 +1,217 @@ +package org.jgrapht.alg.intervalgraph; + +import org.jgrapht.*; + +import java.util.*; + +public class LexBreathFirstSearch +{ + + /** + * Performs a lexicographical BFS starting at {@code startingVertex}. + * + * @param graph the graph we want to perform LBFS on + * @param startingVertex the starting vertex of the LBFS + * @return an array of vertices representing the order in which the vertices were found + */ + public V[] lexBreathFirstSearch(Graph graph, V startingVertex) + { + int n = graph.vertexSet().size(); + ArrayList ordering = new ArrayList(); + + String maxLabel = Integer.toString(n); + + HashMap> labelToVertexMap = new HashMap>(); + HashMap vertexToLabelMap = new HashMap(); + + // initialize labels to be empty ... + ArrayList initialVertexList = new ArrayList(graph.vertexSet()); + initialVertexList.remove(startingVertex); + + labelToVertexMap.put("", initialVertexList); + + for(V vertex : initialVertexList) { + vertexToLabelMap.put(vertex, ""); + } + + // ... except for the starting vertex + ArrayList startingVertexList = new ArrayList(); + startingVertexList.add(startingVertex); + + labelToVertexMap.put(maxLabel, startingVertexList); + vertexToLabelMap.put(startingVertex, maxLabel); + + for(int i = n; i >= 1; i--) { + // pick unvisited vertex v with largest label + ArrayList candidates = labelToVertexMap.get(maxLabel); + V currentVertex = candidates.get(0); + + // set index of v to be n + 1 - i + ordering.add(currentVertex); + + // for every unvisited neighbor w of v, append i to label of w + for(V neighbor : Graphs.neighborListOf(graph, currentVertex)) { + String oldLabel = vertexToLabelMap.get(neighbor); + String newLabel = oldLabel + Integer.toString(i); + + // remove neighbor from previous list + ArrayList oldList = labelToVertexMap.get(oldLabel); + oldList.remove(neighbor); + + // if there are no vertices left in this list, delete the entry + if(oldList.isEmpty()) { + labelToVertexMap.remove(oldLabel); + } else { + // else we replace the list with its updated version + labelToVertexMap.replace(oldLabel, oldList); + } + + // now add neighbor to the list of the new label + if(labelToVertexMap.containsKey(newLabel)) { + ArrayList newList = labelToVertexMap.get(newLabel); + newList.add(neighbor); + labelToVertexMap.replace(newLabel, newList); + } else { + ArrayList newList = new ArrayList(); + newList.add(neighbor); + labelToVertexMap.put(newLabel, newList); + } + + // associate neighbor with its new label + vertexToLabelMap.replace(neighbor, newLabel); + } + + // mark current vertex as visited, i.e. remove its entries from the maps + vertexToLabelMap.remove(currentVertex); + candidates.remove(currentVertex); + labelToVertexMap.replace(maxLabel, candidates); + } + + // return ordering -- thanks Java for not being able to create an array from a list with generic types for some reason + V[] orderingArray = null; + orderingArray = ordering.toArray(orderingArray); + + return orderingArray; + } + + /** + * Performs LBFS+ starting at {@code startingVertex} using the previous ordering {@code prevOrdering}. + * + * @param graph the graph we want to perform LBFS on + * @param startingVertex the starting vertex of the LBFS + * @param prevOrdering the previous LBFS ordering given as an array + * @return an array of vertices representing the order in which the vertices were found + */ + public V[] lexBreathFirstSearch(Graph graph, V startingVertex, V[] prevOrdering) + { + LBFSComparator comp = new LBFSComparator(prevOrdering); + + int n = graph.vertexSet().size(); + ArrayList ordering = new ArrayList(); + + String maxLabel = Integer.toString(n); + + HashMap> labelToVertexMap = new HashMap>(); + HashMap vertexToLabelMap = new HashMap(); + + // initialize labels to be empty ... + ArrayList initialVertexList = new ArrayList(graph.vertexSet()); + initialVertexList.remove(startingVertex); + + labelToVertexMap.put("", initialVertexList); + + for(V vertex : initialVertexList) { + vertexToLabelMap.put(vertex, ""); + } + + // ... except for the starting vertex + ArrayList startingVertexList = new ArrayList(); + startingVertexList.add(startingVertex); + + labelToVertexMap.put(maxLabel, startingVertexList); + vertexToLabelMap.put(startingVertex, maxLabel); + + for(int i = n; i >= 1; i--) { + // pick unvisited vertex v with largest label + ArrayList candidates = labelToVertexMap.get(maxLabel); + + // LBFS+: pick the vertex with the lex. largest label which appears last in the previous ordering + candidates.sort(comp.reversed()); + V currentVertex = candidates.get(0); + + // set index of v to be n + 1 - i + ordering.add(currentVertex); + + // for every unvisited neighbor w of v, append i to label of w + for(V neighbor : Graphs.neighborListOf(graph, currentVertex)) { + String oldLabel = vertexToLabelMap.get(neighbor); + String newLabel = oldLabel + Integer.toString(i); + + // remove neighbor from previous list + ArrayList oldList = labelToVertexMap.get(oldLabel); + oldList.remove(neighbor); + + // if there are no vertices left in this list, delete the entry + if(oldList.isEmpty()) { + labelToVertexMap.remove(oldLabel); + } else { + // else we replace the list with its updated version + labelToVertexMap.replace(oldLabel, oldList); + } + + // now add neighbor to the list of the new label + if(labelToVertexMap.containsKey(newLabel)) { + ArrayList newList = labelToVertexMap.get(newLabel); + newList.add(neighbor); + labelToVertexMap.replace(newLabel, newList); + } else { + ArrayList newList = new ArrayList(); + newList.add(neighbor); + labelToVertexMap.put(newLabel, newList); + } + + // associate neighbor with its new label + vertexToLabelMap.replace(neighbor, newLabel); + } + + // mark current vertex as visited, i.e. remove its entries from the maps + vertexToLabelMap.remove(currentVertex); + candidates.remove(currentVertex); + labelToVertexMap.replace(maxLabel, candidates); + } + + // return ordering -- thanks Java for not being able to create an array from a list with generic types for some reason + V[] orderingArray = null; + orderingArray = ordering.toArray(orderingArray); + + return orderingArray; + } + + class LBFSComparator implements Comparator + { + private final V[] prevOrdering; + + public LBFSComparator(V[] prevOrdering) { + this.prevOrdering = prevOrdering; + } + + // apparantly Java has no indexOf method... + private int indexOf(V vertex) throws NoSuchElementException{ + for(int index = 0; index < prevOrdering.length; index++) { + if(prevOrdering[index].equals(vertex)) { + return index; + } + } + throw new NoSuchElementException("Previous ordering is on a different vertex set."); + } + + @Override + public int compare(V vertex1, V vertex2) + { + int index1 = indexOf(vertex1); + int index2 = indexOf(vertex2); + + return (index1 - index2); + } + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/package-info.java new file mode 100644 index 00000000000..fcfba4693ee --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/package-info.java @@ -0,0 +1,6 @@ + +/** + * Interval graph related algorithms. + * + */ +package org.jgrapht.alg.intervalgraph; From 0ad117087d18250479b6fff6ca3ce1b5f689d208 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Fri, 20 Apr 2018 15:09:47 +0200 Subject: [PATCH 027/131] Add some tests for the interval tree and fix a found bug --- .../intervalgraph/CenteredIntervalTree.java | 8 ++- .../interval/IntegerInterval.java | 5 ++ .../intervalgraph/interval/Interval.java | 8 ++- .../CenteredIntervalTreeTest.java | 52 +++++++++++++++---- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java index 4d27d2d67df..fa05eb8f83a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -45,11 +45,9 @@ private void initialize(List> intervals) { for (Interval interval: intervals) { if (interval.contains(centerPoint)) { intersectingIntervals.add(interval); - } - - if (interval.relativeDistance(centerPoint) < 0) { // is completely left to center point + } else if (interval.compareToPoint(centerPoint) < 0) { // is completely left to center point leftIntervals.add(interval); - } else if (interval.relativeDistance(centerPoint) > 0) { // completely right + } else if (interval.compareToPoint(centerPoint) > 0) { // completely right rightIntervals.add(interval); } } @@ -66,7 +64,7 @@ private void initialize(List> intervals) { leftTree.initialize(leftIntervals); rightTree = new CenteredIntervalTree<>(); - leftTree.initialize(rightIntervals); + rightTree.initialize(rightIntervals); } @Override diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java index e463e70c1e9..81131e8a52a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java @@ -8,4 +8,9 @@ public IntegerInterval(int start, int end) { public int length() { return getEnd() - getStart(); } + + @Override + public String toString() { + return "[" + getStart() + ", " + getEnd() + "]"; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 4416a004ab2..587ed37c7f4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -29,12 +29,12 @@ public boolean contains(T point) { } boolean result = point.compareTo(getStart()) >= 0 && point.compareTo(getEnd()) <= 0; - assert result == (relativeDistance(point) == 0); + assert result == (compareToPoint(point) == 0); return result; } - public int relativeDistance(T o) { + public int compareToPoint(T o) { if (o == null) { throw new IllegalArgumentException(); } @@ -44,10 +44,8 @@ public int relativeDistance(T o) { if (relativeStart <= 0 && relativeEnd >= 0) { return 0; - } else if (relativeStart > 0) { + } else { return relativeStart; - } else { - return relativeEnd; } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java index 584e9dde857..1a813030206 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java @@ -5,7 +5,6 @@ import org.junit.Before; import org.junit.Test; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -13,19 +12,54 @@ public class CenteredIntervalTreeTest { - IntegerInterval i00 = new IntegerInterval(0,0); - IntegerInterval i01 = new IntegerInterval(0,1); - IntegerInterval i56 = new IntegerInterval(5,6); - List> list; + @Test + public void testCompareToPoint() { + IntegerInterval interval = new IntegerInterval(0, 1); + assertEquals(-1, interval.compareToPoint(-1)); + assertEquals(0, interval.compareToPoint(0)); + assertEquals(0, interval.compareToPoint(1)); + assertEquals(1, interval.compareToPoint(2)); + } + + @Test + public void testEmptyTree() { + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-2).size()); + assertEquals(0, tree.intersections(0).size()); + assertEquals(0, tree.intersections((2)).size()); + } + + @Test + public void testSingleInterval() { + list.add(new IntegerInterval(0, 2)); + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-1).size()); + assertEquals(1, tree.intersections(0).size()); + assertEquals(1, tree.intersections(1).size()); + assertEquals(1, tree.intersections(2).size()); + assertEquals(0, tree.intersections(3).size()); + } @Test - public void intersections() { + public void testPath() { + list.add(new IntegerInterval(0, 1)); + list.add(new IntegerInterval(1, 2)); + list.add(new IntegerInterval(2, 3)); + list.add(new IntegerInterval(3, 4)); + list.add(new IntegerInterval(4, 5)); + list.add(new IntegerInterval(5, 6)); CenteredIntervalTree tree = new CenteredIntervalTree<>(list); - assertEquals(0, tree.intersections(2).size()); - assertEquals(2, tree.intersections(0).size()); - assertEquals(0, new CenteredIntervalTree(new LinkedList<>()).intersections(0).size()); + assertEquals(0, tree.intersections(-1).size()); + assertEquals(1, tree.intersections(0).size()); + assertEquals(2, tree.intersections(1).size()); + assertEquals(2, tree.intersections(2).size()); + assertEquals(2, tree.intersections(3).size()); + assertEquals(2, tree.intersections(4).size()); + assertEquals(2, tree.intersections(5).size()); + assertEquals(1, tree.intersections(6).size()); + assertEquals(0, tree.intersections(7).size()); } @Before From 4c5be675e729e4961b964df281cd033d125d13b5 Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Fri, 20 Apr 2018 20:01:23 +0200 Subject: [PATCH 028/131] Implemented IntervalTree --- .../jgrapht/intervalgraph/IntervalTree.java | 41 ++++- .../intervalgraph/IntervalTreeInterface.java | 15 +- .../java/org/jgrapht/intervalgraph/Node.java | 10 ++ .../intervalgraph/RedBlackIntervalTree.java | 78 ++++++++++ .../jgrapht/intervalgraph/RedBlackTree.java | 141 +++++++++++++----- .../intervalgraph/interval/Interval.java | 5 + .../intervalgraph/IntervalTreeTest.java | 33 ++++ .../RedBlackIntervalTreeTest.java | 39 +++++ 8 files changed, 318 insertions(+), 44 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java index 1b415462255..d67c72f1d07 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java @@ -3,11 +3,14 @@ import org.jgrapht.intervalgraph.interval.Interval; import java.io.Serializable; +import java.util.LinkedList; import java.util.List; public class IntervalTree> implements IntervalTreeInterface, Serializable { private static final long serialVersionUID = 2834567756342332325L; + private RedBlackIntervalTree> tree = new RedBlackIntervalTree<>(); + /** * Returns all intervals that overlap with the given interval * @@ -19,15 +22,43 @@ public List> overlapsWith(Interval interval) { return null; } + @Override + public List> overlapsWithPoint(T point) { + List> result = new LinkedList<>(); + + overlapsWithPoint(tree.getRoot(), point, result); + return result; + } + + private void overlapsWithPoint(Node> node, T point, List> result) { + if (node == null) { + return; + } + + if (point.compareTo(node.getHi()) > 0) { + return; + } + + overlapsWithPoint(node.getLeftChild(), point, result); + + if (node.getVal().contains(point)) { + result.add(node.getVal()); + } + + if (point.compareTo(node.getVal().getStart()) >= 0) { + overlapsWithPoint(node.getRightChild(), point, result); + } + } + + /** * adds an interval to the interval tree * * @param interval the interval - * @return */ @Override - public boolean add(Interval interval) { - return false; + public void add(Interval interval) { + tree.insert(interval.getStart(), interval); } /** @@ -37,7 +68,7 @@ public boolean add(Interval interval) { * @return */ @Override - public boolean remove(Interval interval) { - return false; + public void remove(Interval interval) { + tree.delete(interval.getStart()); } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index e6e84567591..0516a21c8b0 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -12,15 +12,22 @@ public interface IntervalTreeInterface> { * @param interval the interval * @return all intervals that overlap with the given interval */ - List> overlapsWith(Interval interval); + public List> overlapsWith(Interval interval); + + + /** + * Returns all intervals that overlap with the given point + * @param point the point + * @return all intervals that overlap with the given point + */ + public List> overlapsWithPoint(T point); /** * adds an interval to the interval tree * * @param interval the interval - * @return */ - boolean add(Interval interval); + public void add(Interval interval); /** * removes an interval from the tree @@ -28,5 +35,5 @@ public interface IntervalTreeInterface> { * @param interval the interval * @return */ - boolean remove(Interval interval); + public void remove(Interval interval); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 0d211200992..d3875dc5eb8 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -75,4 +75,14 @@ protected int getSize() { public void setKey(K key) { this.key = key; } + + private K hi; + + public K getHi() { + return hi; + } + + public void setHi(K hi) { + this.hi = hi; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java new file mode 100644 index 00000000000..cb27be5cb30 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -0,0 +1,78 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +public class RedBlackIntervalTree, I extends Interval> extends RedBlackTree{ + @Override + protected Node rotateRight(Node node) { + // Perform rotation as usual + Node result = super.rotateRight(node); + + // update hi vals + result.setHi(node.getHi()); + updateHi(node); + + return result; + } + + @Override + protected Node rotateLeft(Node node) { + // Perform rotation as usual + Node result = super.rotateLeft(node); + + // update hi vals + result.setHi(node.getHi()); + updateHi(node); + + return result; + } + + @Override + protected Node delete(Node current, T key) { + Node result = super.delete(current, key); + updateHi(result); + return result; + } + + @Override + protected Node insert(Node current, T key, I val) { + Node result = super.insert(current, key, val); + updateHi(result); + return result; + } + + @Override + protected Node balance(Node node) { + Node result = super.balance(node); + updateHi(result); + return result; + } + + // sets the hi attribute of the given node to the max of the subtree or itself + private void updateHi(Node node) { + if (node == null) { + return; + } + + T result = node.getVal().getEnd(); + if (node.getRightChild() != null) { + result = max(result, node.getRightChild().getHi()); + } + + if (node.getLeftChild() != null) { + result = max(result, node.getLeftChild().getHi()); + } + + node.setHi(result); + } + + + // returns the max of two values + public T max(T t1, T t2) { + if (t1.compareTo(t2) > 0) { + return t1; + } else { + return t2; + } + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 0161adc891a..a63075b6bd2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -1,8 +1,7 @@ package org.jgrapht.intervalgraph; import java.io.Serializable; -import java.util.Comparator; -import java.util.NoSuchElementException; +import java.util.*; /** * Implementation of a Red-Black-Tree @@ -18,7 +17,11 @@ public class RedBlackTree, V> implements BinarySearchTre private static final long serialVersionUID = 1199228564356373435L; - private Node root; + protected Node root; + + public Node getRoot() { + return root; + } /** * Returns the value associated with the given key @@ -36,6 +39,12 @@ public V get(K key) { return searchNode(key).getVal(); } + private boolean isRed(Node node){ + if (node == null) { + return false; + } + return node.isRed(); + } /** * Returns whether a key is contained in the tree @@ -71,7 +80,7 @@ public void insert(K key, V val) { root.setBlack(); } - private Node insert(Node current, K key, V val) { + protected Node insert(Node current, K key, V val) { if (current == null){ return new Node<>(key, val, true, 1); } @@ -86,13 +95,13 @@ private Node insert(Node current, K key, V val) { // Fixup - if (current.getRightChild().isRed() && !current.getLeftChild().isRed()) { + if (isRed(current.getRightChild()) && !isRed(current.getLeftChild())) { current = rotateLeft(current); } - if (current.getLeftChild().isRed() && current.getLeftChild().getLeftChild().isRed()) { + if (isRed(current.getLeftChild()) && isRed(current.getLeftChild().getLeftChild())) { current = rotateRight(current); } - if (current.getLeftChild().isRed() && current.getRightChild().isRed()) { + if (isRed(current.getLeftChild()) && isRed(current.getRightChild())) { changeColor(current); } current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); @@ -115,7 +124,7 @@ public void delete(K key) { return; } - if (!root.getLeftChild().isRed() && !root.getRightChild().isRed()) { + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { root.setRed(); } @@ -129,20 +138,20 @@ private boolean isEmpty() { return root == null; } - private Node delete(Node current, K key) { + protected Node delete(Node current, K key) { if (key.compareTo(current.getKey()) < 0) { - if (!current.getLeftChild().isRed() && !current.getLeftChild().getLeftChild().isRed()) { + if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { current = moveRedLeft(current); } current.setLeftChild(delete(current.getLeftChild(), key)); } else { - if (current.getLeftChild().isRed()) { + if (isRed(current.getLeftChild())) { current = rotateRight(current); } if (key.compareTo(current.getKey()) == 0 && current.getRightChild() == null) { return null; } - if (!current.getRightChild().isRed() && !current.getRightChild().getLeftChild().isRed()) { + if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { current = moveRedRight(current); } if (key.compareTo(current.getKey()) == 0) { @@ -157,14 +166,14 @@ private Node delete(Node current, K key) { return balance(current); } - private Node balance(Node node) { - if (node.getRightChild().isRed()) { + protected Node balance(Node node) { + if (isRed(node.getRightChild())) { node = rotateLeft(node); } - if (node.getLeftChild().isRed() && node.getLeftChild().getLeftChild().isRed()) { + if (isRed(node.getLeftChild()) && isRed(node.getLeftChild().getLeftChild())) { node = rotateRight(node); } - if (node.getLeftChild().isRed() && node.getRightChild().isRed()) { + if (isRed(node.getLeftChild()) && isRed(node.getRightChild())) { changeColor(node); } @@ -183,7 +192,7 @@ public void deleteMin() { throw new NoSuchElementException("empty tree"); } - if (!root.getLeftChild().isRed() && !root.getRightChild().isRed()) { + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { root.setRed(); } @@ -198,7 +207,7 @@ private Node deleteMin(Node node) { return null; } - if (!node.getLeftChild().isRed() && !node.getLeftChild().getLeftChild().isRed()) { + if (!isRed(node.getLeftChild()) && !isRed(node.getLeftChild().getLeftChild())) { root = moveRedLeft(node); } @@ -217,7 +226,7 @@ public void deleteMax() { throw new NoSuchElementException(); } - if (!root.getRightChild().isRed() && !root.getRightChild().isRed()) { + if (!isRed(root.getRightChild()) && !isRed(root.getRightChild())) { root.setRed(); } @@ -228,13 +237,13 @@ public void deleteMax() { } private Node deleteMax(Node node) { - if (node.getLeftChild().isRed()) { + if (isRed(node.getLeftChild())) { node = rotateRight(node); } if (node.getRightChild() == null) { return null; } - if (!node.getRightChild().isRed() && !node.getRightChild().getLeftChild().isRed()) { + if (!isRed(node.getRightChild()) && !isRed(node.getRightChild().getLeftChild())) { node = moveRedRight(node); } @@ -405,39 +414,43 @@ public int size(Node node) { return 0; } - return node.getSize(); + return getSize(node); } /******************************************************************************************************************* * HELPER METHODS * ******************************************************************************************************************/ - private Node rotateLeft(Node node) { + protected Node rotateLeft(Node node) { Node rightChild = node.getRightChild(); node.setRightChild(rightChild.getLeftChild()); rightChild.setLeftChild(node); - rightChild.setRed(rightChild.getLeftChild().isRed()); + rightChild.setRed(isRed(rightChild.getLeftChild())); rightChild.getLeftChild().setRed(true); - rightChild.setSize(node.getSize()); - node.setSize(node.getLeftChild().getSize() + node.getRightChild().getSize() + 1); + rightChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); return rightChild; } - private Node rotateRight(Node node) { + private int getSize(Node node) { + return node != null ? node.getSize() : 0; + } + + protected Node rotateRight(Node node) { Node leftChild = node.getLeftChild(); node.setLeftChild(leftChild.getRightChild()); leftChild.setRightChild(node); - leftChild.setRed(leftChild.getRightChild().isRed()); + leftChild.setRed(isRed(leftChild.getRightChild())); leftChild.getRightChild().setRed(true); - leftChild.setSize(node.getSize()); - node.setSize(node.getLeftChild().getSize() + node.getRightChild().getSize() + 1); + leftChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); return leftChild; } private void changeColor(Node node) { - node.setRed(!node.isRed()); - node.getRightChild().setRed(!node.getRightChild().isRed()); - node.getLeftChild().setRed(!node.getLeftChild().isRed()); + node.setRed(!isRed(node)); + node.getRightChild().setRed(!isRed(node.getRightChild())); + node.getLeftChild().setRed(!isRed(node.getLeftChild())); } private Node searchNode(K key) { @@ -457,7 +470,7 @@ private Node searchNode(K key) { private Node moveRedRight(Node node) { changeColor(node); - if (node.getLeftChild().getLeftChild().isRed()) { + if (isRed(node.getLeftChild().getLeftChild())) { node = rotateRight(node); changeColor(node); } @@ -467,7 +480,7 @@ private Node moveRedRight(Node node) { private Node moveRedLeft(Node node) { changeColor(node); - if (node.getRightChild().getLeftChild().isRed()) { + if (isRed(node.getRightChild().getLeftChild())) { node.setRightChild(rotateRight(node.getRightChild())); node = rotateLeft(node); changeColor(node); @@ -475,4 +488,62 @@ private Node moveRedLeft(Node node) { return node; } + + // returns the nodes inorder + private List> inorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + inorder(root, result); + return result; + } + + private void inorder(Node current, List> result) { + if (current == null) { + return; + } + + inorder(current.getLeftChild(), result); + result.add(current); + inorder(current.getRightChild(), result); + } + + public List inorderValues(){ + List> inorder = inorder(); + List result = new ArrayList<>(inorder.size()); + for (Node node: inorder) { + result.add(node.getVal()); + } + return result; + } + + private List> preorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + preorder(root, result); + return result; + } + + private void preorder(Node current, List> result) { + if (current == null) { + return; + } + + result.add(current); + inorder(current.getLeftChild(), result); + inorder(current.getRightChild(), result); + } + + // returns the minimum node in the subtree of input node + private Node getMin(Node node) { + while (node.getLeftChild() != null) { + node = node.getLeftChild(); + } + return node; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 4416a004ab2..75bf4dfc2d7 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -69,4 +69,9 @@ public int compareTo(Interval o) { public boolean isValid() { return getStart().compareTo(getEnd()) <= 0; } + + @Override + public String toString() { + return "Interval[" + start + ", " + end + "]"; + } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java new file mode 100644 index 00000000000..00b59e72052 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java @@ -0,0 +1,33 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class IntervalTreeTest { + List sorted = new LinkedList<>(); + IntervalTree tree = new IntervalTree<>(); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 20; i++) { + IntegerInterval interval = new IntegerInterval(i, i+3); + tree.add(interval); + sorted.add(interval); + } + } + + @Test + public void test1() { + for (int i = 3; i < 20; i++) { + assertEquals("loop " + i, 4, tree.overlapsWithPoint(i).size()); + } + } + + +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java new file mode 100644 index 00000000000..cc2808afad1 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java @@ -0,0 +1,39 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class RedBlackIntervalTreeTest { + List list = new LinkedList<>(); + List sorted = new LinkedList<>(); + RedBlackIntervalTree tree = new RedBlackIntervalTree<>(); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 20; i++) { + IntegerInterval interval = new IntegerInterval(i, i+3); + tree.insert(i, interval); + sorted.add(interval); + } + } + + @Test + public void testInorder() { + List result = tree.inorderValues(); + for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { + IntegerInterval i = result.get(i1); + assertEquals("fault at " + i1,i, sorted.get(i1)); + } + + + tree.delete(5); + assertFalse(tree.contains(5)); + assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getHi()); + } +} \ No newline at end of file From 52369bfda36094aeebc2499d98063a815b5920b3 Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Fri, 20 Apr 2018 20:52:27 +0200 Subject: [PATCH 029/131] Added overlapsWith() and very few comments --- .../jgrapht/intervalgraph/IntervalTree.java | 33 ++++++++++++++++++- .../intervalgraph/RedBlackIntervalTree.java | 2 ++ .../intervalgraph/IntervalTreeTest.java | 8 ++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java index d67c72f1d07..5a540adf1d9 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java @@ -19,7 +19,34 @@ public class IntervalTree> implements IntervalTreeInterf */ @Override public List> overlapsWith(Interval interval) { - return null; + List> result = new LinkedList<>(); + + overlapsWith(tree.getRoot(), interval, result); + + return result; + } + + private void overlapsWith(Node> node, Interval interval, List> result) { + if (node == null) { + return; + } + + // query starts strictly after any interval in the subtree + if (interval.getStart().compareTo(node.getHi()) > 0) { + return; + } + + // node and query overlap + if (node.getVal().isIntersecting(interval)) { + result.add(node.getVal()); + } + + // if the node starts before the query ends, check right children + if (node.getVal().getStart().compareTo(interval.getEnd()) <= 0) { + overlapsWith(node.getRightChild(), interval, result); + } + + overlapsWith(node.getLeftChild(), interval, result); } @Override @@ -35,16 +62,20 @@ private void overlapsWithPoint(Node> node, T point, List 0) { return; } + // check left subtrees overlapsWithPoint(node.getLeftChild(), point, result); + // add node interval if it contains the query point if (node.getVal().contains(point)) { result.add(node.getVal()); } + // check right subtree if their start values are smaller (equal) than query point if (point.compareTo(node.getVal().getStart()) >= 0) { overlapsWithPoint(node.getRightChild(), point, result); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index cb27be5cb30..f6b741b37ee 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -2,6 +2,8 @@ import org.jgrapht.intervalgraph.interval.Interval; +// Essentially, this class updates the hi value after any operation on this tree. +// The hi value equals to the highest endpoint in the subtree public class RedBlackIntervalTree, I extends Interval> extends RedBlackTree{ @Override protected Node rotateRight(Node node) { diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java index 00b59e72052..8cdacf32eb2 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java @@ -29,5 +29,11 @@ public void test1() { } } - + @Test + public void testIntervalOverlap() { + assertEquals(4, tree.overlapsWith(new IntegerInterval(0,3)).size()); + assertEquals(1 , tree.overlapsWith(new IntegerInterval(0,0)).size()); + assertEquals(0, tree.overlapsWith(new IntegerInterval(-3, -1)).size()); + assertEquals(20, tree.overlapsWith(new IntegerInterval(-5, 20)).size()); + } } \ No newline at end of file From a2eb2587efff15e1db04fe7be6bc66b46bf5f761 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Apr 2018 22:01:17 +0200 Subject: [PATCH 030/131] changes in interval tree data strcuture to ensure correct abstraction and last implementations --- .../IntervalGraphVertexContainer.java | 24 ++-- .../IntervalStructureInterface.java | 39 +++++++ .../jgrapht/intervalgraph/IntervalTree.java | 105 ------------------ .../intervalgraph/IntervalTreeInterface.java | 32 +----- .../intervalgraph/IntervalTreeStructure.java | 51 +++++++++ .../intervalgraph/RedBlackIntervalTree.java | 70 +++++++++++- ...=> CenteredIntervalTreeStructureTest.java} | 2 +- ...st.java => IntervalTreeStructureTest.java} | 4 +- ...=> RedBlackIntervalTreeStructureTest.java} | 2 +- 9 files changed, 181 insertions(+), 148 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java rename jgrapht-core/src/test/java/org/jgrapht/intervalgraph/{CenteredIntervalTreeTest.java => CenteredIntervalTreeStructureTest.java} (94%) rename jgrapht-core/src/test/java/org/jgrapht/intervalgraph/{IntervalTreeTest.java => IntervalTreeStructureTest.java} (90%) rename jgrapht-core/src/test/java/org/jgrapht/intervalgraph/{RedBlackIntervalTreeTest.java => RedBlackIntervalTreeStructureTest.java} (95%) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 3b76fc9f3b0..67c34c5c3e4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -5,21 +5,20 @@ import org.jgrapht.intervalgraph.interval.IntervalVertex; import java.io.Serializable; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { private static final long serialVersionUID = 7768940080894764546L; - private IntervalTreeInterface intervalTree; + private IntervalStructureInterface intervalTree; private Map> vertexMap; + private Map, V> intervalMap; public IntervalGraphVertexContainer() { - this.intervalTree = new IntervalTree<>(); + this.intervalTree = new IntervalTreeStructure<>(); this.vertexMap = new LinkedHashMap<>(); + this.intervalMap = new LinkedHashMap<>(); } /** @@ -39,9 +38,14 @@ public Set getVertexSet() { */ @Override public List getOverlappingIntervalVertices(V vertex) { - //TODO Daniel - // return intervalTree.overlapsWith(vertex.getInterval()); - return null; + List> intervalList = intervalTree.overlapsWith(vertex.getInterval()); + List vertexList = new LinkedList<>(); + + for(Interval interval: intervalList) { + vertexList.add(intervalMap.get(interval)); + } + + return vertexList; } /** @@ -64,6 +68,7 @@ public UndirectedEdgeContainer get(V vertex) { @Override public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec) { intervalTree.add(vertex.getInterval()); + intervalMap.put(vertex.getInterval(), vertex); return vertexMap.put(vertex, ec); } @@ -76,6 +81,7 @@ public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer @Override public UndirectedEdgeContainer remove(V vertex) { intervalTree.remove(vertex.getInterval()); + intervalMap.remove(vertex.getInterval()); return vertexMap.remove(vertex); } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java new file mode 100644 index 00000000000..598f9f13f32 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java @@ -0,0 +1,39 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.List; + +public interface IntervalStructureInterface> { + + /** + * Returns all intervals that overlap with the given interval + * + * @param interval the interval + * @return all intervals that overlap with the given interval + */ + public List> overlapsWith(Interval interval); + + + /** + * Returns all intervals that overlap with the given point + * @param point the point + * @return all intervals that overlap with the given point + */ + public List> overlapsWithPoint(T point); + + /** + * adds an interval to the interval tree + * + * @param interval the interval + */ + public void add(Interval interval); + + /** + * removes an interval from the tree + * + * @param interval the interval + * @return + */ + public void remove(Interval interval); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java deleted file mode 100644 index 5a540adf1d9..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTree.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.jgrapht.intervalgraph; - -import org.jgrapht.intervalgraph.interval.Interval; - -import java.io.Serializable; -import java.util.LinkedList; -import java.util.List; - -public class IntervalTree> implements IntervalTreeInterface, Serializable { - private static final long serialVersionUID = 2834567756342332325L; - - private RedBlackIntervalTree> tree = new RedBlackIntervalTree<>(); - - /** - * Returns all intervals that overlap with the given interval - * - * @param interval the interval - * @return all intervals that overlap with the given interval - */ - @Override - public List> overlapsWith(Interval interval) { - List> result = new LinkedList<>(); - - overlapsWith(tree.getRoot(), interval, result); - - return result; - } - - private void overlapsWith(Node> node, Interval interval, List> result) { - if (node == null) { - return; - } - - // query starts strictly after any interval in the subtree - if (interval.getStart().compareTo(node.getHi()) > 0) { - return; - } - - // node and query overlap - if (node.getVal().isIntersecting(interval)) { - result.add(node.getVal()); - } - - // if the node starts before the query ends, check right children - if (node.getVal().getStart().compareTo(interval.getEnd()) <= 0) { - overlapsWith(node.getRightChild(), interval, result); - } - - overlapsWith(node.getLeftChild(), interval, result); - } - - @Override - public List> overlapsWithPoint(T point) { - List> result = new LinkedList<>(); - - overlapsWithPoint(tree.getRoot(), point, result); - return result; - } - - private void overlapsWithPoint(Node> node, T point, List> result) { - if (node == null) { - return; - } - - // point is bigger than the endpoint of any interval in the subtree - if (point.compareTo(node.getHi()) > 0) { - return; - } - - // check left subtrees - overlapsWithPoint(node.getLeftChild(), point, result); - - // add node interval if it contains the query point - if (node.getVal().contains(point)) { - result.add(node.getVal()); - } - - // check right subtree if their start values are smaller (equal) than query point - if (point.compareTo(node.getVal().getStart()) >= 0) { - overlapsWithPoint(node.getRightChild(), point, result); - } - } - - - /** - * adds an interval to the interval tree - * - * @param interval the interval - */ - @Override - public void add(Interval interval) { - tree.insert(interval.getStart(), interval); - } - - /** - * removes an interval from the tree - * - * @param interval the interval - * @return - */ - @Override - public void remove(Interval interval) { - tree.delete(interval.getStart()); - } -} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index 0516a21c8b0..1179c3fed19 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -4,36 +4,10 @@ import java.util.List; -public interface IntervalTreeInterface> { +public interface IntervalTreeInterface, I extends Interval> extends BinarySearchTree { - /** - * Returns all intervals that overlap with the given interval - * - * @param interval the interval - * @return all intervals that overlap with the given interval - */ - public List> overlapsWith(Interval interval); + List overlapsWith(I interval); + List overlapsWithPoint(T point); - /** - * Returns all intervals that overlap with the given point - * @param point the point - * @return all intervals that overlap with the given point - */ - public List> overlapsWithPoint(T point); - - /** - * adds an interval to the interval tree - * - * @param interval the interval - */ - public void add(Interval interval); - - /** - * removes an interval from the tree - * - * @param interval the interval - * @return - */ - public void remove(Interval interval); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java new file mode 100644 index 00000000000..db9515f9242 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -0,0 +1,51 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +public class IntervalTreeStructure> implements IntervalStructureInterface, Serializable { + private static final long serialVersionUID = 2834567756342332325L; + + private IntervalTreeInterface> tree = new RedBlackIntervalTree<>(); + + /** + * Returns all intervals that overlap with the given interval + * + * @param interval the interval + * @return all intervals that overlap with the given interval + */ + @Override + public List> overlapsWith(Interval interval) { + return tree.overlapsWith(interval); + } + + @Override + public List> overlapsWithPoint(T point) { + return tree.overlapsWithPoint(point); + } + + + /** + * adds an interval to the interval tree + * + * @param interval the interval + */ + @Override + public void add(Interval interval) { + tree.insert(interval.getStart(), interval); + } + + /** + * removes an interval from the tree + * + * @param interval the interval + * @return + */ + @Override + public void remove(Interval interval) { + tree.delete(interval.getStart()); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index f6b741b37ee..5b5e230fca2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -2,9 +2,30 @@ import org.jgrapht.intervalgraph.interval.Interval; +import java.util.LinkedList; +import java.util.List; + // Essentially, this class updates the hi value after any operation on this tree. // The hi value equals to the highest endpoint in the subtree -public class RedBlackIntervalTree, I extends Interval> extends RedBlackTree{ +public class RedBlackIntervalTree, I extends Interval> extends RedBlackTree implements IntervalTreeInterface { + + @Override + public List overlapsWith(I interval) { + List result = new LinkedList<>(); + + overlapsWith(this.getRoot(), interval, result); + + return result; + } + + @Override + public List overlapsWithPoint(T point) { + List result = new LinkedList<>(); + + overlapsWithPoint(this.getRoot(), point, result); + return result; + } + @Override protected Node rotateRight(Node node) { // Perform rotation as usual @@ -77,4 +98,51 @@ public T max(T t1, T t2) { return t2; } } + + private void overlapsWith(Node node, Interval interval, List result) { + if (node == null) { + return; + } + + // query starts strictly after any interval in the subtree + if (interval.getStart().compareTo(node.getHi()) > 0) { + return; + } + + // node and query overlap + if (node.getVal().isIntersecting(interval)) { + result.add(node.getVal()); + } + + // if the node starts before the query ends, check right children + if (node.getVal().getStart().compareTo(interval.getEnd()) <= 0) { + overlapsWith(node.getRightChild(), interval, result); + } + + overlapsWith(node.getLeftChild(), interval, result); + } + + private void overlapsWithPoint(Node node, T point, List result) { + if (node == null) { + return; + } + + // point is bigger than the endpoint of any interval in the subtree + if (point.compareTo(node.getHi()) > 0) { + return; + } + + // check left subtrees + overlapsWithPoint(node.getLeftChild(), point, result); + + // add node interval if it contains the query point + if (node.getVal().contains(point)) { + result.add(node.getVal()); + } + + // check right subtree if their start values are smaller (equal) than query point + if (point.compareTo(node.getVal().getStart()) >= 0) { + overlapsWithPoint(node.getRightChild(), point, result); + } + } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java similarity index 94% rename from jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java rename to jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java index 584e9dde857..fdb3317bbd0 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.*; -public class CenteredIntervalTreeTest { +public class CenteredIntervalTreeStructureTest { IntegerInterval i00 = new IntegerInterval(0,0); IntegerInterval i01 = new IntegerInterval(0,1); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java similarity index 90% rename from jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java rename to jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java index 8cdacf32eb2..bb24b3165fe 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java @@ -9,9 +9,9 @@ import static org.junit.Assert.*; -public class IntervalTreeTest { +public class IntervalTreeStructureTest { List sorted = new LinkedList<>(); - IntervalTree tree = new IntervalTree<>(); + IntervalTreeStructure tree = new IntervalTreeStructure<>(); @Before public void setUp() throws Exception { diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java similarity index 95% rename from jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java rename to jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index cc2808afad1..331e925e8cc 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -9,7 +9,7 @@ import static org.junit.Assert.*; -public class RedBlackIntervalTreeTest { +public class RedBlackIntervalTreeStructureTest { List list = new LinkedList<>(); List sorted = new LinkedList<>(); RedBlackIntervalTree tree = new RedBlackIntervalTree<>(); From 23399e224d33cab4e88f0c61c62490a8f3f23e44 Mon Sep 17 00:00:00 2001 From: Abdallah Date: Sat, 21 Apr 2018 15:44:16 +0200 Subject: [PATCH 031/131] IOrdering Algorithm added For a sweep and a graph the algorithm checks if the sweep is an i-ordering --- .../jgrapht/alg/intervalgraph/IOrdering.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java new file mode 100644 index 00000000000..6a8a3d44534 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java @@ -0,0 +1,32 @@ +package org.jgrapht.alg.intervalgraph; + +import org.jgrapht.Graph; + +public class IOrdering{ + + /** + * Calculates if the given sweep is an I-Ordering + * (according to the Graph graph) + * + * @param sweep the order we want to check if its an I-Order + * @param graph the graph we want to check if its an I-Order + * @return true, if sweep is an I-Order according to graph + */ + public boolean IsIOrder(V[] sweep, Graph graph) + { + for (int i=0; i Date: Sun, 22 Apr 2018 03:28:03 +0200 Subject: [PATCH 032/131] LBFS/+ changed to work around existing LBFS implementation, hopefully --- .../intervalgraph/LexBreadthFirstSearch.java | 50 ++++ .../intervalgraph/LexBreathFirstSearch.java | 217 ------------------ .../traverse/LexBreadthFirstIterator.java | 90 +++++++- 3 files changed, 130 insertions(+), 227 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java new file mode 100644 index 00000000000..9fc5fc53a55 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java @@ -0,0 +1,50 @@ +package org.jgrapht.alg.intervalgraph; + +import org.jgrapht.*; +import org.jgrapht.traverse.*; + +import java.util.*; + +public class LexBreadthFirstSearch +{ + + /** + * Performs a lexicographical BFS starting at {@code startingVertex}. + * + * @param graph the graph we want to perform LBFS on + * @param startingVertex the starting vertex of the LBFS + * @return an array of vertices representing the order in which the vertices were found + */ + public List lexBreadthFirstSearch(Graph graph, V startingVertex) + { + ArrayList result = new ArrayList<>(graph.vertexSet().size()); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph); + + for(int i = 0; i < graph.vertexSet().size(); i++) { + result.add(lbfIterator.next()); + } + + return result; + } + + /** + * Performs LBFS+ starting at {@code startingVertex} using the previous ordering {@code prevOrdering}. + * + * @param graph the graph we want to perform LBFS on + * @param startingVertex the starting vertex of the LBFS + * @param priority the priority of vertices for tiebreaking + * @return an array of vertices representing the order in which the vertices were found + */ + + public List lexBreadthFirstSearch(Graph graph, V startingVertex, V[] priority) + { + ArrayList result = new ArrayList<>(graph.vertexSet().size()); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority); + + for(int i = 0; i < graph.vertexSet().size(); i++) { + result.add(lbfIterator.next()); + } + + return result; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java deleted file mode 100644 index 25b8dcc5e15..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreathFirstSearch.java +++ /dev/null @@ -1,217 +0,0 @@ -package org.jgrapht.alg.intervalgraph; - -import org.jgrapht.*; - -import java.util.*; - -public class LexBreathFirstSearch -{ - - /** - * Performs a lexicographical BFS starting at {@code startingVertex}. - * - * @param graph the graph we want to perform LBFS on - * @param startingVertex the starting vertex of the LBFS - * @return an array of vertices representing the order in which the vertices were found - */ - public V[] lexBreathFirstSearch(Graph graph, V startingVertex) - { - int n = graph.vertexSet().size(); - ArrayList ordering = new ArrayList(); - - String maxLabel = Integer.toString(n); - - HashMap> labelToVertexMap = new HashMap>(); - HashMap vertexToLabelMap = new HashMap(); - - // initialize labels to be empty ... - ArrayList initialVertexList = new ArrayList(graph.vertexSet()); - initialVertexList.remove(startingVertex); - - labelToVertexMap.put("", initialVertexList); - - for(V vertex : initialVertexList) { - vertexToLabelMap.put(vertex, ""); - } - - // ... except for the starting vertex - ArrayList startingVertexList = new ArrayList(); - startingVertexList.add(startingVertex); - - labelToVertexMap.put(maxLabel, startingVertexList); - vertexToLabelMap.put(startingVertex, maxLabel); - - for(int i = n; i >= 1; i--) { - // pick unvisited vertex v with largest label - ArrayList candidates = labelToVertexMap.get(maxLabel); - V currentVertex = candidates.get(0); - - // set index of v to be n + 1 - i - ordering.add(currentVertex); - - // for every unvisited neighbor w of v, append i to label of w - for(V neighbor : Graphs.neighborListOf(graph, currentVertex)) { - String oldLabel = vertexToLabelMap.get(neighbor); - String newLabel = oldLabel + Integer.toString(i); - - // remove neighbor from previous list - ArrayList oldList = labelToVertexMap.get(oldLabel); - oldList.remove(neighbor); - - // if there are no vertices left in this list, delete the entry - if(oldList.isEmpty()) { - labelToVertexMap.remove(oldLabel); - } else { - // else we replace the list with its updated version - labelToVertexMap.replace(oldLabel, oldList); - } - - // now add neighbor to the list of the new label - if(labelToVertexMap.containsKey(newLabel)) { - ArrayList newList = labelToVertexMap.get(newLabel); - newList.add(neighbor); - labelToVertexMap.replace(newLabel, newList); - } else { - ArrayList newList = new ArrayList(); - newList.add(neighbor); - labelToVertexMap.put(newLabel, newList); - } - - // associate neighbor with its new label - vertexToLabelMap.replace(neighbor, newLabel); - } - - // mark current vertex as visited, i.e. remove its entries from the maps - vertexToLabelMap.remove(currentVertex); - candidates.remove(currentVertex); - labelToVertexMap.replace(maxLabel, candidates); - } - - // return ordering -- thanks Java for not being able to create an array from a list with generic types for some reason - V[] orderingArray = null; - orderingArray = ordering.toArray(orderingArray); - - return orderingArray; - } - - /** - * Performs LBFS+ starting at {@code startingVertex} using the previous ordering {@code prevOrdering}. - * - * @param graph the graph we want to perform LBFS on - * @param startingVertex the starting vertex of the LBFS - * @param prevOrdering the previous LBFS ordering given as an array - * @return an array of vertices representing the order in which the vertices were found - */ - public V[] lexBreathFirstSearch(Graph graph, V startingVertex, V[] prevOrdering) - { - LBFSComparator comp = new LBFSComparator(prevOrdering); - - int n = graph.vertexSet().size(); - ArrayList ordering = new ArrayList(); - - String maxLabel = Integer.toString(n); - - HashMap> labelToVertexMap = new HashMap>(); - HashMap vertexToLabelMap = new HashMap(); - - // initialize labels to be empty ... - ArrayList initialVertexList = new ArrayList(graph.vertexSet()); - initialVertexList.remove(startingVertex); - - labelToVertexMap.put("", initialVertexList); - - for(V vertex : initialVertexList) { - vertexToLabelMap.put(vertex, ""); - } - - // ... except for the starting vertex - ArrayList startingVertexList = new ArrayList(); - startingVertexList.add(startingVertex); - - labelToVertexMap.put(maxLabel, startingVertexList); - vertexToLabelMap.put(startingVertex, maxLabel); - - for(int i = n; i >= 1; i--) { - // pick unvisited vertex v with largest label - ArrayList candidates = labelToVertexMap.get(maxLabel); - - // LBFS+: pick the vertex with the lex. largest label which appears last in the previous ordering - candidates.sort(comp.reversed()); - V currentVertex = candidates.get(0); - - // set index of v to be n + 1 - i - ordering.add(currentVertex); - - // for every unvisited neighbor w of v, append i to label of w - for(V neighbor : Graphs.neighborListOf(graph, currentVertex)) { - String oldLabel = vertexToLabelMap.get(neighbor); - String newLabel = oldLabel + Integer.toString(i); - - // remove neighbor from previous list - ArrayList oldList = labelToVertexMap.get(oldLabel); - oldList.remove(neighbor); - - // if there are no vertices left in this list, delete the entry - if(oldList.isEmpty()) { - labelToVertexMap.remove(oldLabel); - } else { - // else we replace the list with its updated version - labelToVertexMap.replace(oldLabel, oldList); - } - - // now add neighbor to the list of the new label - if(labelToVertexMap.containsKey(newLabel)) { - ArrayList newList = labelToVertexMap.get(newLabel); - newList.add(neighbor); - labelToVertexMap.replace(newLabel, newList); - } else { - ArrayList newList = new ArrayList(); - newList.add(neighbor); - labelToVertexMap.put(newLabel, newList); - } - - // associate neighbor with its new label - vertexToLabelMap.replace(neighbor, newLabel); - } - - // mark current vertex as visited, i.e. remove its entries from the maps - vertexToLabelMap.remove(currentVertex); - candidates.remove(currentVertex); - labelToVertexMap.replace(maxLabel, candidates); - } - - // return ordering -- thanks Java for not being able to create an array from a list with generic types for some reason - V[] orderingArray = null; - orderingArray = ordering.toArray(orderingArray); - - return orderingArray; - } - - class LBFSComparator implements Comparator - { - private final V[] prevOrdering; - - public LBFSComparator(V[] prevOrdering) { - this.prevOrdering = prevOrdering; - } - - // apparantly Java has no indexOf method... - private int indexOf(V vertex) throws NoSuchElementException{ - for(int index = 0; index < prevOrdering.length; index++) { - if(prevOrdering[index].equals(vertex)) { - return index; - } - } - throw new NoSuchElementException("Previous ordering is on a different vertex set."); - } - - @Override - public int compare(V vertex1, V vertex2) - { - int index1 = indexOf(vertex1); - int index2 = indexOf(vertex2); - - return (index1 - index2); - } - } -} diff --git a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java index 2d330fcf85f..977094f28b7 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java +++ b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java @@ -74,6 +74,18 @@ public LexBreadthFirstIterator(Graph graph) { GraphTests.requireUndirected(graph); bucketList = new BucketList(graph.vertexSet()); } + + /** + * Creates new lexicographical breadth-first iterator with a static priority list for {@code graph}. + * + * @param graph the graph to be iterated. + * @param priority the vertex array sorted by their priorities. + */ + public LexBreadthFirstIterator(Graph graph, V[] priority) { + super(graph); + GraphTests.requireUndirected(graph); + bucketList = new BucketList(graph.vertexSet(), new PriorityComparator(priority)); + } /** * Checks whether there exist unvisited vertices. @@ -182,14 +194,34 @@ class BucketList { * the vertex in constant time. */ private Map bucketMap; - + + /** + * Comparator used for tiebreaking when multiple vertices have the same label + */ + private Comparator priorityComparator = null; + /** * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. * * @param vertices the vertices of the graph, that should be stored in the {@code head} bucket. */ BucketList(Collection vertices) { - head = new Bucket(vertices); + head = new Bucket(vertices, priorityComparator); // we do not need a comparator + bucketMap = new HashMap<>(vertices.size()); + for (V vertex : vertices) { + bucketMap.put(vertex, head); + } + } + + /** + * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. + * + * @param vertices the vertices of the graph, that should be stored in the {@code head} bucket. + * @param priorityComparator a comparator which defines a priority for tiebreaking. + */ + BucketList(Collection vertices, Comparator priorityComparator) { + this.priorityComparator = priorityComparator; + head = new Bucket(vertices, priorityComparator); bucketMap = new HashMap<>(vertices.size()); for (V vertex : vertices) { bucketMap.put(vertex, head); @@ -251,7 +283,7 @@ void updateBuckets(Set vertices) { bucketMap.put(vertex, bucket.prev); } else { visitedBuckets.add(bucket); - Bucket newBucket = new Bucket(vertex); + Bucket newBucket = new Bucket(vertex, priorityComparator); newBucket.insertBefore(bucket); bucketMap.put(vertex, newBucket); if (head == bucket) { @@ -285,15 +317,20 @@ private class Bucket { /** * Set of vertices currently stored in this bucket. */ - private Set vertices; + private Queue vertices; /** * Creates a new bucket with all {@code vertices} stored in it. * * @param vertices vertices to store in this bucket. */ - Bucket(Collection vertices) { - this.vertices = new HashSet<>(vertices); + Bucket(Collection vertices, Comparator c) { + if(c == null) { + this.vertices = new PriorityQueue<>(); + } else { + this.vertices = new PriorityQueue<>(c); + } + this.vertices.addAll(vertices); } /** @@ -301,8 +338,12 @@ private class Bucket { * * @param vertex the vertex to store in this bucket. */ - Bucket(V vertex) { - this.vertices = new HashSet<>(); + Bucket(V vertex, Comparator c) { + if(c == null) { + this.vertices = new PriorityQueue<>(); + } else { + this.vertices = new PriorityQueue<>(c); + } vertices.add(vertex); } @@ -363,8 +404,7 @@ V poll() { if (vertices.isEmpty()) { return null; } else { - V vertex = vertices.iterator().next(); - vertices.remove(vertex); + V vertex = vertices.poll(); return vertex; } } @@ -379,4 +419,34 @@ boolean isEmpty() { } } } + + class PriorityComparator implements Comparator + { + private final V[] priority; + + public PriorityComparator(V[] priority) throws IllegalArgumentException { + if(priority == null) { + throw new IllegalArgumentException("Priority array must not be null"); + } + this.priority = priority; + } + + private int indexOf(V vertex) throws NoSuchElementException { + for(int index = 0; index < priority.length; index++) { + if(priority[index].equals(vertex)) { + return index; + } + } + throw new NoSuchElementException("Priority is on a different vertex set."); + } + + @Override + public int compare(V vertex1, V vertex2) + { + int index1 = indexOf(vertex1); + int index2 = indexOf(vertex2); + + return (index1 - index2); + } + } } From ed9c4e71c048c3f6b17f6e731eb8d4f225ab044e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Apr 2018 12:59:14 +0200 Subject: [PATCH 033/131] added class IntervalTreeNodeValue to use this as wrapper class for the value of the interval tree nodes --- .../intervalgraph/IntervalTreeInterface.java | 8 +- .../intervalgraph/IntervalTreeNodeValue.java | 94 +++++++++++++++++++ .../java/org/jgrapht/intervalgraph/Node.java | 10 -- .../intervalgraph/RedBlackIntervalTree.java | 64 ++++++------- 4 files changed, 131 insertions(+), 45 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index 1179c3fed19..2fa5cec4a86 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -1,13 +1,15 @@ package org.jgrapht.intervalgraph; +import jdk.javadoc.internal.doclets.formats.html.PackageIndexFrameWriter; +import org.jgrapht.alg.util.Pair; import org.jgrapht.intervalgraph.interval.Interval; import java.util.List; -public interface IntervalTreeInterface, I extends Interval> extends BinarySearchTree { +public interface IntervalTreeInterface, NodeValue extends IntervalTreeNodeValue, T>> extends BinarySearchTree { - List overlapsWith(I interval); + List> overlapsWith(Interval interval); - List overlapsWithPoint(T point); + List> overlapsWithPoint(T point); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java new file mode 100644 index 00000000000..9bb88f5aedb --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -0,0 +1,94 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.alg.util.Pair; +import org.jgrapht.intervalgraph.interval.Interval; + +import java.io.Serializable; +import java.util.Objects; + +public class IntervalTreeNodeValue, T extends Comparable> implements Serializable { + + private static final long serialVersionUID = 1111005364785643338L; + + private Interval interval; + + private T highValue; + + /** + * Create a new pair + * + * @param interval the first element + * @param highValue the second element + */ + public IntervalTreeNodeValue(I interval, T highValue) { + this.interval = interval; + this.highValue = highValue; + } + + /** + * Get the first element of the pair + * + * @return the first element of the pair + */ + public Interval getInterval() + { + return interval; + } + + /** + * Get the second element of the pair + * + * @return the second element of the pair + */ + public T getHighValue() + { + return highValue; + } + + public void setHighValue(T highValue) { + this.highValue = highValue; + } + + + public boolean hasInterval(E e) + { + if (e == null) { + return interval == null; + } else { + return e.equals(interval); + } + } + + public boolean hasHighValue(E e) + { + if (e == null) { + return highValue == null; + } else { + return e.equals(highValue); + } + } + + @Override + public String toString() + { + return "(" + interval + "," + highValue + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + else if (!(o instanceof IntervalTreeNodeValue)) + return false; + + @SuppressWarnings("unchecked") IntervalTreeNodeValue other = (IntervalTreeNodeValue) o; + return Objects.equals(interval, other.interval) && Objects.equals(highValue, other.highValue); + } + + @Override + public int hashCode() + { + return Objects.hash(interval, highValue); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index d3875dc5eb8..0d211200992 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -75,14 +75,4 @@ protected int getSize() { public void setKey(K key) { this.key = key; } - - private K hi; - - public K getHi() { - return hi; - } - - public void setHi(K hi) { - this.hi = hi; - } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index 5b5e230fca2..a5704ff8616 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -7,11 +7,11 @@ // Essentially, this class updates the hi value after any operation on this tree. // The hi value equals to the highest endpoint in the subtree -public class RedBlackIntervalTree, I extends Interval> extends RedBlackTree implements IntervalTreeInterface { +public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface { @Override - public List overlapsWith(I interval) { - List result = new LinkedList<>(); + public List> overlapsWith(Interval interval) { + List> result = new LinkedList<>(); overlapsWith(this.getRoot(), interval, result); @@ -19,74 +19,74 @@ public List overlapsWith(I interval) { } @Override - public List overlapsWithPoint(T point) { - List result = new LinkedList<>(); + public List> overlapsWithPoint(T point) { + List> result = new LinkedList<>(); overlapsWithPoint(this.getRoot(), point, result); return result; } @Override - protected Node rotateRight(Node node) { + protected Node rotateRight(Node node) { // Perform rotation as usual - Node result = super.rotateRight(node); + Node result = super.rotateRight(node); // update hi vals - result.setHi(node.getHi()); + result.getVal().setHighValue(node.getVal().getHighValue()); updateHi(node); return result; } @Override - protected Node rotateLeft(Node node) { + protected Node rotateLeft(Node node) { // Perform rotation as usual - Node result = super.rotateLeft(node); + Node result = super.rotateLeft(node); // update hi vals - result.setHi(node.getHi()); + result.getVal().setHighValue(node.getVal().getHighValue()); updateHi(node); return result; } @Override - protected Node delete(Node current, T key) { - Node result = super.delete(current, key); + protected Node delete(Node current, T key) { + Node result = super.delete(current, key); updateHi(result); return result; } @Override - protected Node insert(Node current, T key, I val) { - Node result = super.insert(current, key, val); + protected Node insert(Node current, T key, NodeValue val) { + Node result = super.insert(current, key, val); updateHi(result); return result; } @Override - protected Node balance(Node node) { - Node result = super.balance(node); + protected Node balance(Node node) { + Node result = super.balance(node); updateHi(result); return result; } // sets the hi attribute of the given node to the max of the subtree or itself - private void updateHi(Node node) { + private void updateHi(Node node) { if (node == null) { return; } - T result = node.getVal().getEnd(); + T result = node.getVal().getInterval().getEnd(); if (node.getRightChild() != null) { - result = max(result, node.getRightChild().getHi()); + result = max(result, node.getRightChild().getVal().getHighValue()); } if (node.getLeftChild() != null) { - result = max(result, node.getLeftChild().getHi()); + result = max(result, node.getLeftChild().getVal().getHighValue()); } - node.setHi(result); + node.getVal().setHighValue(result); } @@ -99,36 +99,36 @@ public T max(T t1, T t2) { } } - private void overlapsWith(Node node, Interval interval, List result) { + private void overlapsWith(Node node, Interval interval, List> result) { if (node == null) { return; } // query starts strictly after any interval in the subtree - if (interval.getStart().compareTo(node.getHi()) > 0) { + if (interval.getStart().compareTo(node.getVal().getHighValue()) > 0) { return; } // node and query overlap - if (node.getVal().isIntersecting(interval)) { - result.add(node.getVal()); + if (node.getVal().getInterval().isIntersecting(interval)) { + result.add(node.getVal().getInterval()); } // if the node starts before the query ends, check right children - if (node.getVal().getStart().compareTo(interval.getEnd()) <= 0) { + if (node.getVal().getInterval().getStart().compareTo(interval.getEnd()) <= 0) { overlapsWith(node.getRightChild(), interval, result); } overlapsWith(node.getLeftChild(), interval, result); } - private void overlapsWithPoint(Node node, T point, List result) { + private void overlapsWithPoint(Node node, T point, List> result) { if (node == null) { return; } // point is bigger than the endpoint of any interval in the subtree - if (point.compareTo(node.getHi()) > 0) { + if (point.compareTo(node.getVal().getHighValue()) > 0) { return; } @@ -136,12 +136,12 @@ private void overlapsWithPoint(Node node, T point, List result) { overlapsWithPoint(node.getLeftChild(), point, result); // add node interval if it contains the query point - if (node.getVal().contains(point)) { - result.add(node.getVal()); + if (node.getVal().getInterval().contains(point)) { + result.add(node.getVal().getInterval()); } // check right subtree if their start values are smaller (equal) than query point - if (point.compareTo(node.getVal().getStart()) >= 0) { + if (point.compareTo(node.getVal().getInterval().getStart()) >= 0) { overlapsWithPoint(node.getRightChild(), point, result); } } From d8c77a35517ae4226708103771d61a85c688b16e Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Fri, 20 Apr 2018 15:09:47 +0200 Subject: [PATCH 034/131] Add some tests for the interval tree and fix a found bug --- .../intervalgraph/CenteredIntervalTree.java | 8 ++- .../interval/IntegerInterval.java | 5 ++ .../intervalgraph/interval/Interval.java | 8 ++- .../CenteredIntervalTreeTest.java | 52 +++++++++++++++---- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java index 4d27d2d67df..fa05eb8f83a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -45,11 +45,9 @@ private void initialize(List> intervals) { for (Interval interval: intervals) { if (interval.contains(centerPoint)) { intersectingIntervals.add(interval); - } - - if (interval.relativeDistance(centerPoint) < 0) { // is completely left to center point + } else if (interval.compareToPoint(centerPoint) < 0) { // is completely left to center point leftIntervals.add(interval); - } else if (interval.relativeDistance(centerPoint) > 0) { // completely right + } else if (interval.compareToPoint(centerPoint) > 0) { // completely right rightIntervals.add(interval); } } @@ -66,7 +64,7 @@ private void initialize(List> intervals) { leftTree.initialize(leftIntervals); rightTree = new CenteredIntervalTree<>(); - leftTree.initialize(rightIntervals); + rightTree.initialize(rightIntervals); } @Override diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java index e463e70c1e9..81131e8a52a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java @@ -8,4 +8,9 @@ public IntegerInterval(int start, int end) { public int length() { return getEnd() - getStart(); } + + @Override + public String toString() { + return "[" + getStart() + ", " + getEnd() + "]"; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 4416a004ab2..587ed37c7f4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -29,12 +29,12 @@ public boolean contains(T point) { } boolean result = point.compareTo(getStart()) >= 0 && point.compareTo(getEnd()) <= 0; - assert result == (relativeDistance(point) == 0); + assert result == (compareToPoint(point) == 0); return result; } - public int relativeDistance(T o) { + public int compareToPoint(T o) { if (o == null) { throw new IllegalArgumentException(); } @@ -44,10 +44,8 @@ public int relativeDistance(T o) { if (relativeStart <= 0 && relativeEnd >= 0) { return 0; - } else if (relativeStart > 0) { + } else { return relativeStart; - } else { - return relativeEnd; } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java index 584e9dde857..1a813030206 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java @@ -5,7 +5,6 @@ import org.junit.Before; import org.junit.Test; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -13,19 +12,54 @@ public class CenteredIntervalTreeTest { - IntegerInterval i00 = new IntegerInterval(0,0); - IntegerInterval i01 = new IntegerInterval(0,1); - IntegerInterval i56 = new IntegerInterval(5,6); - List> list; + @Test + public void testCompareToPoint() { + IntegerInterval interval = new IntegerInterval(0, 1); + assertEquals(-1, interval.compareToPoint(-1)); + assertEquals(0, interval.compareToPoint(0)); + assertEquals(0, interval.compareToPoint(1)); + assertEquals(1, interval.compareToPoint(2)); + } + + @Test + public void testEmptyTree() { + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-2).size()); + assertEquals(0, tree.intersections(0).size()); + assertEquals(0, tree.intersections((2)).size()); + } + + @Test + public void testSingleInterval() { + list.add(new IntegerInterval(0, 2)); + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-1).size()); + assertEquals(1, tree.intersections(0).size()); + assertEquals(1, tree.intersections(1).size()); + assertEquals(1, tree.intersections(2).size()); + assertEquals(0, tree.intersections(3).size()); + } @Test - public void intersections() { + public void testPath() { + list.add(new IntegerInterval(0, 1)); + list.add(new IntegerInterval(1, 2)); + list.add(new IntegerInterval(2, 3)); + list.add(new IntegerInterval(3, 4)); + list.add(new IntegerInterval(4, 5)); + list.add(new IntegerInterval(5, 6)); CenteredIntervalTree tree = new CenteredIntervalTree<>(list); - assertEquals(0, tree.intersections(2).size()); - assertEquals(2, tree.intersections(0).size()); - assertEquals(0, new CenteredIntervalTree(new LinkedList<>()).intersections(0).size()); + assertEquals(0, tree.intersections(-1).size()); + assertEquals(1, tree.intersections(0).size()); + assertEquals(2, tree.intersections(1).size()); + assertEquals(2, tree.intersections(2).size()); + assertEquals(2, tree.intersections(3).size()); + assertEquals(2, tree.intersections(4).size()); + assertEquals(2, tree.intersections(5).size()); + assertEquals(1, tree.intersections(6).size()); + assertEquals(0, tree.intersections(7).size()); } @Before From 1c5d35d68f2e5ed994cf5c66f793420984b7eee5 Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Sun, 22 Apr 2018 16:43:22 +0200 Subject: [PATCH 035/131] Interval Graph Recognition Algorithm - General Skeleton --- .../jgrapht/alg/intervalgraph/IOrdering.java | 32 ---- .../IntervalGraphRecognizer.java | 142 ++++++++++++++++++ .../intervalgraph/LexBreadthFirstSearch.java | 4 +- 3 files changed, 144 insertions(+), 34 deletions(-) delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java deleted file mode 100644 index 6a8a3d44534..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IOrdering.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.jgrapht.alg.intervalgraph; - -import org.jgrapht.Graph; - -public class IOrdering{ - - /** - * Calculates if the given sweep is an I-Ordering - * (according to the Graph graph) - * - * @param sweep the order we want to check if its an I-Order - * @param graph the graph we want to check if its an I-Order - * @return true, if sweep is an I-Order according to graph - */ - public boolean IsIOrder(V[] sweep, Graph graph) - { - for (int i=0; i the generic type representing vertices + * @param the generic type representing edges + * @return + */ + public static boolean isIntervalGraph(Graph graph) { + // Step 1 - LBFS from an arbitrary vertex + // Input - random vertex r + // Output - the result of current sweep alpha, further last vertex a visited by current sweep + List sweepAlpha = lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); + V vertexA = lastElementOf(sweepAlpha); + + // Step 2 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep alpha, vertex a + // Output - the result of current sweep beta, further last vertex b visited by current sweep + List sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, arrayOf(sweepAlpha)); + V vertexB = lastElementOf(sweepBeta); + + // Step 3 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep beta, vertex b + // Output - the result of current sweep gamma, further last vertex c visited by current sweep + List sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, arrayOf(sweepBeta)); + V vertexC = lastElementOf(sweepGamma); + + // Step 4 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep gamma, vertex c + // Output - the result of current sweep delta, further last vertex d visited by current sweep + List sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, arrayOf(sweepGamma)); + V vertexD = lastElementOf(sweepDelta); + + // Additionally, calculate the index and the corresponding A set for each vertex + + // Step 5 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep delta, vertex d + // Output - the result of current sweep epsilon, further last vertex e visited by current sweep + List sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, arrayOf(sweepDelta)); + V vertexE = lastElementOf(sweepEpsilon); + + // Additionally, calculate the index and the corresponding B set for each vertex + + // Step 6 - LBFS* with the resulting sweeps + // Input - the result of sweep gamma and sweep epsilon + // Output - the result of current sweep zeta + List sweepZeta = null; // TODO: replace by the invocation of lexBreadthFirstSearchStar + + // if sweepZeta is umbrella-free, then the graph is interval. + // otherwise, the graph is not interval + return isIOrdering(arrayOf(sweepZeta), graph); + } + + /** + * Calculates if the given sweep is an I-Ordering + * (according to the Graph graph) + * + * @param sweep the order we want to check if its an I-Order + * @param graph the graph we want to check if its an I-Order + * @return true, if sweep is an I-Order according to graph + */ + private static boolean isIOrdering(V[] sweep, Graph graph) { + for (int i = 0; i < sweep.length - 2; i++) { + for (int j = i + 1; j < sweep.length - 1; j++) { + for (int k = j + 1; k < sweep.length; k++) { + boolean edgeIJ = graph.containsEdge(sweep[i], sweep[j]); + boolean edgeIK = graph.containsEdge(sweep[i], sweep[k]); + if (!edgeIJ && edgeIK) { + return false; + } + } + } + } + return true; + } + + /** + * return the last element of the given list + * + * @param list + * @param the generic type representing vertices + * @return + */ + private static V lastElementOf(List list) { + if (list == null) { + throw new IllegalArgumentException("List parameter cannot be null."); + } + + return list.get(list.size() - 1); + } + + /** + * return a random element of the given set + * + * @param set + * @param the generic type representing vertices + * @return + */ + private static V randomElementOf(Set set) { + if (set == null) { + throw new IllegalArgumentException("List parameter cannot be null."); + } + + int index = new Random().nextInt(set.size()); + Iterator iterator = set.iterator(); + for (int i = 0; i < index; i++) { + iterator.next(); + } + return iterator.next(); + } + + /** + * convert the given list into array in weak typing way + * + * @param list + * @param the generic type representing vertices + * @return + */ + private static V[] arrayOf(List list) { + if (list == null) { + throw new IllegalArgumentException("List parameter cannot be null."); + } + + V[] resultArray = (V[]) new Object[list.size()]; + list.toArray(resultArray); + return resultArray; + } + +} \ No newline at end of file diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java index 9fc5fc53a55..e0d81527b4e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java @@ -15,7 +15,7 @@ public class LexBreadthFirstSearch * @param startingVertex the starting vertex of the LBFS * @return an array of vertices representing the order in which the vertices were found */ - public List lexBreadthFirstSearch(Graph graph, V startingVertex) + public static List lexBreadthFirstSearch(Graph graph, V startingVertex) { ArrayList result = new ArrayList<>(graph.vertexSet().size()); LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph); @@ -36,7 +36,7 @@ public List lexBreadthFirstSearch(Graph graph, V startingVertex) * @return an array of vertices representing the order in which the vertices were found */ - public List lexBreadthFirstSearch(Graph graph, V startingVertex, V[] priority) + public static List lexBreadthFirstSearchPlus(Graph graph, V startingVertex, V[] priority) { ArrayList result = new ArrayList<>(graph.vertexSet().size()); LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority); From 5ad3f1c76e9100e6a2447cf6561babe78b18e86a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Apr 2018 19:55:45 +0200 Subject: [PATCH 036/131] updated method addIntervalEdges() and addVertex() in IntervalGraph such that it can be private. --- .../graph/specifics/IntervalSpecifics.java | 15 +++++++++++---- .../org/jgrapht/intervalgraph/IntervalGraph.java | 4 ++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index dfab4cd44e9..e04e69e2995 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -8,6 +8,7 @@ import org.jgrapht.util.ArrayUnenforcedSet; import java.io.Serializable; +import java.util.List; import java.util.Set; public class IntervalSpecifics implements Specifics, Serializable { @@ -15,7 +16,7 @@ public class IntervalSpecifics implements Specifics private static final long serialVersionUID = 1112673663745687843L; protected IntervalGraph intervalGraph; - protected IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; //TODO anpassen + protected IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; protected EdgeSetFactory edgeSetFactory; /** @@ -33,10 +34,16 @@ public IntervalSpecifics(IntervalGraph intervalGraph) { * {@inheritDoc} */ @Override - public void addVertex(V v) + public void addVertex(V vertex) { - getEdgeContainer(v); - intervalGraph.addIntervalEdges(v, intervalGraphVertexContainerInterface.getOverlappingIntervalVertices(v)); + getEdgeContainer(vertex); + } + + /** + * + */ + public List getOverlappingIntervalVertices(V vertex) { + return intervalGraphVertexContainerInterface.getOverlappingIntervalVertices(vertex); } /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 5461cb98fff..30f6d37ca64 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -173,7 +173,7 @@ public boolean addVertex(V v) return false; } else { specifics.addVertex(v); - + addIntervalEdges(v, specifics.getOverlappingIntervalVertices(v)); return true; } } @@ -450,7 +450,7 @@ protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean we * @param sourceVertex source vertex of all edges * @param targetVertices target vertices of edges */ - public boolean addIntervalEdges(V sourceVertex, Collection targetVertices) { + private boolean addIntervalEdges(V sourceVertex, Collection targetVertices) { assertVertexExist(sourceVertex); From 93cf6dba3d67328570d3aff0e585f2ecf1fa8b38 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Apr 2018 20:01:42 +0200 Subject: [PATCH 037/131] added new line at end of file --- .../java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java index 9bb88f5aedb..539c4200e2f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -91,4 +91,4 @@ public int hashCode() { return Objects.hash(interval, highValue); } -} \ No newline at end of file +} From cdcd83ce0eff1dddef33b88495258a5cba8f964c Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 22 Apr 2018 20:14:08 +0200 Subject: [PATCH 038/131] fixed adding to intervaltree --- .../jgrapht/intervalgraph/IntervalStructureInterface.java | 8 ++++---- .../org/jgrapht/intervalgraph/IntervalTreeStructure.java | 4 ++-- .../org/jgrapht/intervalgraph/RedBlackIntervalTree.java | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java index 598f9f13f32..40befd7ff1c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java @@ -12,7 +12,7 @@ public interface IntervalStructureInterface> { * @param interval the interval * @return all intervals that overlap with the given interval */ - public List> overlapsWith(Interval interval); + List> overlapsWith(Interval interval); /** @@ -20,14 +20,14 @@ public interface IntervalStructureInterface> { * @param point the point * @return all intervals that overlap with the given point */ - public List> overlapsWithPoint(T point); + List> overlapsWithPoint(T point); /** * adds an interval to the interval tree * * @param interval the interval */ - public void add(Interval interval); + void add(Interval interval); /** * removes an interval from the tree @@ -35,5 +35,5 @@ public interface IntervalStructureInterface> { * @param interval the interval * @return */ - public void remove(Interval interval); + void remove(Interval interval); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index db9515f9242..971c165a83c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -9,7 +9,7 @@ public class IntervalTreeStructure> implements IntervalStructureInterface, Serializable { private static final long serialVersionUID = 2834567756342332325L; - private IntervalTreeInterface> tree = new RedBlackIntervalTree<>(); + private IntervalTreeInterface, T>> tree = new RedBlackIntervalTree<>(); /** * Returns all intervals that overlap with the given interval @@ -35,7 +35,7 @@ public List> overlapsWithPoint(T point) { */ @Override public void add(Interval interval) { - tree.insert(interval.getStart(), interval); + tree.insert(interval.getStart(), new IntervalTreeNodeValue<>(interval, null)); } /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index a5704ff8616..896de75395e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -57,7 +57,6 @@ protected Node delete(Node current, T key) { return result; } - @Override protected Node insert(Node current, T key, NodeValue val) { Node result = super.insert(current, key, val); updateHi(result); From 509eff619305fc1059561a92cf5e32d7e7967092 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Apr 2018 10:16:30 +0200 Subject: [PATCH 039/131] added Override to insert() method of RedBlackIntervalTree --- .../java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index 896de75395e..a5704ff8616 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -57,6 +57,7 @@ protected Node delete(Node current, T key) { return result; } + @Override protected Node insert(Node current, T key, NodeValue val) { Node result = super.insert(current, key, val); updateHi(result); From 5083f7ea7c80dceda1e481229d4bfec6e24f27f6 Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Tue, 24 Apr 2018 01:13:13 +0200 Subject: [PATCH 040/131] Implemented basically the missing parts of the algorithm; still need to output interval representation (need to merge interface first tho...)) --- .../IntervalGraphRecognizer.java | 115 +++++----- .../intervalgraph/LexBreadthFirstSearch.java | 78 ++++++- .../traverse/LexBreadthFirstIterator.java | 202 ++++++++++++++++-- 3 files changed, 312 insertions(+), 83 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 67f2df715ac..43f59716c63 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -1,13 +1,12 @@ package org.jgrapht.alg.intervalgraph; -import org.jgrapht.Graph; +import static org.jgrapht.alg.intervalgraph.LexBreadthFirstSearch.*; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.Set; +import java.util.*; -import static org.jgrapht.alg.intervalgraph.LexBreadthFirstSearch.*; +import org.jgrapht.*; +import org.jgrapht.intervalgraph.*; +import org.jgrapht.intervalgraph.interval.*; public final class IntervalGraphRecognizer { @@ -23,25 +22,25 @@ public static boolean isIntervalGraph(Graph graph) { // Step 1 - LBFS from an arbitrary vertex // Input - random vertex r // Output - the result of current sweep alpha, further last vertex a visited by current sweep - List sweepAlpha = lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); + HashMap sweepAlpha = lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); V vertexA = lastElementOf(sweepAlpha); // Step 2 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep alpha, vertex a // Output - the result of current sweep beta, further last vertex b visited by current sweep - List sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, arrayOf(sweepAlpha)); + HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, sweepAlpha); V vertexB = lastElementOf(sweepBeta); // Step 3 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep beta, vertex b // Output - the result of current sweep gamma, further last vertex c visited by current sweep - List sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, arrayOf(sweepBeta)); + HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, sweepBeta); V vertexC = lastElementOf(sweepGamma); // Step 4 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep gamma, vertex c // Output - the result of current sweep delta, further last vertex d visited by current sweep - List sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, arrayOf(sweepGamma)); + HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, sweepGamma); V vertexD = lastElementOf(sweepDelta); // Additionally, calculate the index and the corresponding A set for each vertex @@ -49,57 +48,87 @@ public static boolean isIntervalGraph(Graph graph) { // Step 5 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep delta, vertex d // Output - the result of current sweep epsilon, further last vertex e visited by current sweep - List sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, arrayOf(sweepDelta)); - V vertexE = lastElementOf(sweepEpsilon); + HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, sweepDelta); + // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? // Additionally, calculate the index and the corresponding B set for each vertex // Step 6 - LBFS* with the resulting sweeps // Input - the result of sweep gamma and sweep epsilon // Output - the result of current sweep zeta - List sweepZeta = null; // TODO: replace by the invocation of lexBreadthFirstSearchStar + HashMap sweepZeta = lexBreadthFirstSearchStar(graph, vertexD, sweepDelta, sweepEpsilon); // if sweepZeta is umbrella-free, then the graph is interval. // otherwise, the graph is not interval - return isIOrdering(arrayOf(sweepZeta), graph); + //return isIOrdering(sweepZeta, graph); + + // Compute interval representation -- TODO: complete after merge + HashMap neighborIndex = new HashMap<>(); + for(V vertex : graph.vertexSet()) { + int maxNeighbor = 0; + + List neighbors = Graphs.neighborListOf(graph, vertex); + neighbors.add(vertex); + + for(V neighbor : neighbors) { + maxNeighbor = Math.max(maxNeighbor, sweepZeta.get(neighbor)); + } + + neighborIndex.put(vertex, maxNeighbor); + } + + ArrayList> intervals = new ArrayList<>(graph.vertexSet().size()); + + for(V vertex : graph.vertexSet()) { + Interval vertexInterval = new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); + intervals.add(vertexInterval); + } + + return isIOrdering(sweepZeta, graph); } /** * Calculates if the given sweep is an I-Ordering * (according to the Graph graph) + * @param * * @param sweep the order we want to check if its an I-Order * @param graph the graph we want to check if its an I-Order * @return true, if sweep is an I-Order according to graph */ - private static boolean isIOrdering(V[] sweep, Graph graph) { - for (int i = 0; i < sweep.length - 2; i++) { - for (int j = i + 1; j < sweep.length - 1; j++) { - for (int k = j + 1; k < sweep.length; k++) { - boolean edgeIJ = graph.containsEdge(sweep[i], sweep[j]); - boolean edgeIK = graph.containsEdge(sweep[i], sweep[k]); - if (!edgeIJ && edgeIK) { - return false; + private static boolean isIOrdering(HashMap sweep, Graph graph) { + HashMap last = new HashMap<>(); + HashMap inverseSweep = new HashMap<>(); + + for(V vertex : graph.vertexSet()) { + int index = sweep.get(vertex); + inverseSweep.put(index, vertex); + } + + for(int i = 0; i < graph.vertexSet().size(); i++) { + V vertex = inverseSweep.get(i); + + for(V neighbor : Graphs.neighborListOf(graph, vertex)) { + if(last.get(neighbor) != null && last.get(neighbor) != i - 1) { + return false; + } else { + last.replace(neighbor, i); + } } - } } - } - return true; + + return true; } /** - * return the last element of the given list + * return the last element of the given map * - * @param list + * @param map * @param the generic type representing vertices * @return */ - private static V lastElementOf(List list) { - if (list == null) { - throw new IllegalArgumentException("List parameter cannot be null."); - } - - return list.get(list.size() - 1); + private static V lastElementOf(HashMap map) { + return Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey(); } /** @@ -121,22 +150,4 @@ private static V randomElementOf(Set set) { } return iterator.next(); } - - /** - * convert the given list into array in weak typing way - * - * @param list - * @param the generic type representing vertices - * @return - */ - private static V[] arrayOf(List list) { - if (list == null) { - throw new IllegalArgumentException("List parameter cannot be null."); - } - - V[] resultArray = (V[]) new Object[list.size()]; - list.toArray(resultArray); - return resultArray; - } - -} \ No newline at end of file +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java index e0d81527b4e..22a032ad0cd 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java @@ -15,13 +15,13 @@ public class LexBreadthFirstSearch * @param startingVertex the starting vertex of the LBFS * @return an array of vertices representing the order in which the vertices were found */ - public static List lexBreadthFirstSearch(Graph graph, V startingVertex) + public static HashMap lexBreadthFirstSearch(Graph graph, V startingVertex) { - ArrayList result = new ArrayList<>(graph.vertexSet().size()); - LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph); + HashMap result = new HashMap<>(graph.vertexSet().size()); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, startingVertex); for(int i = 0; i < graph.vertexSet().size(); i++) { - result.add(lbfIterator.next()); + result.put(lbfIterator.next(), i); } return result; @@ -36,15 +36,77 @@ public static List lexBreadthFirstSearch(Graph graph, V starting * @return an array of vertices representing the order in which the vertices were found */ - public static List lexBreadthFirstSearchPlus(Graph graph, V startingVertex, V[] priority) + public static HashMap lexBreadthFirstSearchPlus(Graph graph, V startingVertex, HashMap priority) { - ArrayList result = new ArrayList<>(graph.vertexSet().size()); - LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority); + HashMap result = new HashMap<>(graph.vertexSet().size()); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority, startingVertex); for(int i = 0; i < graph.vertexSet().size(); i++) { - result.add(lbfIterator.next()); + result.put(lbfIterator.next(), i); } return result; } + + /** + * Performs LBFS* starting at {@code startingVertex} using two previous orderings {@code prevOrdering1} and {@code prevOrdering2}. + * + * @param graph the graph we want to perform LBFS on + * @param startingVertex the starting vertex of the LBFS + * @param priority1 the first priority of vertices for tiebreaking + * @param priority2 the second priority of vertices for tiebreaking + * @return an array of vertices representing the order in which the vertices were found + */ + + public static HashMap lexBreadthFirstSearchStar(Graph graph, V startingVertex, HashMap priorityA, HashMap priorityB) + { + HashMap neighborIndexA = new HashMap<>(); + HashMap neighborIndexB = new HashMap<>(); + + HashMap> ASets = new HashMap<>(); + HashMap> BSets = new HashMap<>(); + + for(V vertex : graph.vertexSet()) { + // Compute indexA, indexB + int maxNeighborA = 0; + int maxNeighborB = 0; + + List neighbors = Graphs.neighborListOf(graph, vertex); + neighbors.add(vertex); + + for(V neighbor : neighbors) { + maxNeighborA = Math.max(maxNeighborA, priorityA.get(neighbor)); + maxNeighborB = Math.max(maxNeighborB, priorityB.get(neighbor)); + } + + neighborIndexA.put(vertex, maxNeighborA); + neighborIndexB.put(vertex, maxNeighborB); + } + + for(V vertex : graph.vertexSet()) { + HashSet Av = new HashSet<>(); + HashSet Bv = new HashSet<>(); + + for(V neighbor : Graphs.neighborListOf(graph, vertex)) { + if(priorityA.get(neighbor) < priorityA.get(vertex) && neighborIndexA.get(neighbor) > priorityA.get(vertex)) { + Av.add(neighbor); + } + + if(priorityB.get(neighbor) < priorityB.get(vertex) && neighborIndexB.get(neighbor) > priorityB.get(vertex)) { + Bv.add(neighbor); + } + } + + ASets.put(vertex, Av); + BSets.put(vertex, Bv); + } + + HashMap result = new HashMap<>(graph.vertexSet().size()); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets, startingVertex); + + for(int i = 0; i < graph.vertexSet().size(); i++) { + result.put(lbfIterator.next(), i); + } + return result; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java index 977094f28b7..35db6acece5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java +++ b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java @@ -75,16 +75,43 @@ public LexBreadthFirstIterator(Graph graph) { bucketList = new BucketList(graph.vertexSet()); } + /** + * Creates new lexicographical breadth-first iterator for {@code graph}. + * + * @param graph the graph to be iterated. + * @param startingVertex the initial vertex. + */ + public LexBreadthFirstIterator(Graph graph, V startingVertex) { + super(graph); + GraphTests.requireUndirected(graph); + bucketList = new BucketList(graph.vertexSet(), startingVertex); + } + + + /** + * Creates new lexicographical breadth-first iterator with a static priority list for {@code graph}. + * + * @param graph the graph to be iterated. + * @param priority the vertex array sorted by their priorities. + * @param startingVertex the initial vertex. + */ + public LexBreadthFirstIterator(Graph graph, HashMap priority, V startingVertex) { + super(graph); + GraphTests.requireUndirected(graph); + bucketList = new BucketList(graph.vertexSet(), new PriorityComparator(priority), startingVertex); + } + /** * Creates new lexicographical breadth-first iterator with a static priority list for {@code graph}. * * @param graph the graph to be iterated. * @param priority the vertex array sorted by their priorities. + * @param startingVertex the initial vertex. */ - public LexBreadthFirstIterator(Graph graph, V[] priority) { + public LexBreadthFirstIterator(Graph graph, HashMap priorityA, HashMap priorityB, HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets, V startingVertex) { super(graph); GraphTests.requireUndirected(graph); - bucketList = new BucketList(graph.vertexSet(), new PriorityComparator(priority)); + bucketList = new BucketList(graph.vertexSet(), priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets, startingVertex); } /** @@ -200,6 +227,18 @@ class BucketList { */ private Comparator priorityComparator = null; + /** + * LBFS* static parameters + */ + private HashMap neighborIndexA = null; + private HashMap neighborIndexB = null; + + private HashMap> ASets = null; + private HashMap> BSets = null; + + private HashMap priorityA = null; + private HashMap priorityB = null; + /** * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. * @@ -213,18 +252,72 @@ class BucketList { } } + /** + * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. + * + * @param vertices the vertices of the graph, that should be stored in the {@code head} bucket. + * @param startingVertex the initial vertex. + */ + BucketList(Collection vertices, V startingVertex) { + bucketMap = new HashMap<>(vertices.size()); + + // Split off starting vertex into its own bucket + vertices.remove(startingVertex); + head = new Bucket(startingVertex, priorityComparator); + head.insertBefore(new Bucket(vertices, priorityComparator)); + + bucketMap.put(startingVertex, head); + for (V vertex : vertices) { + bucketMap.put(vertex, head.next); + } + } + /** * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. * * @param vertices the vertices of the graph, that should be stored in the {@code head} bucket. * @param priorityComparator a comparator which defines a priority for tiebreaking. + * @param startingVertex the initial vertex. */ - BucketList(Collection vertices, Comparator priorityComparator) { - this.priorityComparator = priorityComparator; - head = new Bucket(vertices, priorityComparator); + BucketList(Collection vertices, Comparator priorityComparator, V startingVertex) { bucketMap = new HashMap<>(vertices.size()); + + // Split off starting vertex into its own bucket + vertices.remove(startingVertex); + head = new Bucket(startingVertex, priorityComparator); + head.insertBefore(new Bucket(vertices, priorityComparator)); + + bucketMap.put(startingVertex, head); for (V vertex : vertices) { - bucketMap.put(vertex, head); + bucketMap.put(vertex, head.next); + } + } + + /** + * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. + * + * @param vertices the vertices of the graph, that should be stored in the {@code head} bucket. + * @param priorityComparator a comparator which defines a priority for tiebreaking. + * @param startingVertex the initial vertex. + */ + BucketList(Collection vertices, HashMap priorityA, HashMap priorityB, HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets, V startingVertex) { + this.neighborIndexA = neighborIndexA; + this.neighborIndexB = neighborIndexB; + this.ASets = ASets; + this.BSets = BSets; + this.priorityA = priorityA; + this.priorityB = priorityB; + + bucketMap = new HashMap<>(vertices.size()); + + // Split off starting vertex into its own bucket + vertices.remove(startingVertex); + head = new Bucket(startingVertex, new PriorityComparator(priorityA), new PriorityComparator(priorityB)); + head.insertBefore(new Bucket(vertices, new PriorityComparator(priorityA), new PriorityComparator(priorityB))); + + bucketMap.put(startingVertex, head); + for (V vertex : vertices) { + bucketMap.put(vertex, head.next); } } @@ -251,7 +344,14 @@ boolean containsBucketWith(V vertex) { */ V poll() { if (bucketMap.size() > 0) { - V res = head.poll(); + V res = null; + + if(neighborIndexA == null) { + res = head.poll(); + } else { + res = head.poll(neighborIndexA, neighborIndexB, ASets, BSets, priorityA, priorityB); + } + bucketMap.remove(res); if (head.isEmpty()) { head = head.next; @@ -318,6 +418,10 @@ private class Bucket { * Set of vertices currently stored in this bucket. */ private Queue vertices; + /** + * Set of vertices currently stored in this bucket (sorted by other order). + */ + private Queue verticesB = null; /** * Creates a new bucket with all {@code vertices} stored in it. @@ -346,6 +450,36 @@ private class Bucket { } vertices.add(vertex); } + + /** + * LBFS*-variants + */ + + /** + * Creates a new bucket with all {@code vertices} stored in it. + * + * @param vertices vertices to store in this bucket. + */ + Bucket(Collection vertices, Comparator compA, Comparator compB) { + this.vertices = new PriorityQueue<>(compA); + this.verticesB = new PriorityQueue<>(compB); + + this.vertices.addAll(vertices); + this.verticesB.addAll(vertices); + } + + /** + * Creates a new Bucket with a single {@code vertex} in it. + * + * @param vertex the vertex to store in this bucket. + */ + Bucket(V vertex, Comparator compA, Comparator compB) { + this.vertices = new PriorityQueue<>(compA); + this.verticesB = new PriorityQueue<>(compB); + + vertices.add(vertex); + verticesB.add(vertex); + } /** * Removes the {@code vertex} from this bucket. @@ -354,6 +488,10 @@ private class Bucket { */ void removeVertex(V vertex) { vertices.remove(vertex); + + if(verticesB != null) { + verticesB.remove(vertex); + } } /** @@ -393,6 +531,10 @@ void insertBefore(Bucket bucket) { */ void addVertex(V vertex) { vertices.add(vertex); + + if(verticesB != null) { + verticesB.add(vertex); + } } /** @@ -408,6 +550,32 @@ V poll() { return vertex; } } + + /** + * Retrieves one vertex from this bucket (according to LBFS*). + * + * @return vertex, that was removed from this bucket, null if the bucket was empty. + */ + V poll(HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets, HashMap priorityA, HashMap priorityB) { + if (vertices.isEmpty()) { + return null; + } else { + V alpha = vertices.peek(); + V beta = verticesB.peek(); + + if(neighborIndexA.get(alpha) > priorityA.get(alpha)) { + return verticesB.poll(); // return Beta + } else if(neighborIndexB.get(beta) > priorityB.get(beta)) { + return vertices.poll(); // return Alpha + } else if(BSets.get(beta).isEmpty() || !ASets.get(alpha).isEmpty()) { + return verticesB.poll(); // return Beta + } else if(neighborIndexA.get(BSets.get(beta).iterator().next()) == priorityA.get(alpha)) { + return verticesB.poll(); // return Beta + } else { + return vertices.poll(); // return Alpha + } + } + } /** * Checks whether this bucket is empty. @@ -422,31 +590,19 @@ boolean isEmpty() { class PriorityComparator implements Comparator { - private final V[] priority; + private final HashMap priority; - public PriorityComparator(V[] priority) throws IllegalArgumentException { + public PriorityComparator(HashMap priority) throws IllegalArgumentException { if(priority == null) { - throw new IllegalArgumentException("Priority array must not be null"); + throw new IllegalArgumentException("Priority map must not be null"); } this.priority = priority; } - private int indexOf(V vertex) throws NoSuchElementException { - for(int index = 0; index < priority.length; index++) { - if(priority[index].equals(vertex)) { - return index; - } - } - throw new NoSuchElementException("Priority is on a different vertex set."); - } - @Override public int compare(V vertex1, V vertex2) { - int index1 = indexOf(vertex1); - int index2 = indexOf(vertex2); - - return (index1 - index2); + return (priority.get(vertex1) - priority.get(vertex2)); } } } From 8dd0dffd4a7d6f2d60e50d955bb1170cc6f3bb0f Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Tue, 24 Apr 2018 12:25:22 +0200 Subject: [PATCH 041/131] Fix bugs in the interval graph detection and add some tests --- .../IntervalGraphRecognizer.java | 27 +++-- .../traverse/LexBreadthFirstIterator.java | 31 +++++- .../interval/IntervalGraphRecognizerTest.java | 99 +++++++++++++++++++ 3 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 43f59716c63..941d70ccd6d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -19,6 +19,12 @@ public final class IntervalGraphRecognizer { * @return */ public static boolean isIntervalGraph(Graph graph) { + + // An empty graph is an interval graph. + if (graph.vertexSet().isEmpty()) { + return true; + } + // Step 1 - LBFS from an arbitrary vertex // Input - random vertex r // Output - the result of current sweep alpha, further last vertex a visited by current sweep @@ -104,19 +110,20 @@ private static boolean isIOrdering(HashMap sweep, Graph int index = sweep.get(vertex); inverseSweep.put(index, vertex); } - - for(int i = 0; i < graph.vertexSet().size(); i++) { - V vertex = inverseSweep.get(i); - - for(V neighbor : Graphs.neighborListOf(graph, vertex)) { - if(last.get(neighbor) != null && last.get(neighbor) != i - 1) { - return false; - } else { - last.replace(neighbor, i); + + for (int i=0; i graph) { public LexBreadthFirstIterator(Graph graph, V startingVertex) { super(graph); GraphTests.requireUndirected(graph); - bucketList = new BucketList(graph.vertexSet(), startingVertex); + + Set copyOfSet = new HashSet<>(); + + copyOfSet.addAll(graph.vertexSet()); + bucketList = new BucketList(copyOfSet, startingVertex); } @@ -98,7 +102,11 @@ public LexBreadthFirstIterator(Graph graph, V startingVertex) { public LexBreadthFirstIterator(Graph graph, HashMap priority, V startingVertex) { super(graph); GraphTests.requireUndirected(graph); - bucketList = new BucketList(graph.vertexSet(), new PriorityComparator(priority), startingVertex); + + Set copyOfSet = new HashSet<>(); + + copyOfSet.addAll(graph.vertexSet()); + bucketList = new BucketList(copyOfSet, new PriorityComparator(priority), startingVertex); } /** @@ -111,7 +119,11 @@ public LexBreadthFirstIterator(Graph graph, HashMap priority, public LexBreadthFirstIterator(Graph graph, HashMap priorityA, HashMap priorityB, HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets, V startingVertex) { super(graph); GraphTests.requireUndirected(graph); - bucketList = new BucketList(graph.vertexSet(), priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets, startingVertex); + + Set copyOfSet = new HashSet<>(); + + copyOfSet.addAll(graph.vertexSet()); + bucketList = new BucketList(copyOfSet, priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets, startingVertex); } /** @@ -383,7 +395,13 @@ void updateBuckets(Set vertices) { bucketMap.put(vertex, bucket.prev); } else { visitedBuckets.add(bucket); - Bucket newBucket = new Bucket(vertex, priorityComparator); + Bucket newBucket; + if (priorityB != null) { + newBucket = new Bucket(vertex, new PriorityComparator(priorityA), new PriorityComparator(priorityB)); + } + else{ + newBucket = new Bucket(vertex, priorityComparator); + } newBucket.insertBefore(bucket); bucketMap.put(vertex, newBucket); if (head == bucket) { @@ -564,14 +582,19 @@ V poll(HashMap neighborIndexA, HashMap neighborIndexB, H V beta = verticesB.peek(); if(neighborIndexA.get(alpha) > priorityA.get(alpha)) { + vertices.remove(beta); return verticesB.poll(); // return Beta } else if(neighborIndexB.get(beta) > priorityB.get(beta)) { + verticesB.remove(beta); return vertices.poll(); // return Alpha } else if(BSets.get(beta).isEmpty() || !ASets.get(alpha).isEmpty()) { + vertices.remove(beta); return verticesB.poll(); // return Beta } else if(neighborIndexA.get(BSets.get(beta).iterator().next()) == priorityA.get(alpha)) { + vertices.remove(beta); return verticesB.poll(); // return Beta } else { + verticesB.remove(beta); return vertices.poll(); // return Alpha } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java new file mode 100644 index 00000000000..0a0c1b8e9dc --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -0,0 +1,99 @@ +package org.jgrapht.intervalgraph.interval; + +import org.jgrapht.Graph; +import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.SimpleGraph; + +import org.jgrapht.graph.builder.GraphBuilder; +import org.jgrapht.intervalgraph.IntervalGraph; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class IntervalGraphRecognizerTest { + + @Test + public void testEmptyGraph() { + Graph g = new SimpleGraph<>(DefaultEdge.class); + + assertTrue(IntervalGraphRecognizer.isIntervalGraph(g)); + } + + @Test + public void testForbiddenSubgraphBiclawWithAT() { + GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + builder.addEdge(0, 1); + builder.addEdge(0, 2); + builder.addEdge(0, 3); + + builder.addEdge(1, 4); + builder.addEdge(2, 5); + builder.addEdge(3, 6); + + assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + } + + @Test + public void testForbiddenSubgraphLekkerkerkerBoland() { + + + GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + builder.addEdge(0, 1); + builder.addEdge(0, 2); + builder.addEdge(0, 3); + builder.addEdge(0, 4); + builder.addEdge(0, 5); + + builder.addEdge(1, 2); + builder.addEdge(2, 3); + builder.addEdge(3, 4); + builder.addEdge(4, 5); + + builder.addEdge(3, 6); + + assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + } + + public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { + GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + builder.addEdge(0, 1); + + for(int i = 3; i < n; i++) { + builder.addEdge(1, i); + builder.addEdge(i - 1, i); + } + + builder.addEdge(n - 1, n); + + assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + } + + @Test + public void testForbiddenSubgraphLekkerkerkerBolandFamily() { + for(int n = 7; n < 20; n++) { + testForbiddenSubgraphLekkerkerkerBolandFamily(n); + } + } + + public boolean isCnAnIntervalGraph(int n) { + GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + for(int i = 0; i < n; i++) { + builder.addEdge(i, (i + 1) % n); + } + + return IntervalGraphRecognizer.isIntervalGraph(builder.build()); + } + + @Test + public void testForbiddenSubgraphCn() { + for(int n = 2; n < 20; n++) { + assertEquals("Testing C_" + n, n < 4, isCnAnIntervalGraph(n)); + } + } +} From 0a96f910ceb1fc227e67a32828fe99444857a509 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Apr 2018 19:49:26 +0200 Subject: [PATCH 042/131] adpated Test to new Implementations --- .../RedBlackIntervalTreeStructureTest.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index 331e925e8cc..aa01cb0ae54 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -1,6 +1,7 @@ package org.jgrapht.intervalgraph; import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.jgrapht.intervalgraph.interval.Interval; import org.junit.Before; import org.junit.Test; @@ -12,28 +13,28 @@ public class RedBlackIntervalTreeStructureTest { List list = new LinkedList<>(); List sorted = new LinkedList<>(); - RedBlackIntervalTree tree = new RedBlackIntervalTree<>(); + RedBlackIntervalTree, Integer>> tree = new RedBlackIntervalTree<>(); @Before public void setUp() throws Exception { for (int i = 0; i < 20; i++) { IntegerInterval interval = new IntegerInterval(i, i+3); - tree.insert(i, interval); + tree.insert(i, new IntervalTreeNodeValue<>(interval,0)); sorted.add(interval); } } @Test public void testInorder() { - List result = tree.inorderValues(); + List, Integer>> result = tree.inorderValues(); for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { - IntegerInterval i = result.get(i1); + Interval i = result.get(i1).getInterval(); assertEquals("fault at " + i1,i, sorted.get(i1)); } tree.delete(5); assertFalse(tree.contains(5)); - assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getHi()); + assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); } } \ No newline at end of file From 30624112cb6d57bb879dc937c5e80b6a8e450d72 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Apr 2018 19:50:16 +0200 Subject: [PATCH 043/131] added implementation of IntervalVertexInterface and modified interface for it --- .../graph/specifics/IntervalSpecifics.java | 4 +- .../jgrapht/intervalgraph/IntervalGraph.java | 8 +-- .../IntervalGraphVertexContainer.java | 4 +- ...IntervalGraphVertexContainerInterface.java | 5 +- .../intervalgraph/IntervalTreeInterface.java | 2 - .../interval/IntervalVertex.java | 50 ++++++++++++++++++- .../interval/IntervalVertexInterface.java | 9 ++++ 7 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index e04e69e2995..0474ce06c3a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -4,14 +4,14 @@ import org.jgrapht.intervalgraph.IntervalGraph; import org.jgrapht.intervalgraph.IntervalGraphVertexContainerInterface; import org.jgrapht.intervalgraph.IntervalGraphVertexContainer; -import org.jgrapht.intervalgraph.interval.IntervalVertex; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; import org.jgrapht.util.ArrayUnenforcedSet; import java.io.Serializable; import java.util.List; import java.util.Set; -public class IntervalSpecifics implements Specifics, Serializable { +public class IntervalSpecifics implements Specifics, Serializable { private static final long serialVersionUID = 1112673663745687843L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 30f6d37ca64..42dc295b153 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -5,12 +5,8 @@ import org.jgrapht.GraphType; import org.jgrapht.Graphs; import org.jgrapht.graph.*; -import org.jgrapht.graph.specifics.FastLookupDirectedSpecifics; -import org.jgrapht.graph.specifics.FastLookupUndirectedSpecifics; import org.jgrapht.graph.specifics.IntervalSpecifics; -import org.jgrapht.graph.specifics.Specifics; -import org.jgrapht.intervalgraph.interval.Interval; -import org.jgrapht.intervalgraph.interval.IntervalVertex; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; import org.jgrapht.util.TypeUtil; import java.io.Serializable; @@ -25,7 +21,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { +public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { private static final long serialVersionUID = 7835287075273098344L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 67c34c5c3e4..748ab7bd604 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -2,12 +2,12 @@ import org.jgrapht.graph.specifics.UndirectedEdgeContainer; import org.jgrapht.intervalgraph.interval.Interval; -import org.jgrapht.intervalgraph.interval.IntervalVertex; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; import java.io.Serializable; import java.util.*; -public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { +public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { private static final long serialVersionUID = 7768940080894764546L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java index 3a42c4afdaf..080cacfbb12 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java @@ -1,13 +1,12 @@ package org.jgrapht.intervalgraph; import org.jgrapht.graph.specifics.UndirectedEdgeContainer; -import org.jgrapht.intervalgraph.interval.IntervalVertex; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; -import java.io.Serializable; import java.util.List; import java.util.Set; -public interface IntervalGraphVertexContainerInterface { +public interface IntervalGraphVertexContainerInterface { /** * Returns the whole vertex set of the graph. diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index 2fa5cec4a86..b0d816fb01f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -1,7 +1,5 @@ package org.jgrapht.intervalgraph; -import jdk.javadoc.internal.doclets.formats.html.PackageIndexFrameWriter; -import org.jgrapht.alg.util.Pair; import org.jgrapht.intervalgraph.interval.Interval; import java.util.List; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java index cbcb83d692d..b893a5e898c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java @@ -1,7 +1,53 @@ package org.jgrapht.intervalgraph.interval; -public interface IntervalVertex> { +import org.jgrapht.alg.util.Pair; - Interval getInterval(); +import java.util.Objects; +public class IntervalVertex> implements IntervalVertexInterface { + private V vertex; + private Interval interval; + + public IntervalVertex(V vertex, Interval interval) { + this.vertex = vertex; + this.interval = interval; + } + + @Override + public Interval getInterval() { + return interval; + } + + @Override + public V getVertex() { + return vertex; + } + + @Override + public String toString() + { + return "(" + vertex + "," + interval + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + else if (!(o instanceof IntervalVertex)) + return false; + + @SuppressWarnings("unchecked") IntervalVertex other = (IntervalVertex) o; + return Objects.equals(vertex, other.vertex) && Objects.equals(interval, other.interval); + } + + @Override + public int hashCode() + { + return Objects.hash(vertex, interval); + } + + public static > IntervalVertex of(V vertex, Interval interval) { + return new IntervalVertex<>(vertex, interval); + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java new file mode 100644 index 00000000000..a1215828cc5 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java @@ -0,0 +1,9 @@ +package org.jgrapht.intervalgraph.interval; + +public interface IntervalVertexInterface> { + + V getVertex(); + + Interval getInterval(); + +} From 2dd1053f80532dbf658b78e196926ee8ab39a014 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Apr 2018 16:05:39 +0200 Subject: [PATCH 044/131] commented code --- .../graph/specifics/IntervalSpecifics.java | 18 +++- .../intervalgraph/BinarySearchTree.java | 2 + .../jgrapht/intervalgraph/IntervalGraph.java | 9 ++ .../intervalgraph/IntervalGraphInterface.java | 4 +- .../IntervalGraphVertexContainer.java | 32 +++++- ...IntervalGraphVertexContainerInterface.java | 15 ++- .../IntervalStructureInterface.java | 9 ++ .../intervalgraph/IntervalTreeInterface.java | 25 ++++- .../intervalgraph/IntervalTreeNodeValue.java | 35 +++--- .../intervalgraph/IntervalTreeStructure.java | 12 ++- .../java/org/jgrapht/intervalgraph/Node.java | 101 +++++++++++++++++- .../intervalgraph/RedBlackIntervalTree.java | 16 ++- .../jgrapht/intervalgraph/RedBlackTree.java | 4 +- .../interval/IntervalVertex.java | 40 ++++++- .../interval/IntervalVertexInterface.java | 22 +++- 15 files changed, 298 insertions(+), 46 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index 0474ce06c3a..01e235b2838 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -11,16 +11,26 @@ import java.util.List; import java.util.Set; +/** + * Implementation of IntervalSpecifics. + * This class implements necessary methods for IntervalGraph. + * + * @param the vertex type + * @param the edge type + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public class IntervalSpecifics implements Specifics, Serializable { private static final long serialVersionUID = 1112673663745687843L; - protected IntervalGraph intervalGraph; - protected IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; - protected EdgeSetFactory edgeSetFactory; + private IntervalGraph intervalGraph; + private IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; + private EdgeSetFactory edgeSetFactory; /** - * Construct a new interval specifics. + * Constructs new interval specifics. * * @param intervalGraph the graph for which these specifics are for */ diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java index 522c8a644d2..db0b01d6f64 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -1,5 +1,7 @@ package org.jgrapht.intervalgraph; +import java.util.NoSuchElementException; + /** * Interface for Binary Search Trees * diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 42dc295b153..d740d6676f7 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -140,6 +140,8 @@ public EdgeFactory getEdgeFactory() } /** + * This method an IllegalArgumentException in every case because you can not add edges to an interval graph manually. + * * {@inheritDoc} */ @Override @@ -149,6 +151,8 @@ public E addEdge(V sourceVertex, V targetVertex) } /** + * This method an IllegalArgumentException in every case because you can not add edges to an interval graph manually. + * * {@inheritDoc} */ @Override @@ -169,6 +173,7 @@ public boolean addVertex(V v) return false; } else { specifics.addVertex(v); + // add all edges between the new vertex and vertices with intersecting intervals addIntervalEdges(v, specifics.getOverlappingIntervalVertices(v)); return true; } @@ -314,6 +319,8 @@ public Set outgoingEdgesOf(V vertex) } /** + * This method an IllegalArgumentException in every case because you can not remove edges from an interval graph manually. + * * {@inheritDoc} */ @Override @@ -323,6 +330,8 @@ public E removeEdge(V sourceVertex, V targetVertex) } /** + * This method an IllegalArgumentException in every case because you can not remove edges from an interval graph manually. + * * {@inheritDoc} */ @Override diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java index 77ff37a7092..930a139af15 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java @@ -1,10 +1,10 @@ package org.jgrapht.intervalgraph; -import java.util.Collection; - import org.jgrapht.Graph; import org.jgrapht.intervalgraph.interval.Interval; +import java.util.Collection; + public interface IntervalGraphInterface> { Collection> intersections(T queryInterval); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 748ab7bd604..24456133438 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -7,16 +7,38 @@ import java.io.Serializable; import java.util.*; +/** + * Implementation of IntervalGraphVertexContainer + * + * @param the vertex type + * @param the edge type + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { private static final long serialVersionUID = 7768940080894764546L; - private IntervalStructureInterface intervalTree; + /** + * intervalStructure maintains all intervals in order to get intersecting intervals efficiently. + */ + private IntervalStructureInterface intervalStructure; + /** + * vertexMap maintains an EdgeContainer for every Vertex + */ private Map> vertexMap; + /** + * intervalMap maintains the assignment of every interval to vertex + */ private Map, V> intervalMap; + /** + * Constructs a vertex container for an interval graph with all necessary objects. + */ public IntervalGraphVertexContainer() { - this.intervalTree = new IntervalTreeStructure<>(); + this.intervalStructure = new IntervalTreeStructure<>(); this.vertexMap = new LinkedHashMap<>(); this.intervalMap = new LinkedHashMap<>(); } @@ -38,7 +60,7 @@ public Set getVertexSet() { */ @Override public List getOverlappingIntervalVertices(V vertex) { - List> intervalList = intervalTree.overlapsWith(vertex.getInterval()); + List> intervalList = intervalStructure.overlapsWith(vertex.getInterval()); List vertexList = new LinkedList<>(); for(Interval interval: intervalList) { @@ -67,7 +89,7 @@ public UndirectedEdgeContainer get(V vertex) { */ @Override public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec) { - intervalTree.add(vertex.getInterval()); + intervalStructure.add(vertex.getInterval()); intervalMap.put(vertex.getInterval(), vertex); return vertexMap.put(vertex, ec); } @@ -80,7 +102,7 @@ public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer */ @Override public UndirectedEdgeContainer remove(V vertex) { - intervalTree.remove(vertex.getInterval()); + intervalStructure.remove(vertex.getInterval()); intervalMap.remove(vertex.getInterval()); return vertexMap.remove(vertex); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java index 080cacfbb12..6b339a33231 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java @@ -6,6 +6,15 @@ import java.util.List; import java.util.Set; +/** + * Interface of IntervalGraphVertexContainer + * + * @param the vertex type + * @param the edge type + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public interface IntervalGraphVertexContainerInterface { /** @@ -20,7 +29,7 @@ public interface IntervalGraphVertexContainerInterface getOverlappingIntervalVertices(V v); + List getOverlappingIntervalVertices(V v); /** * Returns the edge container to the vertex @@ -36,7 +45,7 @@ public interface IntervalGraphVertexContainerInterface put(V vertex, UndirectedEdgeContainer ec); + UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec); /** * Removes a vertex from the data structure if it is present. @@ -44,5 +53,5 @@ public interface IntervalGraphVertexContainerInterface remove(V vertex); + UndirectedEdgeContainer remove(V vertex); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java index 40befd7ff1c..63b065b292f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java @@ -4,6 +4,15 @@ import java.util.List; +/** + * Interface of IntervalStructure + * This interface is used for an implementation of an efficient data structure to maintain intervals. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public interface IntervalStructureInterface> { /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index b0d816fb01f..4c775653526 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -4,10 +4,33 @@ import java.util.List; +/** + * Interface of IntervalTree + * This is the interface to an interval tree. It maintains intervals in order to find intersecting intervals and + * included points in O(log n + k), where n is the number of intervals and k the output size, + * i.e. the number of output intervals. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public interface IntervalTreeInterface, NodeValue extends IntervalTreeNodeValue, T>> extends BinarySearchTree { + /** + * Returns all intervals of all vertices that intersect with the given interval + * + * @param interval the interval + * @return all intersecting intervals of vertices in the graph + */ List> overlapsWith(Interval interval); - List> overlapsWithPoint(T point); + /** + * Returns all intervals of all vertices that include the given point + * + * @param point the point + * @return all including intervals of vertices in the graph + */ + List> overlapsWith(T point); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java index 539c4200e2f..388e2a2995d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -1,17 +1,31 @@ package org.jgrapht.intervalgraph; -import org.jgrapht.alg.util.Pair; import org.jgrapht.intervalgraph.interval.Interval; import java.io.Serializable; import java.util.Objects; +/** + * Implementation of IntervalTreeNodeValue + * This is a container class to store the necessary data for the (augmented) interval tree in the nodes of the tree. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public class IntervalTreeNodeValue, T extends Comparable> implements Serializable { private static final long serialVersionUID = 1111005364785643338L; + /** + * The interval + */ private Interval interval; + /** + * the greatest end point of all intervals in the subtree rooted at that node. + */ private T highValue; /** @@ -49,25 +63,6 @@ public void setHighValue(T highValue) { this.highValue = highValue; } - - public boolean hasInterval(E e) - { - if (e == null) { - return interval == null; - } else { - return e.equals(interval); - } - } - - public boolean hasHighValue(E e) - { - if (e == null) { - return highValue == null; - } else { - return e.equals(highValue); - } - } - @Override public String toString() { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index 971c165a83c..1286e68ce2f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -3,9 +3,17 @@ import org.jgrapht.intervalgraph.interval.Interval; import java.io.Serializable; -import java.util.LinkedList; import java.util.List; +/** + * Implementation of IntervalTreeStructure + * This class realises the interval tree structure, which has a interval tree as maintaining object. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public class IntervalTreeStructure> implements IntervalStructureInterface, Serializable { private static final long serialVersionUID = 2834567756342332325L; @@ -24,7 +32,7 @@ public List> overlapsWith(Interval interval) { @Override public List> overlapsWithPoint(T point) { - return tree.overlapsWithPoint(point); + return tree.overlapsWith(point); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 0d211200992..44009581c14 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -2,17 +2,50 @@ import java.io.Serializable; -// BST helper node data type +/** + * Implementation of Node + * This class implements the node for a BST. + * + * @param the key + * @param the value + * + * @author Christoph Grüne (christophgruene) + * @author Daniel Mock (danielmock) + * @since Apr 26, 2018 + */ public class Node implements Serializable { private static final long serialVersionUID = 5674337686253743843L; + /** + * the key of the node + */ private K key; + /** + * the value of the node + */ private V val; + /** + * node's corresponding left and right children + */ private Node leftChild, rightChild; + /** + * the color of the node (important for usage in red black tree)(not necessary for all implementations) + */ private boolean red; + /** + * the size of the sub tree rooted at this node (not necessary for all implementations) + */ private int size; + /** + * constructs a node object + * + * @param key the key of the node + * @param val the value of the node + * @param red the color of the node + * @param size the size of the sub tree rooted at the node + */ public Node(K key, V val, boolean red, int size) { this.key = key; this.val = val; @@ -20,58 +53,124 @@ public Node(K key, V val, boolean red, int size) { this.size = size; } + /** + * sets a new left child of the node + * + * @param leftChild the node that should be new left child + */ protected void setLeftChild(Node leftChild) { this.leftChild = leftChild; } + /** + * sets a new right child of the node + * + * @param rightChild the node that should be new right child + */ protected void setRightChild(Node rightChild) { this.rightChild = rightChild; } + /** + * sets the color for the node + * + * @param red red: true, black: false + */ protected void setRed(boolean red) { this.red = red; } + /** + * sets the color of the node to red + */ protected void setRed() { this.red = true; } + /** + * sets the color of the node to black + */ protected void setBlack() { this.red = false; } + /** + * sets a new size for the sub tree rooted at this node + * + * @param size the size of the sub tree rooted at this node + */ protected void setSize(int size) { this.size = size; } + /** + * returns whether node is red or black + * + * @return red:true, black:false + */ protected boolean isRed() { return red; } + /** + * Getter for key + * + * @return the key + */ protected K getKey() { return key; } + /** + * Getter for val + * + * @return the value of the node + */ protected V getVal() { return val; } + /** + * Setter for val + * + * @param val the new value of the node + */ public void setVal(V val) { this.val = val; } + /** + * Getter for leftChild + * + * @return the left child of the node + */ protected Node getLeftChild() { return leftChild; } + /** + * Getter for rightChild + * + * @return the right child of the node + */ protected Node getRightChild() { return rightChild; } + /** + * Getter for size + * + * @return the size of the sub tree rooted at the node, if maintained + */ protected int getSize() { return size; } + /** + * sets a new key element for this node + * + * @param key the new key of the node + */ public void setKey(K key) { this.key = key; } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index a5704ff8616..7138e4ce23f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -5,8 +5,18 @@ import java.util.LinkedList; import java.util.List; -// Essentially, this class updates the hi value after any operation on this tree. -// The hi value equals to the highest endpoint in the subtree +/** + * Implementation of RedBlackIntervalTree + * This class implements the augmented interval tree. Essentially, this class updates the highValue + * after any operation on this tree. The highValue equals to the highest endpoint in the subtree + * + * @param the type of the interval + * @param the type of the node value + * + * @author Daniel Mock (danielmock) + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface { @Override @@ -19,7 +29,7 @@ public List> overlapsWith(Interval interval) { } @Override - public List> overlapsWithPoint(T point) { + public List> overlapsWith(T point) { List> result = new LinkedList<>(); overlapsWithPoint(this.getRoot(), point, result); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index a63075b6bd2..429ec51fa0f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -1,7 +1,9 @@ package org.jgrapht.intervalgraph; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; /** * Implementation of a Red-Black-Tree diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java index b893a5e898c..b7ee1c82e6a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java @@ -1,23 +1,47 @@ package org.jgrapht.intervalgraph.interval; -import org.jgrapht.alg.util.Pair; - import java.util.Objects; +/** + * Implementation for IntervalVertex + * This class implements the container class for vertices in an interval graph. + * + * @param the vertex + * @param the interval element + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public class IntervalVertex> implements IntervalVertexInterface { private V vertex; private Interval interval; - public IntervalVertex(V vertex, Interval interval) { + /** + * Constructor for an IntervalVertex (container class for vertices in interval graphs) + * + * @param vertex the vertex + * @param interval the interval + */ + private IntervalVertex(V vertex, Interval interval) { this.vertex = vertex; this.interval = interval; } + /** + * Getter for interval + * + * @return the interval + */ @Override public Interval getInterval() { return interval; } + /** + * Getter for vertex + * + * @return the vertex + */ @Override public V getVertex() { return vertex; @@ -47,6 +71,16 @@ public int hashCode() return Objects.hash(vertex, interval); } + /** + * Creates new IntervalVertex of elements pulling of the necessity to provide corresponding types of the + * elements supplied. + * + * @param the vertex type + * @param the interval element type + * @param vertex the vertex + * @param interval the interval + * @return new pair + */ public static > IntervalVertex of(V vertex, Interval interval) { return new IntervalVertex<>(vertex, interval); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java index a1215828cc5..2abcb0d79b5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java @@ -1,9 +1,29 @@ package org.jgrapht.intervalgraph.interval; +/** + * Interface for IntervalVertex + * This interface provides necessary getters for the container of vertices in an interval graph + * as every vertex needs to have an interval. + * + * @param the vertex + * @param the interval element + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ public interface IntervalVertexInterface> { + /** + * Getter for vertex + * + * @return the vertex + */ V getVertex(); + /** + * Getter for interval + * + * @return the interval + */ Interval getInterval(); - } From 943cd47da2255411fc251551d4d87a2e79cd167a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Apr 2018 16:08:45 +0200 Subject: [PATCH 045/131] add implementation of Serializable interface --- .../org/jgrapht/intervalgraph/IntervalTreeStructure.java | 1 + .../java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java | 5 ++++- .../org/jgrapht/intervalgraph/interval/IntervalVertex.java | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index 1286e68ce2f..120b8fc30d5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -15,6 +15,7 @@ * @since Apr 26, 2018 */ public class IntervalTreeStructure> implements IntervalStructureInterface, Serializable { + private static final long serialVersionUID = 2834567756342332325L; private IntervalTreeInterface, T>> tree = new RedBlackIntervalTree<>(); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index 7138e4ce23f..2afe6c223bc 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -2,6 +2,7 @@ import org.jgrapht.intervalgraph.interval.Interval; +import java.io.Serializable; import java.util.LinkedList; import java.util.List; @@ -17,7 +18,9 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface { +public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface, Serializable { + + private static final long serialVersionUID = 4353687394654923429L; @Override public List> overlapsWith(Interval interval) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java index b7ee1c82e6a..f150244194c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java @@ -1,5 +1,6 @@ package org.jgrapht.intervalgraph.interval; +import java.io.Serializable; import java.util.Objects; /** @@ -12,10 +13,12 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class IntervalVertex> implements IntervalVertexInterface { +public class IntervalVertex> implements IntervalVertexInterface, Serializable { private V vertex; private Interval interval; + private static final long serialVersionUID = 7632653463458053425L; + /** * Constructor for an IntervalVertex (container class for vertices in interval graphs) * From f16d3787880397bcd4fb755b12025915b956de28 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Apr 2018 16:37:20 +0200 Subject: [PATCH 046/131] added interval graph constructor with initial vertices --- .../jgrapht/intervalgraph/IntervalGraph.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index d740d6676f7..da84324542e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -69,6 +69,41 @@ protected IntervalGraph( createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); } + /** + * Construct a new graph with given vertices. The graph can either be directed or undirected, depending on the + * specified edge factory. + * + * @param vertices initial vertices + * @param ef the edge factory of the new graph. + * @param directed if true the graph will be directed, otherwise undirected + * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. + * @param allowLoops whether to allow edges that are self-loops or not. + * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * + * @throws NullPointerException if the specified edge factory is + * null. + */ + protected IntervalGraph( + List vertices, EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, + boolean weighted) + { + Objects.requireNonNull(ef); + + this.edgeFactory = ef; + this.allowingLoops = allowLoops; + this.allowingMultipleEdges = allowMultipleEdges; + this.directed = directed; + this.specifics = + Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + this.weighted = weighted; + this.intrusiveEdgesSpecifics = Objects.requireNonNull( + createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + + for(V vertex : vertices) { + this.addVertex(vertex); + } + } + /** * {@inheritDoc} From 00e983b73343cd64cd284fb6171b1dfabb1e4b6c Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Sat, 28 Apr 2018 12:02:36 +0200 Subject: [PATCH 047/131] added the last forbidden interval graph test added complete graph test --- .../alg/interval/IntervalGraphTester.java | 104 ------------------ .../interval/IntervalGraphRecognizerTest.java | 72 +++++++++++- 2 files changed, 66 insertions(+), 110 deletions(-) delete mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java b/jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java deleted file mode 100644 index ace4dcc5715..00000000000 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/interval/IntervalGraphTester.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * (C) Copyright 2017-2018, by TODO and Contributors. - * - * JGraphT : a free Java graph-theory library - * - * This program and the accompanying materials are dual-licensed under - * either - * - * (a) the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation, or (at your option) any - * later version. - * - * or (per the licensee's choosing) - * - * (b) the terms of the Eclipse Public License v1.0 as published by - * the Eclipse Foundation. - */ -package org.jgrapht.alg.interval; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.alg.cycle.*; -import org.jgrapht.alg.util.*; -import org.jgrapht.generate.*; -import org.jgrapht.graph.*; -import org.junit.*; - -/** - * Test that correct interval graphs are detected and presentation is correct as well - * - * @author Ira Justus Fesefeldt - */ -public class IntervalGraphTester -{ - - @Test - public void completeGraphTest() - { - for(int i=0; i<10; i++) { - CompleteGraphGenerator cgg = - new CompleteGraphGenerator(i); - Graph cg = - new SimpleGraph<>(DefaultEdge.class); - cgg.generateGraph(cg, new IntegerVertexFactory(), null); - - //Every complete Graph is an interval graph - assertTrue(GraphTests.isIntervalGraph(cgg)); - } - - } - - @Test - public void circleGraphTest() - { - for(int i=4; i<10; i++) { - Graph graph = new SimpleGraph<>(DefaultEdge.class); - Graphs.addEdgeWithVertices(graph, 0, 1); - Graphs.addEdgeWithVertices(graph, 1, 2); - Graphs.addEdgeWithVertices(graph, 2, 3); - Graphs.addEdgeWithVertices(graph, 3, 4); - Graphs.addEdgeWithVertices(graph, 4, 5); - Graphs.addEdgeWithVertices(graph, 5, 0); - - //Every circle graph bigger than 4 is not an interval graph - assertFalse(GraphTests.isIntervalGraph(graph)); - } - } - - @Test - public void complexGraphTest() { - /* - * 0: [0,2], 1: [1,4], 2: [3,8], 3: [3,6], 4: [3,8], 5: [5,8], 6: [9,10] - * An arbitrary example for an interval graph - * - */ - - Graph graph = new SimpleGraph<>(DefaultEdge.class); - Graphs.addEdgeWithVertices(graph, 0, 1); - Graphs.addEdgeWithVertices(graph, 1, 2); - Graphs.addEdgeWithVertices(graph, 1, 3); - Graphs.addEdgeWithVertices(graph, 1, 4); - Graphs.addEdgeWithVertices(graph, 2, 3); - Graphs.addEdgeWithVertices(graph, 2, 4); - Graphs.addEdgeWithVertices(graph, 2, 5); - Graphs.addEdgeWithVertices(graph, 3, 4); - Graphs.addEdgeWithVertices(graph, 3, 5); - Graphs.addEdgeWithVertices(graph, 4, 5); - graph.addVertex(6); - - - assertTrue(GraphTests.isIntervalGraph(graph)); - - //Adding (5,6) and (6,0) creates an circle - graph.addEdge(5, 6); - graph.addEdge(6, 0); - assertFalse(GraphTests.isIntervalGraph(graph)); - } - -} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 0a0c1b8e9dc..5f9d0f68ac1 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -1,7 +1,9 @@ package org.jgrapht.intervalgraph.interval; -import org.jgrapht.Graph; +import org.jgrapht.*; import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; +import org.jgrapht.alg.util.*; +import org.jgrapht.generate.*; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.SimpleGraph; @@ -12,6 +14,9 @@ import static org.junit.Assert.*; +import java.lang.reflect.*; +import java.util.*; + public class IntervalGraphRecognizerTest { @Test @@ -23,7 +28,8 @@ public void testEmptyGraph() { @Test public void testForbiddenSubgraphBiclawWithAT() { - GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + GraphBuilder> builder + = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); builder.addEdge(0, 1); builder.addEdge(0, 2); @@ -40,7 +46,8 @@ public void testForbiddenSubgraphBiclawWithAT() { public void testForbiddenSubgraphLekkerkerkerBoland() { - GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + GraphBuilder> builder + = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); builder.addEdge(0, 1); builder.addEdge(0, 2); @@ -59,7 +66,8 @@ public void testForbiddenSubgraphLekkerkerkerBoland() { } public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { - GraphBuilder> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + GraphBuilder> builder + = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); builder.addEdge(0, 1); @@ -79,9 +87,41 @@ public void testForbiddenSubgraphLekkerkerkerBolandFamily() { testForbiddenSubgraphLekkerkerkerBolandFamily(n); } } + + + public void isForbiddenSubgraphLekkerkerkerBolandFamily2(int n) { + GraphBuilder> builder + = new SimpleGraph<>((sourveVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + //asteroidal triple: 1,3,5 + builder.addEdge(0, 1); + builder.addEdge(1, 2); + builder.addEdge(2, 3); + builder.addEdge(3, 4); + builder.addEdge(4, 5); + builder.addEdge(5, n); + + for (int i=5; i> builder = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + GraphBuilder> builder + = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); for(int i = 0; i < n; i++) { builder.addEdge(i, (i + 1) % n); @@ -96,4 +136,24 @@ public void testForbiddenSubgraphCn() { assertEquals("Testing C_" + n, n < 4, isCnAnIntervalGraph(n)); } } -} + + public void isCompleteAnIntervalGraph(int n) { + CompleteGraphGenerator cgg = + new CompleteGraphGenerator(n); + Graph cg = + new SimpleGraph<>(DefaultEdge.class); + cgg.generateGraph(cg, new IntegerVertexFactory(), null); + + //Every complete Graph is an interval graph + assertTrue(IntervalGraphRecognizer.isIntervalGraph(cg)); + } + + @Test + public void completeGraphTest() + { + for(int i=0; i<20; i++) { + isCompleteAnIntervalGraph(i); + } + + } +} \ No newline at end of file From cba492887498dd6e61bcde3f8a16715586cb1143 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Sat, 28 Apr 2018 12:07:17 +0200 Subject: [PATCH 048/131] changed the minimal size for some tests --- .../intervalgraph/interval/IntervalGraphRecognizerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 5f9d0f68ac1..1299773aa98 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -83,7 +83,7 @@ public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { @Test public void testForbiddenSubgraphLekkerkerkerBolandFamily() { - for(int n = 7; n < 20; n++) { + for(int n = 4; n < 20; n++) { testForbiddenSubgraphLekkerkerkerBolandFamily(n); } } @@ -114,7 +114,7 @@ public void isForbiddenSubgraphLekkerkerkerBolandFamily2(int n) { @Test public void testForbiddenSubgraphLekkerkerkerBolandFamily2() { - for(int n = 7; n < 20; n++) { + for(int n = 5; n < 20; n++) { testForbiddenSubgraphLekkerkerkerBolandFamily(n); } } From 2f9f22e415b6dfe51861f66a5a1b40d0c138d327 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Sat, 28 Apr 2018 21:23:35 +0200 Subject: [PATCH 049/131] added linear graph and unconnected graph to tests for algo Also added some comments, to see which graphs are tested --- .../interval/IntervalGraphRecognizerTest.java | 82 ++++++++++++++++++- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 1299773aa98..347380a85fa 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -9,16 +9,15 @@ import org.jgrapht.graph.builder.GraphBuilder; import org.jgrapht.intervalgraph.IntervalGraph; -import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; -import java.lang.reflect.*; -import java.util.*; - public class IntervalGraphRecognizerTest { + /** + * The graph with no vertex or edge is trivially an interval graph + */ @Test public void testEmptyGraph() { Graph g = new SimpleGraph<>(DefaultEdge.class); @@ -26,6 +25,12 @@ public void testEmptyGraph() { assertTrue(IntervalGraphRecognizer.isIntervalGraph(g)); } + /** + * First of five cases given by Lekkerkerker and Boland + * which at least one of them appears as an induced subgraph in every non-interval graph + * + * A biclaw with AT is a 3-star graph (or claw) with an additional neighbor for every leave + */ @Test public void testForbiddenSubgraphBiclawWithAT() { GraphBuilder> builder @@ -42,6 +47,10 @@ public void testForbiddenSubgraphBiclawWithAT() { assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); } + /** + * Second of five cases given by Lekkerkerker and Boland + * which at least one of them appears as an induced subgraph in every non-interval graph + */ @Test public void testForbiddenSubgraphLekkerkerkerBoland() { @@ -81,6 +90,10 @@ public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); } + /** + * Third of five cases given by Lekkerkerker and Boland + * which at least one of them appears as an induced subgraph in every non-interval graph + */ @Test public void testForbiddenSubgraphLekkerkerkerBolandFamily() { for(int n = 4; n < 20; n++) { @@ -112,6 +125,10 @@ public void isForbiddenSubgraphLekkerkerkerBolandFamily2(int n) { assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); } + /** + * Fourth of five cases given by Lekkerkerker and Boland + * which at least one of them appears as an induced subgraph in every non-interval graph + */ @Test public void testForbiddenSubgraphLekkerkerkerBolandFamily2() { for(int n = 5; n < 20; n++) { @@ -130,6 +147,12 @@ public boolean isCnAnIntervalGraph(int n) { return IntervalGraphRecognizer.isIntervalGraph(builder.build()); } + /** + * Fifth of five cases given by Lekkerkerker and Boland + * which at least one of them appears as an induced subgraph in every non-interval graph + * + * A circle graph of length n + */ @Test public void testForbiddenSubgraphCn() { for(int n = 2; n < 20; n++) { @@ -148,6 +171,9 @@ public void isCompleteAnIntervalGraph(int n) { assertTrue(IntervalGraphRecognizer.isIntervalGraph(cg)); } + /* + * Every complete graph is an interval graph + */ @Test public void completeGraphTest() { @@ -156,4 +182,52 @@ public void completeGraphTest() } } + + public void isUnconnectedAnIntervalGraph(int n) { + GraphBuilder> builder + = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + for(int i = 0; i < n; i++) { + builder.addVertex(i); + } + + //Every complete Graph is an interval graph + assertTrue(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + } + + /* + * Every unconnected Graph is an interval graph + */ + @Test + public void unconnectedGraphTest() + { + for(int i=0; i<20; i++) { + isUnconnectedAnIntervalGraph(i); + } + + } + + public void isLinearAnIntervalGraph(int n) { + GraphBuilder> builder + = new SimpleGraph<>((sourceVertex, targetVertex) -> new DefaultEdge()).createBuilder(DefaultEdge.class); + + for(int i = 0; i < n-1; i++) { + builder.addEdge(i, (i + 1)); + } + + //Every complete Graph is an interval graph + assertTrue(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + } + + /* + * Every linear graph is an interval graph + */ + @Test + public void linearGraphTest() + { + for(int i=0; i<20; i++) { + isLinearAnIntervalGraph(i); + } + + } } \ No newline at end of file From 27cd154012e7b733a26aed2b085a153958379efd Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Sun, 29 Apr 2018 17:34:55 +0200 Subject: [PATCH 050/131] Added a RBTree using Comparator instead of Keys --- .../intervalgraph/IntervalTreeNodeValue.java | 6 +- .../intervalgraph/IntervalTreeStructure.java | 2 +- .../org/jgrapht/intervalgraph/RBNode.java | 146 +++++ .../intervalgraph/RedBlackComparatorTree.java | 537 ++++++++++++++++++ .../RedBlackIntervalComparatorTree.java | 170 ++++++ .../intervalgraph/interval/Interval.java | 17 + .../RedBlackComparatorTreeTest.java | 36 ++ .../RedBlackIntervalComparatorTreeTest.java | 41 ++ .../RedBlackIntervalTreeStructureTest.java | 2 +- 9 files changed, 952 insertions(+), 5 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java index 388e2a2995d..7e8655f3e77 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -34,9 +34,9 @@ public class IntervalTreeNodeValue, T extends Comparable other = (IntervalTreeNodeValue) o; - return Objects.equals(interval, other.interval) && Objects.equals(highValue, other.highValue); + return interval.equals(other.interval); } @Override diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index 120b8fc30d5..5f82110b6e4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -44,7 +44,7 @@ public List> overlapsWithPoint(T point) { */ @Override public void add(Interval interval) { - tree.insert(interval.getStart(), new IntervalTreeNodeValue<>(interval, null)); + tree.insert(interval.getStart(), new IntervalTreeNodeValue<>(interval)); } /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java new file mode 100644 index 00000000000..7a629b1acd3 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java @@ -0,0 +1,146 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; + +/** + * Implementation of Node + * This class implements the node for a BST. + * + * @param the value + * @author Christoph Grüne (christophgruene) + * @author Daniel Mock (danielmock) + * @since Apr 26, 2018 + */ +public class RBNode implements Serializable { + + private static final long serialVersionUID = 5674337686253743843L; + + /** + * the value of the node + */ + private V val; + /** + * node's corresponding left and right children + */ + private RBNode leftChild, rightChild; + /** + * the color of the node (important for usage in red black tree)(not necessary for all implementations) + */ + private boolean red; + /** + * the size of the sub tree rooted at this node (not necessary for all implementations) + */ + private int size; + + /** + * constructs a node object + * + * @param val the value of the node + * @param red the color of the node + * @param size the size of the sub tree rooted at the node + */ + public RBNode(V val, boolean red, int size) { + this.val = val; + this.red = red; + this.size = size; + } + + /** + * sets a new left child of the node + * + * @param leftChild the node that should be new left child + */ + protected void setLeftChild(RBNode leftChild) { + this.leftChild = leftChild; + } + + /** + * sets a new right child of the node + * + * @param rightChild the node that should be new right child + */ + protected void setRightChild(RBNode rightChild) { + this.rightChild = rightChild; + } + + /** + * sets the color for the node + * + * @param red red: true, black: false + */ + protected void setRed(boolean red) { + this.red = red; + } + + /** + * sets the color of the node to red + */ + protected void setRed() { + this.red = true; + } + + /** + * sets the color of the node to black + */ + protected void setBlack() { + this.red = false; + } + + /** + * sets a new size for the sub tree rooted at this node + * + * @param size the size of the sub tree rooted at this node + */ + protected void setSize(int size) { + this.size = size; + } + + /** + * returns whether node is red or black + * + * @return red:true, black:false + */ + protected boolean isRed() { + return red; + } + + /** + * Getter for val + * + * @return the value of the node + */ + protected V getVal() { + return val; + } + + public void setVal(V val) { + this.val = val; + } + + /** + * Getter for leftChild + * + * @return the left child of the node + */ + protected RBNode getLeftChild() { + return leftChild; + } + + /** + * Getter for rightChild + * + * @return the right child of the node + */ + protected RBNode getRightChild() { + return rightChild; + } + + /** + * Getter for size + * + * @return the size of the sub tree rooted at the node, if maintained + */ + protected int getSize() { + return size; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java new file mode 100644 index 00000000000..21c79a38722 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -0,0 +1,537 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * Implementation of a Red-Black-Tree + * + * @param the value + * + * @author Daniel Mock (danielmock) + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ +public class RedBlackComparatorTree implements Serializable { + + private static final long serialVersionUID = 1199228564356373435L; + + protected RBNode root; + + public final Comparator comparator; + public final Comparator> nodeComparator; + + public RedBlackComparatorTree(Comparator comparator) { + this.comparator = comparator; + this.nodeComparator = (o1, o2) -> comparator.compare(o1.getVal(), o2.getVal()); + } + + public RBNode getRoot() { + return root; + } + + private boolean isRed(RBNode node){ + if (node == null) { + return false; + } + return node.isRed(); + } + + /** + * Returns whether a key is contained in the tree + * + * @return true if tree contains key, false otherwise + * @throws IllegalArgumentException if key is null + */ + + public boolean contains(V val) { + if (val == null) { + throw new IllegalArgumentException("Val is null"); + } + + return searchNode(val) != null; + } + + /** + * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * it overwrites the old value with the new. + * + * @param val the value + * @throws IllegalArgumentException if key is null + */ + + public void insert(V val) { + if (val == null) { + throw new IllegalArgumentException("Value is null"); + } + + root = insert(root, val); + root.setBlack(); + } + + protected RBNode insert(RBNode current, V val) { + if (current == null){ + return new RBNode<>(val, true, 1); + } + + if (val.equals(current.getVal())) { + current.setVal(val); + } else if (comparator.compare(val, current.getVal()) < 0) { + current.setLeftChild(insert(current.getLeftChild(), val)); + } else { + current.setRightChild(insert(current.getRightChild(), val)); + } + + // Fixup + + if (isRed(current.getRightChild()) && !isRed(current.getLeftChild())) { + current = rotateLeft(current); + } + if (isRed(current.getLeftChild()) && isRed(current.getLeftChild().getLeftChild())) { + current = rotateRight(current); + } + if (isRed(current.getLeftChild()) && isRed(current.getRightChild())) { + changeColor(current); + } + current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); + + return current; + } + + /** + * Removes the specified key and its associated value from this tree + * + * @throws IllegalArgumentException if key is null + */ + + public void delete(V val) { + if (val == null) { + throw new IllegalArgumentException("Key is null"); + } + if (!contains(val)) { + return; + } + + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = delete(root, val); + if (!isEmpty()) { + root.setBlack(); + } + } + + private boolean isEmpty() { + return root == null; + } + + protected RBNode delete(RBNode current, V val) { + if (comparator.compare(val, current.getVal()) < 0) { + if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { + current = moveRedLeft(current); + } + current.setLeftChild(delete(current.getLeftChild(), val)); + } else { + if (isRed(current.getLeftChild())) { + current = rotateRight(current); + } + if (comparator.compare(val, current.getVal()) == 0 && current.getRightChild() == null) { + return null; + } + if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { + current = moveRedRight(current); + } + if (comparator.compare(val, current.getVal()) == 0) { + RBNode node = min(current.getRightChild()); + current.setVal(node.getVal()); + current.setRightChild(deleteMin(current.getRightChild())); + } + else current.setRightChild(delete(current.getRightChild(), val)); + } + + return balance(current); + } + + protected RBNode balance(RBNode node) { + if (isRed(node.getRightChild())) { + node = rotateLeft(node); + } + if (isRed(node.getLeftChild()) && isRed(node.getLeftChild().getLeftChild())) { + node = rotateRight(node); + } + if (isRed(node.getLeftChild()) && isRed(node.getRightChild())) { + changeColor(node); + } + + node.setSize(size(node.getLeftChild()) + size(node.getRightChild() ) + 1); + return node; + } + + /** + * Removes the smallest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + + public void deleteMin() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = deleteMin(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private RBNode deleteMin(RBNode node) { + if (node.getLeftChild() == null) { + return null; + } + + if (!isRed(node.getLeftChild()) && !isRed(node.getLeftChild().getLeftChild())) { + root = moveRedLeft(node); + } + + node.setLeftChild(deleteMin(node.getLeftChild())); + return balance(node); + } + + /** + * Removes the largest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + + public void deleteMax() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + + if (!isRed(root.getRightChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = deleteMax(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private RBNode deleteMax(RBNode node) { + if (isRed(node.getLeftChild())) { + node = rotateRight(node); + } + if (node.getRightChild() == null) { + return null; + } + if (!isRed(node.getRightChild()) && !isRed(node.getRightChild().getLeftChild())) { + node = moveRedRight(node); + } + + node.setRightChild(deleteMax(node.getRightChild())); + + return balance(node); + } + + /** + * Returns the height of the BST. + * + * @return the height of the BST (a tree with 1 node has height 0) + */ + + public int height() { + return height(root); + } + + private int height(RBNode node) { + if (node == null) { + return -1; + } + + return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); + } + + /** + * Returns the smallest key in the tree. + * + * @return the smallest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + + public V min() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return min(root).getVal(); + } + + private RBNode min(RBNode node) { + if (node.getLeftChild() == null) { + return node; + } + return min(node.getLeftChild()); + } + + /** + * Returns the largest key in the tree. + * + * @return the largest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + + public V max() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return max(root.getRightChild()).getVal(); + } + + private RBNode max(RBNode node) { + if (node.getRightChild() == null) { + return node; + } + + return max(node.getRightChild()); + } + + /** + * Returns the largest key in the tree less than or equal to key. + * + * @return the largest key in the tree less than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + + public V floor(V val) { + return null; + } + + /** + * Returns the smallest key in the tree greater than or equal to key. + * + * @return the smallest key in the tree greater than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + + public V ceiling(V val) { + return null; + } + + /** + * Return the key in the tree whose rank is k. + * This is the (k+1)st smallest key in the tree. + * + * @param k the position + * @return the key in the tree of rank k + * @throws IllegalArgumentException if k not in {0, ..., n-1} + */ + + public V select(int k) { + return null; + } + + /** + * Return the number of keys in the tree strictly less than key. + * + * @param val the value + * @return the number of keys in the tree strictly less than key + * @throws IllegalArgumentException if key is null + */ + + public int rank(V val) { + return 0; + } + + /** + * Returns all keys in the symbol table as an Iterable. + * To iterate over all of the keys in the symbol table named st, + * use the foreach notation: for (Key key : st.keys()). + * + * @return all keys in the symbol table as an Iterable + */ + + public Iterable keys() { + return null; + } + + /** + * Returns all keys in the symbol table in the given range, + * as an Iterable. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return all keys in the sybol table between min + * (inclusive) and max (inclusive) as an Iterable + * @throws IllegalArgumentException if either min or max + * is null + */ + + public Iterable keys(V min, V max) { + return null; + } + + /** + * Returns the number of keys in the symbol table in the given range. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return the number of keys in the sybol table between min + * (inclusive) and max (inclusive) + * @throws IllegalArgumentException if either min or max + * is null + */ + + public int size(V min, V max) { + return 0; + } + + public int size(RBNode node) { + if (node == null) { + return 0; + } + + return getSize(node); + } + + /******************************************************************************************************************* + * HELPER METHODS * + ******************************************************************************************************************/ + + protected RBNode rotateLeft(RBNode node) { + RBNode rightChild = node.getRightChild(); + node.setRightChild(rightChild.getLeftChild()); + rightChild.setLeftChild(node); + rightChild.setRed(isRed(rightChild.getLeftChild())); + rightChild.getLeftChild().setRed(true); + rightChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); + return rightChild; + } + + private int getSize(RBNode node) { + return node != null ? node.getSize() : 0; + } + + protected RBNode rotateRight(RBNode node) { + RBNode leftChild = node.getLeftChild(); + node.setLeftChild(leftChild.getRightChild()); + leftChild.setRightChild(node); + leftChild.setRed(isRed(leftChild.getRightChild())); + leftChild.getRightChild().setRed(true); + leftChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); + return leftChild; + } + + private void changeColor(RBNode node) { + node.setRed(!isRed(node)); + node.getRightChild().setRed(!isRed(node.getRightChild())); + node.getLeftChild().setRed(!isRed(node.getLeftChild())); + } + + private RBNode searchNode(V val) { + RBNode current = root; + while (current != null) { + if (current.getVal().equals(val)) { + return current; + } else if (comparator.compare(current.getVal(), val) < 0) { + current = current.getRightChild(); + } else { + current = current.getLeftChild(); + } + } + + return null; + } + + private RBNode moveRedRight(RBNode node) { + changeColor(node); + if (isRed(node.getLeftChild().getLeftChild())) { + node = rotateRight(node); + changeColor(node); + } + + return node; + } + + private RBNode moveRedLeft(RBNode node) { + changeColor(node); + if (isRed(node.getRightChild().getLeftChild())) { + node.setRightChild(rotateRight(node.getRightChild())); + node = rotateLeft(node); + changeColor(node); + } + + return node; + } + + // returns the nodes inorder + private List> inorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + inorder(root, result); + return result; + } + + private void inorder(RBNode current, List> result) { + if (current == null) { + return; + } + + inorder(current.getLeftChild(), result); + result.add(current); + inorder(current.getRightChild(), result); + } + + public List inorderValues(){ + List> inorder = inorder(); + List result = new ArrayList<>(inorder.size()); + for (RBNode node: inorder) { + result.add(node.getVal()); + } + return result; + } + + private List> preorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + preorder(root, result); + return result; + } + + private void preorder(RBNode current, List> result) { + if (current == null) { + return; + } + + result.add(current); + inorder(current.getLeftChild(), result); + inorder(current.getRightChild(), result); + } + + // returns the minimum node in the subtree of input node + private RBNode getMin(RBNode node) { + while (node.getLeftChild() != null) { + node = node.getLeftChild(); + } + return node; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java new file mode 100644 index 00000000000..8d3f6f7c3dd --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java @@ -0,0 +1,170 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +public class RedBlackIntervalComparatorTree, + NodeValue extends IntervalTreeNodeValue, T>> + extends RedBlackComparatorTree { + public RedBlackIntervalComparatorTree(Comparator> comparator) { + super((o1, o2) -> comparator.compare(o1.getInterval(), o2.getInterval())); + } + + + /** + * Constructs a new instance. The comparator compares the start value of both intervals. + * In a tie, it compares the end values. + */ + public RedBlackIntervalComparatorTree() { + this((o1, o2) -> { + int startCompare = o1.getStart().compareTo(o2.getStart()); + if (startCompare != 0) { + return startCompare; + } else { + return o1.getEnd().compareTo(o2.getEnd()); + } + }); + } + + private static final long serialVersionUID = 4353687394654923429L; + + + public List> overlapsWith(Interval interval) { + List> result = new LinkedList<>(); + + overlapsWith(this.getRoot(), interval, result); + + return result; + } + + + public List> overlapsWith(T point) { + List> result = new LinkedList<>(); + + overlapsWithPoint(this.getRoot(), point, result); + return result; + } + + + protected RBNode rotateRight(RBNode node) { + // Perform rotation as usual + RBNode result = super.rotateRight(node); + + // update hi vals + result.getVal().setHighValue(node.getVal().getHighValue()); + updateHi(node); + + return result; + } + + + protected RBNode rotateLeft(RBNode node) { + // Perform rotation as usual + RBNode result = super.rotateLeft(node); + + // update hi vals + result.getVal().setHighValue(node.getVal().getHighValue()); + updateHi(node); + + return result; + } + + @Override + protected RBNode delete(RBNode current, NodeValue val) { + RBNode result = super.delete(current, val); + updateHi(result); + return result; + } + + + protected RBNode insert(RBNode current, NodeValue val) { + RBNode result = super.insert(current, val); + updateHi(result); + return result; + } + + + protected RBNode balance(RBNode node) { + RBNode result = super.balance(node); + updateHi(result); + return result; + } + + // sets the hi attribute of the given node to the max of the subtree or itself + private void updateHi(RBNode node) { + if (node == null) { + return; + } + + T result = node.getVal().getInterval().getEnd(); + if (node.getRightChild() != null) { + result = max(result, node.getRightChild().getVal().getHighValue()); + } + + if (node.getLeftChild() != null) { + result = max(result, node.getLeftChild().getVal().getHighValue()); + } + + node.getVal().setHighValue(result); + } + + + // returns the max of two values + public T max(T t1, T t2) { + if (t1.compareTo(t2) > 0) { + return t1; + } else { + return t2; + } + } + + private void overlapsWith(RBNode node, Interval interval, List> result) { + if (node == null) { + return; + } + + // query starts strictly after any interval in the subtree + if (interval.getStart().compareTo(node.getVal().getHighValue()) > 0) { + return; + } + + // node and query overlap + if (node.getVal().getInterval().isIntersecting(interval)) { + result.add(node.getVal().getInterval()); + } + + // if the node starts before the query ends, check right children + if (node.getVal().getInterval().getStart().compareTo(interval.getEnd()) <= 0) { + overlapsWith(node.getRightChild(), interval, result); + } + + overlapsWith(node.getLeftChild(), interval, result); + } + + private void overlapsWithPoint(RBNode node, T point, List> result) { + if (node == null) { + return; + } + + // point is bigger than the endpoint of any interval in the subtree + if (point.compareTo(node.getVal().getHighValue()) > 0) { + return; + } + + // check left subtrees + overlapsWithPoint(node.getLeftChild(), point, result); + + // add node interval if it contains the query point + if (node.getVal().getInterval().contains(point)) { + result.add(node.getVal().getInterval()); + } + + // check right subtree if their start values are smaller (equal) than query point + if (point.compareTo(node.getVal().getInterval().getStart()) >= 0) { + overlapsWithPoint(node.getRightChild(), point, result); + } + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index f2901bc67e4..154def1ea18 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -1,5 +1,7 @@ package org.jgrapht.intervalgraph.interval; +import java.util.Objects; + public class Interval> implements Comparable> { private T start; private T end; @@ -72,4 +74,19 @@ public boolean isValid() { public String toString() { return "Interval[" + start + ", " + end + "]"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Interval interval = (Interval) o; + return Objects.equals(start, interval.start) && + Objects.equals(end, interval.end); + } + + @Override + public int hashCode() { + + return Objects.hash(start, end); + } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java new file mode 100644 index 00000000000..2afc76558dc --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java @@ -0,0 +1,36 @@ +package org.jgrapht.intervalgraph; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class RedBlackComparatorTreeTest { + RedBlackComparatorTree tree = new RedBlackComparatorTree<>(Integer::compareTo); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 100; i++) { + tree.insert(i); + } + + tree.delete(5); + tree.delete(73); + tree.delete(200); + } + + @Test + public void isOrdered() { + for (int i = 0; i < 100; i++) { + assertEquals(i, (int) tree.inorderValues().get(i)); + } + } + + @Test + public void contains() { + assertTrue(tree.contains(0)); + assertTrue(tree.contains(4)); + assertFalse(tree.contains(73)); + assertFalse(tree.contains(5)); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java new file mode 100644 index 00000000000..e8132faf34f --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java @@ -0,0 +1,41 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.jgrapht.intervalgraph.interval.Interval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class RedBlackIntervalComparatorTreeTest { + List list = new LinkedList<>(); + List sorted = new LinkedList<>(); + RedBlackIntervalComparatorTree, Integer>> tree = new RedBlackIntervalComparatorTree<>(); + + @Before + public void setUp() { + for (int i = 0; i < 20; i++) { + IntegerInterval interval = new IntegerInterval(i, i+3); + tree.insert(new IntervalTreeNodeValue<>(interval)); + sorted.add(interval); + } + } + + @Test + public void testInorder() { + List, Integer>> result = tree.inorderValues(); + for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { + Interval i = result.get(i1).getInterval(); + assertEquals("fault at " + i1,i, sorted.get(i1)); + } + + + assertTrue(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); + tree.delete(new IntervalTreeNodeValue<>(new IntegerInterval(5,8))); + assertFalse(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); + assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index aa01cb0ae54..de2ba0890ea 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -19,7 +19,7 @@ public class RedBlackIntervalTreeStructureTest { public void setUp() throws Exception { for (int i = 0; i < 20; i++) { IntegerInterval interval = new IntegerInterval(i, i+3); - tree.insert(i, new IntervalTreeNodeValue<>(interval,0)); + tree.insert(i, new IntervalTreeNodeValue<>(interval)); sorted.add(interval); } } From f5c0ed05d0fc5f6bf342bf44117a6f512810c756 Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Mon, 30 Apr 2018 11:07:43 +0200 Subject: [PATCH 051/131] Fixed typo --- .../org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 43f59716c63..2e50a66b539 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -140,7 +140,7 @@ private static V lastElementOf(HashMap map) { */ private static V randomElementOf(Set set) { if (set == null) { - throw new IllegalArgumentException("List parameter cannot be null."); + throw new IllegalArgumentException("Set parameter cannot be null."); } int index = new Random().nextInt(set.size()); From a112521060e3664c5c443f0e60c72bb00780123b Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Mon, 30 Apr 2018 12:15:09 +0200 Subject: [PATCH 052/131] Added documentation, refactored recognizer to be an object with fields containing the results of running the algorithm for quick access. --- .../IntervalGraphRecognizer.java | 361 +++++++++++------- .../traverse/LexBreadthFirstIterator.java | 17 + 2 files changed, 235 insertions(+), 143 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 561cdde59cd..75d332aa9fa 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -8,153 +8,228 @@ import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; -public final class IntervalGraphRecognizer { - - /** - * check if the given graph is an interval graph - * - * @param graph the graph to be checked - * @param the generic type representing vertices - * @param the generic type representing edges - * @return - */ - public static boolean isIntervalGraph(Graph graph) { - - // An empty graph is an interval graph. - if (graph.vertexSet().isEmpty()) { - return true; - } - - // Step 1 - LBFS from an arbitrary vertex - // Input - random vertex r - // Output - the result of current sweep alpha, further last vertex a visited by current sweep - HashMap sweepAlpha = lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); - V vertexA = lastElementOf(sweepAlpha); - - // Step 2 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep alpha, vertex a - // Output - the result of current sweep beta, further last vertex b visited by current sweep - HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, sweepAlpha); - V vertexB = lastElementOf(sweepBeta); - - // Step 3 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep beta, vertex b - // Output - the result of current sweep gamma, further last vertex c visited by current sweep - HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, sweepBeta); - V vertexC = lastElementOf(sweepGamma); - - // Step 4 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep gamma, vertex c - // Output - the result of current sweep delta, further last vertex d visited by current sweep - HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, sweepGamma); - V vertexD = lastElementOf(sweepDelta); - - // Additionally, calculate the index and the corresponding A set for each vertex - - // Step 5 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep delta, vertex d - // Output - the result of current sweep epsilon, further last vertex e visited by current sweep - HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, sweepDelta); - // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? - - // Additionally, calculate the index and the corresponding B set for each vertex - - // Step 6 - LBFS* with the resulting sweeps - // Input - the result of sweep gamma and sweep epsilon - // Output - the result of current sweep zeta - HashMap sweepZeta = lexBreadthFirstSearchStar(graph, vertexD, sweepDelta, sweepEpsilon); - - // if sweepZeta is umbrella-free, then the graph is interval. - // otherwise, the graph is not interval - //return isIOrdering(sweepZeta, graph); - - // Compute interval representation -- TODO: complete after merge - HashMap neighborIndex = new HashMap<>(); - for(V vertex : graph.vertexSet()) { - int maxNeighbor = 0; - - List neighbors = Graphs.neighborListOf(graph, vertex); - neighbors.add(vertex); - - for(V neighbor : neighbors) { - maxNeighbor = Math.max(maxNeighbor, sweepZeta.get(neighbor)); +public final class IntervalGraphRecognizer +{ + + /** + * Stores whether or not the graph is an interval graph. + */ + private boolean isIntervalGraph; + + /** + * Stores the computed interval graph representation (or null if no such representation + * exists) of the graph. + */ + private Graph intervalRepresentation; // TODO: change to work with an actual interval + // graph after merge + + /** + * Creates (and runs) a new interval graph recognizer for the given graph. + * + * @param graph the graph to be tested. + */ + public IntervalGraphRecognizer(Graph graph) + { + isIntervalGraph(graph); + } + + /** + * check if the graph is an interval graph + * + * @param the generic type representing vertices + * @param the generic type representing edges + * @return + */ + public boolean isIntervalGraph(Graph graph) + { + + // An empty graph is an interval graph. + if (graph.vertexSet().isEmpty()) { + return true; } - - neighborIndex.put(vertex, maxNeighbor); + + // Step 1 - LBFS from an arbitrary vertex + // Input - random vertex r + // Output - the result of current sweep alpha, further last vertex a visited by current + // sweep + HashMap sweepAlpha = + lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); + V vertexA = lastElementOf(sweepAlpha); + + // Step 2 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep alpha, vertex a + // Output - the result of current sweep beta, further last vertex b visited by current sweep + HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, sweepAlpha); + V vertexB = lastElementOf(sweepBeta); + + // Step 3 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep beta, vertex b + // Output - the result of current sweep gamma, further last vertex c visited by current + // sweep + HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, sweepBeta); + V vertexC = lastElementOf(sweepGamma); + + // Step 4 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep gamma, vertex c + // Output - the result of current sweep delta, further last vertex d visited by current + // sweep + HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, sweepGamma); + V vertexD = lastElementOf(sweepDelta); + + // Additionally, calculate the index and the corresponding A set for each vertex + + // Step 5 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep delta, vertex d + // Output - the result of current sweep epsilon, further last vertex e visited by current + // sweep + HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, sweepDelta); + // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? + + // Additionally, calculate the index and the corresponding B set for each vertex + + // Step 6 - LBFS* with the resulting sweeps + // Input - the result of sweep gamma and sweep epsilon + // Output - the result of current sweep zeta + HashMap sweepZeta = + lexBreadthFirstSearchStar(graph, vertexD, sweepDelta, sweepEpsilon); + + // if sweepZeta is umbrella-free, then the graph is interval. + // otherwise, the graph is not interval + + if (isIOrdering(sweepZeta, graph)) { + this.isIntervalGraph = true; + + // Compute interval representation -- TODO: complete after merge + HashMap neighborIndex = new HashMap<>(); + for (V vertex : graph.vertexSet()) { + int maxNeighbor = 0; + + List neighbors = Graphs.neighborListOf(graph, vertex); + neighbors.add(vertex); + + for (V neighbor : neighbors) { + maxNeighbor = Math.max(maxNeighbor, sweepZeta.get(neighbor)); + } + + neighborIndex.put(vertex, maxNeighbor); + } + + HashMap> intervals = new HashMap<>(graph.vertexSet().size()); + ArrayList> sortedIntervals = + new ArrayList<>(graph.vertexSet().size()); + + // Compute intervals and store them associated by their starting point ... + for (V vertex : graph.vertexSet()) { + Interval vertexInterval = + new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); + + intervals.put(sweepZeta.get(vertex), vertexInterval); + } + + // ... and produce a list sorted by the starting points for an efficient construction of + // the graph + for (int i = 0; i < graph.vertexSet().size(); i++) { + sortedIntervals.add(intervals.get(i)); + } + + // TODO: build the actual interval graph + this.intervalRepresentation = null; + } else { + // set values negatively + this.isIntervalGraph = false; + this.intervalRepresentation = null; + } + + return isIOrdering(sweepZeta, graph); } - - ArrayList> intervals = new ArrayList<>(graph.vertexSet().size()); - - for(V vertex : graph.vertexSet()) { - Interval vertexInterval = new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); - intervals.add(vertexInterval); + + /** + * Calculates if the given sweep is an I-Ordering (according to the Graph graph) + * + * @param + * + * @param sweep the order we want to check if its an I-Order + * @param graph the graph we want to check if its an I-Order + * @return true, if sweep is an I-Order according to graph + */ + private static boolean isIOrdering(HashMap sweep, Graph graph) + { + HashMap last = new HashMap<>(); + HashMap inverseSweep = new HashMap<>(); + + for (V vertex : graph.vertexSet()) { + int index = sweep.get(vertex); + inverseSweep.put(index, vertex); + } + + for (int i = 0; i < sweep.size() - 2; i++) { + for (int j = i + 1; j < sweep.size() - 1; j++) { + for (int k = j + 1; k < sweep.size(); k++) { + boolean edgeIJ = graph.containsEdge(inverseSweep.get(i), inverseSweep.get(j)); + boolean edgeIK = graph.containsEdge(inverseSweep.get(i), inverseSweep.get(k)); + if (edgeIK) { + if (edgeIJ) { + } else { + return false; + } + } + } + } + } + return true; } - - return isIOrdering(sweepZeta, graph); - } - - /** - * Calculates if the given sweep is an I-Ordering - * (according to the Graph graph) - * @param - * - * @param sweep the order we want to check if its an I-Order - * @param graph the graph we want to check if its an I-Order - * @return true, if sweep is an I-Order according to graph - */ - private static boolean isIOrdering(HashMap sweep, Graph graph) { - HashMap last = new HashMap<>(); - HashMap inverseSweep = new HashMap<>(); - - for(V vertex : graph.vertexSet()) { - int index = sweep.get(vertex); - inverseSweep.put(index, vertex); - } - - for (int i=0; i the generic type representing vertices - * @return - */ - private static V lastElementOf(HashMap map) { - return Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey(); - } - - /** - * return a random element of the given set - * - * @param set - * @param the generic type representing vertices - * @return - */ - private static V randomElementOf(Set set) { - if (set == null) { - throw new IllegalArgumentException("Set parameter cannot be null."); + + /** + * return the last element of the given map + * + * @param map + * @param the generic type representing vertices + * @return + */ + private static V lastElementOf(HashMap map) + { + return Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey(); + } + + /** + * return a random element of the given set + * + * @param set + * @param the generic type representing vertices + * @return + */ + private static V randomElementOf(Set set) + { + if (set == null) { + throw new IllegalArgumentException("Set parameter cannot be null."); + } + + int index = new Random().nextInt(set.size()); + Iterator iterator = set.iterator(); + for (int i = 0; i < index; i++) { + iterator.next(); + } + return iterator.next(); + } + + /** + * Returns whether or not the graph is an interval graph. + * + * @return true if the graph is an interval graph, otherwise false. + */ + public boolean isIntervalGraph() + { + return isIntervalGraph; } - int index = new Random().nextInt(set.size()); - Iterator iterator = set.iterator(); - for (int i = 0; i < index; i++) { - iterator.next(); + /** + * Returns an interval graph representation of the graph. + * + * @return an interval graph representation of the graph or null if the graph is not an + * interval graph. + */ + public Graph getIntervalGraphRepresentation() + { + return intervalRepresentation; } - return iterator.next(); - } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java index d6d3d2a5798..90a0e5293fe 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java +++ b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java @@ -613,8 +613,17 @@ boolean isEmpty() { class PriorityComparator implements Comparator { + /** + * Contains the priorities of the vertices. + */ private final HashMap priority; + /** + * Creates a new priority comparator for the vertex set with given priorities. + * + * @param priority the (integer-valued) priorities of the vertices. + * @throws IllegalArgumentException if the priorities are null. + */ public PriorityComparator(HashMap priority) throws IllegalArgumentException { if(priority == null) { throw new IllegalArgumentException("Priority map must not be null"); @@ -623,6 +632,14 @@ public PriorityComparator(HashMap priority) throws IllegalArgumentEx } @Override + /** + * Compares the priorities of the given vertices. + * + * @param vertex1 the first vertex to be compared. + * @param vertex2 the second vertex to be compared. + * + * @return Returns a positive integer (zero/a negative integer) if the priority of vertex1 is larger (equal to/smaller) than the one of vertex2. + */ public int compare(V vertex1, V vertex2) { return (priority.get(vertex1) - priority.get(vertex2)); From a9f5c10526fe937499a9851a483627acbc1bd74a Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Mon, 30 Apr 2018 12:34:28 +0200 Subject: [PATCH 053/131] Added more documentation for the recognizer class and some notes forstuff to be fixed once we merge --- .../IntervalGraphRecognizer.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 75d332aa9fa..9c96aaa8077 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -8,6 +8,27 @@ import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; +/** + * A recognizer for interval graphs. + *

+ * An interval graph is a intersection graph of a set of intervals on the line, i.e. they contain a + * vertex for each interval and two vertices are connected if the corresponding intervals have a + * nonempty intersection. + *

+ * The recognizer uses the algorithm described in + * (The LBFS Structure + * and Recognition of Interval Graphs. SIAM J. Discrete Math.. 23. 1905-1953. + * 10.1137/S0895480100373455.) by Derek Corneil, Stephan Olariu and Lorna Stewart based on + * multiple lexicographical breadth-first search (LBFS) sweeps. + *

+ * For this recognizer to work correctly the graph must not be modified during iteration. + *

+ * + * @param the graph vertex type. + * @param the graph edge type. + * @author Team J + * @since April 2018 + */ public final class IntervalGraphRecognizer { @@ -154,7 +175,7 @@ public boolean isIntervalGraph(Graph graph) */ private static boolean isIOrdering(HashMap sweep, Graph graph) { - HashMap last = new HashMap<>(); + //HashMap last = new HashMap<>(); TODO: is this needed? Improve the algorithm. HashMap inverseSweep = new HashMap<>(); for (V vertex : graph.vertexSet()) { From d2b663c8c3e86f6247ec70660f818a9b5ca17267 Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Mon, 30 Apr 2018 12:46:44 +0200 Subject: [PATCH 054/131] Refactored tests to work with recognizer instances rather than a static function --- .../interval/IntervalGraphRecognizerTest.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 0a0c1b8e9dc..cace8f9c24e 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -16,9 +16,10 @@ public class IntervalGraphRecognizerTest { @Test public void testEmptyGraph() { - Graph g = new SimpleGraph<>(DefaultEdge.class); + Graph emptyGraph = new SimpleGraph<>(DefaultEdge.class); - assertTrue(IntervalGraphRecognizer.isIntervalGraph(g)); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(emptyGraph); + assertTrue(recognizer.isIntervalGraph()); } @Test @@ -33,7 +34,8 @@ public void testForbiddenSubgraphBiclawWithAT() { builder.addEdge(2, 5); builder.addEdge(3, 6); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } @Test @@ -55,7 +57,8 @@ public void testForbiddenSubgraphLekkerkerkerBoland() { builder.addEdge(3, 6); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { @@ -70,7 +73,8 @@ public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { builder.addEdge(n - 1, n); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } @Test @@ -86,8 +90,9 @@ public boolean isCnAnIntervalGraph(int n) { for(int i = 0; i < n; i++) { builder.addEdge(i, (i + 1) % n); } - - return IntervalGraphRecognizer.isIntervalGraph(builder.build()); + + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + return recognizer.isIntervalGraph(); } @Test From 87ef7ee4dd85898c18a3badf3f6ab8ed70a4ae00 Mon Sep 17 00:00:00 2001 From: Oliver Feith Date: Mon, 30 Apr 2018 13:20:33 +0200 Subject: [PATCH 055/131] Implemented linear time I-Ordering algorithm --- .../IntervalGraphRecognizer.java | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 9c96aaa8077..3a9e1b5239a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -163,9 +163,9 @@ public boolean isIntervalGraph(Graph graph) return isIOrdering(sweepZeta, graph); } - + /** - * Calculates if the given sweep is an I-Ordering (according to the Graph graph) + * Calculates if the given sweep is an I-Ordering (according to the Graph graph) in linear time. * * @param * @@ -175,30 +175,47 @@ public boolean isIntervalGraph(Graph graph) */ private static boolean isIOrdering(HashMap sweep, Graph graph) { - //HashMap last = new HashMap<>(); TODO: is this needed? Improve the algorithm. + // Compute inverse sweep map to quickly find vertices at given indices HashMap inverseSweep = new HashMap<>(); for (V vertex : graph.vertexSet()) { int index = sweep.get(vertex); inverseSweep.put(index, vertex); } - - for (int i = 0; i < sweep.size() - 2; i++) { - for (int j = i + 1; j < sweep.size() - 1; j++) { - for (int k = j + 1; k < sweep.size(); k++) { - boolean edgeIJ = graph.containsEdge(inverseSweep.get(i), inverseSweep.get(j)); - boolean edgeIK = graph.containsEdge(inverseSweep.get(i), inverseSweep.get(k)); - if (edgeIK) { - if (edgeIJ) { - } else { - return false; - } - } + + // Compute maximal neighbors w.r.t. sweep ordering for every vertex + HashMap maxNeighbors = new HashMap<>(graph.vertexSet().size()); + + for(V vertex : graph.vertexSet()) { + List neighbors = Graphs.neighborListOf(graph, vertex); + V maxNeighbor = vertex; + + for(V neighbor : neighbors) { + if(sweep.get(neighbor) > sweep.get(maxNeighbor)) { + maxNeighbor = neighbor; + } + } + + maxNeighbors.put(vertex, maxNeighbor); + } + + // Check if every vertex is connected to all vertices between itself and its maximal neighbor + for(V vertex : graph.vertexSet()) { + int index = sweep.get(vertex); + int maxIndex = sweep.get(maxNeighbors.get(vertex)); + + for(int i = index; i < maxIndex; i++) { + if(!graph.containsEdge(vertex, inverseSweep.get(i))) { + // Found missing edge + return false; } } } + + // No missing edge found return true; } + /** * return the last element of the given map From 1d6f9223c1877c73bb71c56a6dede7830629b6e8 Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Tue, 1 May 2018 13:45:04 +0200 Subject: [PATCH 056/131] Add tests for RedBlackTree --- .../RedBlackComparatorTreeTest.java | 7 +- .../RedBlackIntervalComparatorTreeTest.java | 2 +- .../RedBlackIntervalTreeStructureTest.java | 2 +- .../intervalgraph/RedBlackTreeTest.java | 82 +++++++++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java index 2afc76558dc..38056c076cf 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.*; public class RedBlackComparatorTreeTest { + RedBlackComparatorTree tree = new RedBlackComparatorTree<>(Integer::compareTo); @Before @@ -27,10 +28,12 @@ public void isOrdered() { } @Test - public void contains() { + public void testContains() { assertTrue(tree.contains(0)); assertTrue(tree.contains(4)); - assertFalse(tree.contains(73)); + assertFalse(tree.contains(5)); + assertFalse(tree.contains(73)); + assertFalse(tree.contains(200)); } } \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java index e8132faf34f..3da0ba50ef1 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.*; public class RedBlackIntervalComparatorTreeTest { - List list = new LinkedList<>(); + List sorted = new LinkedList<>(); RedBlackIntervalComparatorTree, Integer>> tree = new RedBlackIntervalComparatorTree<>(); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index de2ba0890ea..1ddcfffcbad 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.*; public class RedBlackIntervalTreeStructureTest { - List list = new LinkedList<>(); + List sorted = new LinkedList<>(); RedBlackIntervalTree, Integer>> tree = new RedBlackIntervalTree<>(); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java new file mode 100644 index 00000000000..d2c581e9eef --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java @@ -0,0 +1,82 @@ +package org.jgrapht.intervalgraph; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Test important properties of red-black tree + */ +public class RedBlackTreeTest { + + private RedBlackTree redBlackTree = new RedBlackTree<>(); + + @Before + public void setUp() { + redBlackTree.insert(13, 13); + redBlackTree.insert(8, 8); + redBlackTree.insert(17, 17); + redBlackTree.insert(1, 1); + redBlackTree.insert(11, 11); + redBlackTree.insert(15, 15); + redBlackTree.insert(25, 25); + redBlackTree.insert(6, 6); + redBlackTree.insert(22, 22); + redBlackTree.insert(27, 27); + } + + /** + * The root is black + */ + @Test + public void testBlackRoot() { + assertFalse(redBlackTree.getRoot().isRed()); + } + + /** + * If a node is red, then both its children are black + */ + @Test + public void testBlackChildren() { + testBlackChildren(redBlackTree.getRoot()); + } + + private void testBlackChildren(Node currentNode) { + Node leftChild = currentNode.getLeftChild(); + if (leftChild != null) { + if (currentNode.isRed()) { + assertFalse(leftChild.isRed()); + } + testBlackChildren(leftChild); + } + + Node rightChild = currentNode.getRightChild(); + if (rightChild != null) { + if (currentNode.isRed()) { + assertFalse(rightChild.isRed()); + } + testBlackChildren(rightChild); + } + } + + /** + * Every path from a given node to any of its descendant leaves contains the same number of black nodes + */ + @Test + public void testBlackNodeNumber() { + assertEquals(countLeftChildren(redBlackTree.getRoot(), 0), countRightChildren(redBlackTree.getRoot(), 0)); + } + + private int countLeftChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); + } + + private int countRightChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); + } + +} From 0e4fa068887ebb84a1186cd11303021cefff8eec Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Tue, 1 May 2018 13:56:57 +0200 Subject: [PATCH 057/131] Fix typos in RedBlackTree --- .../org/jgrapht/intervalgraph/RedBlackComparatorTree.java | 7 ++----- .../main/java/org/jgrapht/intervalgraph/RedBlackTree.java | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java index 21c79a38722..d9541c33534 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -34,10 +34,7 @@ public RBNode getRoot() { } private boolean isRed(RBNode node){ - if (node == null) { - return false; - } - return node.isRed(); + return node == null ? false : node.isRed(); } /** @@ -56,7 +53,7 @@ public boolean contains(V val) { } /** - * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * Inserts the given (key, value) pair into the tree. If the tree contains already a symbol with the given key * it overwrites the old value with the new. * * @param val the value diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 429ec51fa0f..dfc04a5080f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -65,7 +65,7 @@ public boolean contains(K key) { } /** - * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * Inserts the given (key, value) pair into the tree. If the tree contains already a symbol with the given key * it overwrites the old value with the new. * * @param key the key From dae17f8534a0524c03105f590bd948853ce45558 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 May 2018 17:43:49 +0200 Subject: [PATCH 058/131] fixed bug while deleting vertices --- .../jgrapht/intervalgraph/IntervalGraph.java | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index da84324542e..55484946bad 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -382,11 +382,7 @@ public boolean removeEdge(E e) public boolean removeVertex(V v) { if (containsVertex(v)) { - Set touchingEdgesList = edgesOf(v); - - // cannot iterate over list - will cause - // ConcurrentModificationException - removeAllEdges(new ArrayList<>(touchingEdgesList)); + removeAllEdgesFromVertex(v);//remove all edges from the given vertex to delete it safely specifics.removeVertex(v);// remove the vertex itself @@ -505,4 +501,28 @@ private boolean addIntervalEdges(V sourceVertex, Collection targetVertices) { } return true; } + + /** + * @see Graph#removeAllEdges(Collection) + */ + private boolean removeAllEdgesFromVertex(V vertex) { + Set touchingEdgesList = edgesOf(vertex); + + // cannot iterate over list - will cause + // ConcurrentModificationException + ArrayList edges = new ArrayList<>(touchingEdgesList); + + boolean modified = false; + + for (E e : edges) { + + if (containsEdge(e)) { + specifics.removeEdgeFromTouchingVertices(e); + intrusiveEdgesSpecifics.remove(e); + modified = true; + } + } + + return modified; + } } From b79cbeab1901093f32b8303a7c16f3f64fcf12ee Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 May 2018 20:29:38 +0200 Subject: [PATCH 059/131] refreshed redblackintervaltree integration --- .../intervalgraph/BinarySearchTree.java | 2 +- .../intervalgraph/IntervalTreeInterface.java | 2 +- .../intervalgraph/IntervalTreeNodeKey.java | 133 ++++++++++++++++++ .../intervalgraph/IntervalTreeNodeValue.java | 1 - .../intervalgraph/IntervalTreeStructure.java | 22 ++- .../intervalgraph/RedBlackComparatorTree.java | 6 +- .../RedBlackIntervalComparatorTree.java | 4 +- .../intervalgraph/RedBlackIntervalTree.java | 28 ++-- .../jgrapht/intervalgraph/RedBlackTree.java | 10 +- .../RedBlackIntervalTreeStructureTest.java | 30 ++-- 10 files changed, 197 insertions(+), 41 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java index db0b01d6f64..8578d1cc370 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -151,7 +151,7 @@ public interface BinarySearchTree { /** * Returns all keys in the symbol table as an Iterable. * To iterate over all of the keys in the symbol table named st, - * use the foreach notation: for (Key key : st.keys()). + * use the foreach notation: for (IntervalTreeNodeKey key : st.keys()). * * @return all keys in the symbol table as an Iterable */ diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index 4c775653526..059df78ae90 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -15,7 +15,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public interface IntervalTreeInterface, NodeValue extends IntervalTreeNodeValue, T>> extends BinarySearchTree { +public interface IntervalTreeInterface< T extends Comparable, K extends Comparable, NodeValue extends IntervalTreeNodeValue, T>> extends BinarySearchTree { /** * Returns all intervals of all vertices that intersect with the given interval diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java new file mode 100644 index 00000000000..fab2133f0c9 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java @@ -0,0 +1,133 @@ +package org.jgrapht.intervalgraph; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Objects; + +/** + * Implementation of IntervalTreeNodeKey + * This is a container class to store the necessary key data for the (augmented) interval tree in the nodes of the tree. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since May 02, 2018 + */ +public class IntervalTreeNodeKey implements Comparable> { + + private T key; + private Comparator comparator; + + /** + * constructs an IntervalTreeNodeKey object + * + * @param key the content of the key + * @param comparator the comparator defining the order of the key + */ + public IntervalTreeNodeKey(T key, Comparator comparator) { + this.key = key; + this.comparator = comparator; + } + + /** + * Compares this object with the specified object for order. Returns a + * negative integer, zero, or a positive integer as this object is less + * than, equal to, or greater than the specified object. + * + *

The implementor must ensure + * {@code sgn(x.compareTo(y)) == -sgn(y.compareTo(x))} + * for all {@code x} and {@code y}. (This + * implies that {@code x.compareTo(y)} must throw an exception iff + * {@code y.compareTo(x)} throws an exception.) + * + *

The implementor must also ensure that the relation is transitive: + * {@code (x.compareTo(y) > 0 && y.compareTo(z) > 0)} implies + * {@code x.compareTo(z) > 0}. + * + *

Finally, the implementor must ensure that {@code x.compareTo(y)==0} + * implies that {@code sgn(x.compareTo(z)) == sgn(y.compareTo(z))}, for + * all {@code z}. + * + *

It is strongly recommended, but not strictly required that + * {@code (x.compareTo(y)==0) == (x.equals(y))}. Generally speaking, any + * class that implements the {@code Comparable} interface and violates + * this condition should clearly indicate this fact. The recommended + * language is "Note: this class has a natural ordering that is + * inconsistent with equals." + * + *

In the foregoing description, the notation + * {@code sgn(}expression{@code )} designates the mathematical + * signum function, which is defined to return one of {@code -1}, + * {@code 0}, or {@code 1} according to whether the value of + * expression is negative, zero, or positive, respectively. + * + * @param o the object to be compared. + * @return a negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + * @throws NullPointerException if the specified object is null + * @throws ClassCastException if the specified object's type prevents it + * from being compared to this object. + */ + @Override + public int compareTo(IntervalTreeNodeKey o) { + return comparator.compare(this.key, o.key); + } + + /** + * Indicates whether some other object is "equal to" this one. + *

+ * The {@code equals} method implements an equivalence relation + * on non-null object references: + *

+ *

+ * The {@code equals} method for class {@code Object} implements + * the most discriminating possible equivalence relation on objects; + * that is, for any non-null reference values {@code x} and + * {@code y}, this method returns {@code true} if and only + * if {@code x} and {@code y} refer to the same object + * ({@code x == y} has the value {@code true}). + *

+ * Note that it is generally necessary to override the {@code hashCode} + * method whenever this method is overridden, so as to maintain the + * general contract for the {@code hashCode} method, which states + * that equal objects must have equal hash codes. + * + * @param obj the reference object with which to compare. + * @return {@code true} if this object is the same as the obj + * argument; {@code false} otherwise. + * @see #hashCode() + * @see HashMap + */ + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + else if (!(obj instanceof IntervalTreeNodeKey)) + return false; + + @SuppressWarnings("unchecked") IntervalTreeNodeKey other = (IntervalTreeNodeKey) obj; + return Objects.equals(key, other.key) && Objects.equals(comparator, other.comparator); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java index 7e8655f3e77..2935009e236 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -32,7 +32,6 @@ public class IntervalTreeNodeValue, T extends Comparable> implements IntervalS private static final long serialVersionUID = 2834567756342332325L; - private IntervalTreeInterface, T>> tree = new RedBlackIntervalTree<>(); + private IntervalTreeInterface>, IntervalTreeNodeValue, T>> tree = new RedBlackIntervalTree<>(); /** * Returns all intervals that overlap with the given interval @@ -44,7 +45,7 @@ public List> overlapsWithPoint(T point) { */ @Override public void add(Interval interval) { - tree.insert(interval.getStart(), new IntervalTreeNodeValue<>(interval)); + tree.insert(new IntervalTreeNodeKey<>(interval, getComparator()), new IntervalTreeNodeValue<>(interval)); } /** @@ -55,6 +56,21 @@ public void add(Interval interval) { */ @Override public void remove(Interval interval) { - tree.delete(interval.getStart()); + tree.delete(new IntervalTreeNodeKey<>(interval, getComparator())); + } + + /** + * returns the comparator used to compare the keys in the interval tree + * + */ + private Comparator> getComparator() { + return (o1, o2) -> { + int startCompare = o1.getStart().compareTo(o2.getStart()); + if (startCompare != 0) { + return startCompare; + } else { + return o1.getEnd().compareTo(o2.getEnd()); + } + }; } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java index d9541c33534..e60d983071a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -22,11 +22,9 @@ public class RedBlackComparatorTree implements Serializable { protected RBNode root; public final Comparator comparator; - public final Comparator> nodeComparator; public RedBlackComparatorTree(Comparator comparator) { this.comparator = comparator; - this.nodeComparator = (o1, o2) -> comparator.compare(o1.getVal(), o2.getVal()); } public RBNode getRoot() { @@ -106,7 +104,7 @@ protected RBNode insert(RBNode current, V val) { public void delete(V val) { if (val == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("IntervalTreeNodeKey is null"); } if (!contains(val)) { return; @@ -354,7 +352,7 @@ public int rank(V val) { /** * Returns all keys in the symbol table as an Iterable. * To iterate over all of the keys in the symbol table named st, - * use the foreach notation: for (Key key : st.keys()). + * use the foreach notation: for (IntervalTreeNodeKey key : st.keys()). * * @return all keys in the symbol table as an Iterable */ diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java index 8d3f6f7c3dd..94d6f5ef783 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java @@ -6,9 +6,7 @@ import java.util.LinkedList; import java.util.List; -public class RedBlackIntervalComparatorTree, - NodeValue extends IntervalTreeNodeValue, T>> - extends RedBlackComparatorTree { +public class RedBlackIntervalComparatorTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackComparatorTree { public RedBlackIntervalComparatorTree(Comparator> comparator) { super((o1, o2) -> comparator.compare(o1.getInterval(), o2.getInterval())); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index 2afe6c223bc..eb1dda1b995 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -18,7 +18,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface, Serializable { +public class RedBlackIntervalTree, K extends Comparable, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface, Serializable { private static final long serialVersionUID = 4353687394654923429L; @@ -40,9 +40,9 @@ public List> overlapsWith(T point) { } @Override - protected Node rotateRight(Node node) { + protected Node rotateRight(Node node) { // Perform rotation as usual - Node result = super.rotateRight(node); + Node result = super.rotateRight(node); // update hi vals result.getVal().setHighValue(node.getVal().getHighValue()); @@ -52,9 +52,9 @@ protected Node rotateRight(Node node) { } @Override - protected Node rotateLeft(Node node) { + protected Node rotateLeft(Node node) { // Perform rotation as usual - Node result = super.rotateLeft(node); + Node result = super.rotateLeft(node); // update hi vals result.getVal().setHighValue(node.getVal().getHighValue()); @@ -64,28 +64,28 @@ protected Node rotateLeft(Node node) { } @Override - protected Node delete(Node current, T key) { - Node result = super.delete(current, key); + protected Node delete(Node current, K key) { + Node result = super.delete(current, key); updateHi(result); return result; } @Override - protected Node insert(Node current, T key, NodeValue val) { - Node result = super.insert(current, key, val); + protected Node insert(Node current, K key, NodeValue val) { + Node result = super.insert(current, key, val); updateHi(result); return result; } @Override - protected Node balance(Node node) { - Node result = super.balance(node); + protected Node balance(Node node) { + Node result = super.balance(node); updateHi(result); return result; } // sets the hi attribute of the given node to the max of the subtree or itself - private void updateHi(Node node) { + private void updateHi(Node node) { if (node == null) { return; } @@ -112,7 +112,7 @@ public T max(T t1, T t2) { } } - private void overlapsWith(Node node, Interval interval, List> result) { + private void overlapsWith(Node node, Interval interval, List> result) { if (node == null) { return; } @@ -135,7 +135,7 @@ private void overlapsWith(Node node, Interval interval, List node, T point, List> result) { + private void overlapsWithPoint(Node node, T point, List> result) { if (node == null) { return; } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index dfc04a5080f..62a2c40d35a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -35,7 +35,7 @@ public Node getRoot() { @Override public V get(K key) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("IntervalTreeNodeKey is null"); } return searchNode(key).getVal(); @@ -58,7 +58,7 @@ private boolean isRed(Node node){ @Override public boolean contains(K key) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("IntervalTreeNodeKey is null"); } return searchNode(key) != null; @@ -75,7 +75,7 @@ public boolean contains(K key) { @Override public void insert(K key, V val) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("IntervalTreeNodeKey is null"); } root = insert(root, key, val); @@ -120,7 +120,7 @@ protected Node insert(Node current, K key, V val) { @Override public void delete(K key) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("IntervalTreeNodeKey is null"); } if (!contains(key)) { return; @@ -371,7 +371,7 @@ public int rank(K key) { /** * Returns all keys in the symbol table as an Iterable. * To iterate over all of the keys in the symbol table named st, - * use the foreach notation: for (Key key : st.keys()). + * use the foreach notation: for (IntervalTreeNodeKey key : st.keys()). * * @return all keys in the symbol table as an Iterable */ diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index 1ddcfffcbad..fa13b91d1aa 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -1,25 +1,26 @@ package org.jgrapht.intervalgraph; -import org.jgrapht.intervalgraph.interval.IntegerInterval; import org.jgrapht.intervalgraph.interval.Interval; import org.junit.Before; import org.junit.Test; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; public class RedBlackIntervalTreeStructureTest { - List sorted = new LinkedList<>(); - RedBlackIntervalTree, Integer>> tree = new RedBlackIntervalTree<>(); + List> sorted = new LinkedList<>(); + RedBlackIntervalTree>, IntervalTreeNodeValue, Integer>> tree = new RedBlackIntervalTree<>(); @Before public void setUp() throws Exception { for (int i = 0; i < 20; i++) { - IntegerInterval interval = new IntegerInterval(i, i+3); - tree.insert(i, new IntervalTreeNodeValue<>(interval)); + Interval interval = new Interval<>(i, i + 3); + tree.insert(new IntervalTreeNodeKey<>(interval, getComparator()), new IntervalTreeNodeValue<>(interval)); sorted.add(interval); } } @@ -29,12 +30,23 @@ public void testInorder() { List, Integer>> result = tree.inorderValues(); for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { Interval i = result.get(i1).getInterval(); - assertEquals("fault at " + i1,i, sorted.get(i1)); + assertEquals("fault at " + i1, i, sorted.get(i1)); } - tree.delete(5); - assertFalse(tree.contains(5)); + tree.delete(new IntervalTreeNodeKey<>(new Interval<>(5, 8), getComparator())); + assertFalse(tree.contains(new IntervalTreeNodeKey<>(new Interval<>(5, 8), getComparator()))); assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); } + + private Comparator> getComparator() { + return (o1, o2) -> { + int startCompare = o1.getStart().compareTo(o2.getStart()); + if (startCompare != 0) { + return startCompare; + } else { + return o1.getEnd().compareTo(o2.getEnd()); + } + }; + } } \ No newline at end of file From 0ae4e6b44429dc8d1adad3cd5f6f18e05f8e586d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 May 2018 20:44:00 +0200 Subject: [PATCH 060/131] redone incorrect changes --- .../jgrapht/intervalgraph/RedBlackComparatorTree.java | 6 ++++-- .../java/org/jgrapht/intervalgraph/RedBlackTree.java | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java index e60d983071a..d9541c33534 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -22,9 +22,11 @@ public class RedBlackComparatorTree implements Serializable { protected RBNode root; public final Comparator comparator; + public final Comparator> nodeComparator; public RedBlackComparatorTree(Comparator comparator) { this.comparator = comparator; + this.nodeComparator = (o1, o2) -> comparator.compare(o1.getVal(), o2.getVal()); } public RBNode getRoot() { @@ -104,7 +106,7 @@ protected RBNode insert(RBNode current, V val) { public void delete(V val) { if (val == null) { - throw new IllegalArgumentException("IntervalTreeNodeKey is null"); + throw new IllegalArgumentException("Key is null"); } if (!contains(val)) { return; @@ -352,7 +354,7 @@ public int rank(V val) { /** * Returns all keys in the symbol table as an Iterable. * To iterate over all of the keys in the symbol table named st, - * use the foreach notation: for (IntervalTreeNodeKey key : st.keys()). + * use the foreach notation: for (Key key : st.keys()). * * @return all keys in the symbol table as an Iterable */ diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 62a2c40d35a..dfc04a5080f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -35,7 +35,7 @@ public Node getRoot() { @Override public V get(K key) { if (key == null) { - throw new IllegalArgumentException("IntervalTreeNodeKey is null"); + throw new IllegalArgumentException("Key is null"); } return searchNode(key).getVal(); @@ -58,7 +58,7 @@ private boolean isRed(Node node){ @Override public boolean contains(K key) { if (key == null) { - throw new IllegalArgumentException("IntervalTreeNodeKey is null"); + throw new IllegalArgumentException("Key is null"); } return searchNode(key) != null; @@ -75,7 +75,7 @@ public boolean contains(K key) { @Override public void insert(K key, V val) { if (key == null) { - throw new IllegalArgumentException("IntervalTreeNodeKey is null"); + throw new IllegalArgumentException("Key is null"); } root = insert(root, key, val); @@ -120,7 +120,7 @@ protected Node insert(Node current, K key, V val) { @Override public void delete(K key) { if (key == null) { - throw new IllegalArgumentException("IntervalTreeNodeKey is null"); + throw new IllegalArgumentException("Key is null"); } if (!contains(key)) { return; @@ -371,7 +371,7 @@ public int rank(K key) { /** * Returns all keys in the symbol table as an Iterable. * To iterate over all of the keys in the symbol table named st, - * use the foreach notation: for (IntervalTreeNodeKey key : st.keys()). + * use the foreach notation: for (Key key : st.keys()). * * @return all keys in the symbol table as an Iterable */ From 4285a042a532d25ac1adab97155b16492d0bce0d Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Wed, 2 May 2018 21:19:40 +0200 Subject: [PATCH 061/131] added Intervalgraph Tree Decomposition Algorithm --- .../CordalgraphDecomposition.java | 19 ++++ .../IntervalgraphDecomposition.java | 107 ++++++++++++++++++ .../treedecomposition/TreeDecomposition.java | 10 ++ 3 files changed, 136 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java new file mode 100644 index 00000000000..fb8be9e8208 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java @@ -0,0 +1,19 @@ +package org.jgrapht.alg.treedecomposition; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + +public class CordalgraphDecomposition + implements TreeDecomposition +{ + + @Override + public Graph,DefaultEdge> getTreeDecomposition() + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java new file mode 100644 index 00000000000..eab875a34a8 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -0,0 +1,107 @@ +package org.jgrapht.alg.treedecomposition; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; +import org.jgrapht.intervalgraph.*; +import org.jgrapht.intervalgraph.interval.*; + +public class IntervalgraphDecomposition> + implements TreeDecomposition +{ + private Graph,DefaultEdge> treeDecomposition = null; + private Set currentVertex = null; + private List> startSort, endSort; + + public IntervalgraphDecomposition(Graph graph) + { + //TODO + } + + public IntervalgraphDecomposition(IntervalGraph,E> graph) + { + //TODO + } + + public IntervalgraphDecomposition(List> intervals) + { + startSort = new ArrayList<>(intervals); + endSort = new ArrayList<>(intervals); + startSort.sort(new IntervalVertexComparator(true)); + endSort.sort(new IntervalVertexComparator(false)); + } + + private void computeTreeDecomposition() + { + if(treeDecomposition != null) + return; + + initTreeDecomposition(); + + int endIndex=0; + for(IntervalVertex iv: startSort) { + while(endSort.get(endIndex).getInterval().getEnd().compareTo( + iv.getInterval().getStart()) < 0) + { + addForget(endSort.get(endIndex).getVertex()); + endIndex++; + } + addIntroduce(iv.getVertex()); + } + } + + private void initTreeDecomposition() + { + treeDecomposition = new DefaultUndirectedGraph,DefaultEdge>(DefaultEdge.class); + Set root = new HashSet(0); + treeDecomposition.addVertex(root); + currentVertex = root; + } + + private void addIntroduce(V vertex) + { + Set nextVertex = new HashSet(currentVertex); + nextVertex.add(vertex); + treeDecomposition.addVertex(nextVertex); + treeDecomposition.addEdge(currentVertex, nextVertex); + currentVertex = nextVertex; + } + + private void addForget(V vertex) + { + Set nextVertex = new HashSet(currentVertex); + nextVertex.remove(vertex); + treeDecomposition.addVertex(nextVertex); + treeDecomposition.addEdge(currentVertex, nextVertex); + currentVertex = nextVertex; + } + + @Override + public Graph,DefaultEdge> getTreeDecomposition() + { + computeTreeDecomposition(); + return treeDecomposition; + } + + + + private class IntervalVertexComparator implements Comparator> { + + private boolean start = true;; + + public IntervalVertexComparator(boolean startKey) { + start = startKey; + } + + @Override + public int compare(IntervalVertex o1, IntervalVertex o2) + { + if(start) + return o1.getInterval().getStart().compareTo(o2.getInterval().getStart()); + else + return o1.getInterval().getEnd().compareTo(o2.getInterval().getEnd()); + } + + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java new file mode 100644 index 00000000000..0011a3a6e19 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java @@ -0,0 +1,10 @@ +package org.jgrapht.alg.treedecomposition; + +import java.util.*; +import org.jgrapht.*; +import org.jgrapht.graph.*; + +public interface TreeDecomposition +{ + Graph,DefaultEdge> getTreeDecomposition(); +} From f44e0f7a7716fe6ae716a24b5b381a67ba6b12f0 Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Thu, 3 May 2018 11:20:59 +0200 Subject: [PATCH 062/131] fixed RedBlackTree.min --- .../src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index dfc04a5080f..15faafaf3cb 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -291,7 +291,7 @@ private Node min(Node node) { if (node.getLeftChild() == null) { return node; } - return max(node.getLeftChild()); + return min(node.getLeftChild()); } /** From 13aadda900012211c48dd6cc4e4f9aa9a16bdf2d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 May 2018 11:34:21 +0200 Subject: [PATCH 063/131] add doc for type in RedBlackIntervalTree --- .../java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index eb1dda1b995..aeeafde97c9 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -12,6 +12,7 @@ * after any operation on this tree. The highValue equals to the highest endpoint in the subtree * * @param the type of the interval + * @param the type of the key * @param the type of the node value * * @author Daniel Mock (danielmock) From a39a3aff98c5c04f1909c19b4238e7af67f0efa2 Mon Sep 17 00:00:00 2001 From: "Daniel A. Mock" Date: Thu, 3 May 2018 12:34:55 +0200 Subject: [PATCH 064/131] Added list constructor --- .../jgrapht/intervalgraph/RedBlackTree.java | 87 +++++++++++- .../intervalgraph/RedBlackTreeTest.java | 130 ++++++++++-------- 2 files changed, 157 insertions(+), 60 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 15faafaf3cb..e7577bd35b0 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -1,9 +1,7 @@ package org.jgrapht.intervalgraph; import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; +import java.util.*; /** * Implementation of a Red-Black-Tree @@ -25,6 +23,89 @@ public Node getRoot() { return root; } + public RedBlackTree() { + } + + + /** + * Construct a tree with the given keys and values. + * keys.get(i) is assigned to values.get(i) + * Runs in linear time if list is sorted, otherwise naive insertion is performed + * @param keys + * @param values + */ + public RedBlackTree(List keys, List values) { + ArrayList keyList; + ArrayList valueList; + int length = keys.size(); + + // exceptions + if (length != values.size()) { + throw new RuntimeException("Key and value list have to have same length"); + } + if (keys.size() == 0) { + return; + } + + // transform to ArrayList for good performance + if (keys instanceof ArrayList) { + keyList = (ArrayList) keys; + } else { + keyList = new ArrayList<>(keys); + } + + if (values instanceof ArrayList) { + valueList = (ArrayList) values; + } else { + valueList = new ArrayList<>(values); + } + + // check if list is sorted to use efficient insertion + boolean isSorted = true; + K current = keyList.get(0); + for (int i = 1; i < length; i++) { + K next = keyList.get(i); + if (current.compareTo(next) > 0) { + isSorted = false; + break; + } + } + + // use optimized insert if input is sorted, otherwise trivial insertion + if (isSorted) { + root = sortedListToBST(keyList, valueList, 0, length - 1); + } else { + for (int i = 0; i < length; i++) { + this.insert(keyList.get(i), valueList.get(i)); + } + } + } + + private Node sortedListToBST(ArrayList keys, ArrayList values, int start, int end) { + if (start > end) { + return null; + } + + int mid = start + (end - start) / 2; + Node node = new Node<>(keys.get(mid), values.get(mid), false, 0); // colors and size have to be updated + Node left = sortedListToBST(keys, values, start, mid - 1); + Node right = sortedListToBST(keys, values, mid + 1, end); + node.setLeftChild(left); + node.setRightChild(right); + + // color all nodes black and only the leaves red + if (left == null && right == null) { + node.setRed(); + node.setSize(0); + } else { + // update sizes + node.setSize(Math.max((left != null) ? left.getSize() : 0, right != null ? right.getSize() : 0) + 1); + } + + return node; + } + + /** * Returns the value associated with the given key * diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java index d2c581e9eef..105b77e7fbb 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java @@ -3,6 +3,9 @@ import org.junit.Before; import org.junit.Test; +import java.util.LinkedList; +import java.util.List; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -11,72 +14,85 @@ */ public class RedBlackTreeTest { - private RedBlackTree redBlackTree = new RedBlackTree<>(); + private RedBlackTree redBlackTree = new RedBlackTree<>(); + + @Before + public void setUp() { + redBlackTree.insert(13, 13); + redBlackTree.insert(8, 8); + redBlackTree.insert(17, 17); + redBlackTree.insert(1, 1); + redBlackTree.insert(11, 11); + redBlackTree.insert(15, 15); + redBlackTree.insert(25, 25); + redBlackTree.insert(6, 6); + redBlackTree.insert(22, 22); + redBlackTree.insert(27, 27); + } - @Before - public void setUp() { - redBlackTree.insert(13, 13); - redBlackTree.insert(8, 8); - redBlackTree.insert(17, 17); - redBlackTree.insert(1, 1); - redBlackTree.insert(11, 11); - redBlackTree.insert(15, 15); - redBlackTree.insert(25, 25); - redBlackTree.insert(6, 6); - redBlackTree.insert(22, 22); - redBlackTree.insert(27, 27); - } + /** + * The root is black + */ + @Test + public void testBlackRoot() { + assertFalse(redBlackTree.getRoot().isRed()); + } - /** - * The root is black - */ - @Test - public void testBlackRoot() { - assertFalse(redBlackTree.getRoot().isRed()); - } + /** + * If a node is red, then both its children are black + */ + @Test + public void testBlackChildren() { + testBlackChildren(redBlackTree.getRoot()); + } - /** - * If a node is red, then both its children are black - */ - @Test - public void testBlackChildren() { - testBlackChildren(redBlackTree.getRoot()); - } + private void testBlackChildren(Node currentNode) { + Node leftChild = currentNode.getLeftChild(); + if (leftChild != null) { + if (currentNode.isRed()) { + assertFalse(leftChild.isRed()); + } + testBlackChildren(leftChild); + } - private void testBlackChildren(Node currentNode) { - Node leftChild = currentNode.getLeftChild(); - if (leftChild != null) { - if (currentNode.isRed()) { - assertFalse(leftChild.isRed()); - } - testBlackChildren(leftChild); + Node rightChild = currentNode.getRightChild(); + if (rightChild != null) { + if (currentNode.isRed()) { + assertFalse(rightChild.isRed()); + } + testBlackChildren(rightChild); + } } - Node rightChild = currentNode.getRightChild(); - if (rightChild != null) { - if (currentNode.isRed()) { - assertFalse(rightChild.isRed()); - } - testBlackChildren(rightChild); + /** + * Every path from a given node to any of its descendant leaves contains the same number of black nodes + */ + @Test + public void testBlackNodeNumber() { + assertEquals(countLeftChildren(redBlackTree.getRoot(), 0), countRightChildren(redBlackTree.getRoot(), 0)); } - } - /** - * Every path from a given node to any of its descendant leaves contains the same number of black nodes - */ - @Test - public void testBlackNodeNumber() { - assertEquals(countLeftChildren(redBlackTree.getRoot(), 0), countRightChildren(redBlackTree.getRoot(), 0)); - } + private int countLeftChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); + } - private int countLeftChildren(Node node, int currentBlackNumber) { - currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; - return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); - } + private int countRightChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); + } - private int countRightChildren(Node node, int currentBlackNumber) { - currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; - return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); - } + @Test + public void testListConstructor() { + List keyList = new LinkedList<>(); + for (int i = 0; i < 20; i++) { + keyList.add(i); + } + RedBlackTree tree = new RedBlackTree<>(keyList, keyList); + List result = tree.inorderValues(); + for (int i = 0; i < 20; i++) { + assertEquals(i, (int) result.get(i)); + } + } } From 800eb5b06ad0aa96203947a49fc441ad6983ae08 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 May 2018 15:05:01 +0200 Subject: [PATCH 065/131] added initialization of graph with given vertices, edge construction has to be done, however. --- .../graph/specifics/IntervalSpecifics.java | 25 ++++++++- .../jgrapht/intervalgraph/IntervalGraph.java | 55 ++++++++++++++----- .../IntervalGraphVertexContainer.java | 18 ++++++ .../intervalgraph/IntervalTreeStructure.java | 20 ++++++- .../intervalgraph/RedBlackIntervalTree.java | 11 +++- .../jgrapht/intervalgraph/RedBlackTree.java | 29 +++------- .../RedBlackIntervalTreeStructureTest.java | 2 +- .../intervalgraph/RedBlackTreeTest.java | 5 +- 8 files changed, 121 insertions(+), 44 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index 01e235b2838..7a96b1f67be 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -8,6 +8,7 @@ import org.jgrapht.util.ArrayUnenforcedSet; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -21,11 +22,11 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class IntervalSpecifics implements Specifics, Serializable { +public class IntervalSpecifics, E, T extends Comparable> implements Specifics, Serializable { private static final long serialVersionUID = 1112673663745687843L; - private IntervalGraph intervalGraph; + private IntervalGraph intervalGraph; private IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; private EdgeSetFactory edgeSetFactory; @@ -34,12 +35,30 @@ public class IntervalSpecifics implements * * @param intervalGraph the graph for which these specifics are for */ - public IntervalSpecifics(IntervalGraph intervalGraph) { + public IntervalSpecifics(IntervalGraph intervalGraph) { this.intervalGraph = intervalGraph; this.intervalGraphVertexContainerInterface = new IntervalGraphVertexContainer<>(); this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); } + /** + * Constructs new interval specifics. + * + * @param intervalGraph the graph for which these specifics are for + */ + public IntervalSpecifics(IntervalGraph intervalGraph, ArrayList vertices) { + + this.intervalGraph = intervalGraph; + this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); + + ArrayList> undirectedEdgeContainers = new ArrayList<>(vertices.size()); + for(int i = 0; i < vertices.size(); ++i) { + undirectedEdgeContainers.add(i, new UndirectedEdgeContainer<>(edgeSetFactory, vertices.get(i))); + } + + this.intervalGraphVertexContainerInterface = new IntervalGraphVertexContainer<>(vertices, undirectedEdgeContainers); + } + /** * {@inheritDoc} */ diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 55484946bad..962116ae9f2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -21,7 +21,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { +public class IntervalGraph, E, T extends Comparable> extends AbstractGraph implements Graph, Cloneable, Serializable { private static final long serialVersionUID = 7835287075273098344L; @@ -31,7 +31,7 @@ public class IntervalGraph extends Abstrac private EdgeFactory edgeFactory; private transient Set unmodifiableVertexSet = null; - private IntervalSpecifics specifics; + private IntervalSpecifics specifics; private IntrusiveEdgesSpecifics intrusiveEdgesSpecifics; private boolean directed; @@ -84,23 +84,41 @@ protected IntervalGraph( * null. */ protected IntervalGraph( - List vertices, EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, + ArrayList vertices, EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, boolean weighted) { + Objects.requireNonNull(ef); + boolean isSorted = true; + V current = vertices.get(0); + for (int i = 1; i < vertices.size(); i++) { + V next = vertices.get(i); + if (current.getInterval().compareTo(next.getInterval()) > 0) { + isSorted = false; + break; + } + current = next; + } + this.edgeFactory = ef; this.allowingLoops = allowLoops; this.allowingMultipleEdges = allowMultipleEdges; this.directed = directed; - this.specifics = - Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + this.weighted = weighted; this.intrusiveEdgesSpecifics = Objects.requireNonNull( createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); - for(V vertex : vertices) { - this.addVertex(vertex); + if(isSorted) { + this.specifics = Objects.requireNonNull(createSpecifics(directed, vertices), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + //TODO add edges + } else { + this.specifics = Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + + for (V vertex : vertices) { + this.addVertex(vertex); + } } } @@ -245,7 +263,7 @@ public V getEdgeTarget(E e) public Object clone() { try { - IntervalGraph newGraph = TypeUtil.uncheckedCast(super.clone()); + IntervalGraph newGraph = TypeUtil.uncheckedCast(super.clone()); newGraph.edgeFactory = this.edgeFactory; newGraph.unmodifiableVertexSet = null; @@ -459,19 +477,29 @@ public GraphType getType() * otherwise undirected * @return the specifics used by this graph */ - protected IntervalSpecifics createSpecifics(boolean directed) - { + protected IntervalSpecifics createSpecifics(boolean directed) { return new IntervalSpecifics<>(this); } + /** + * Create the specifics for this graph. Subclasses can override this method in order to adjust + * the specifics and thus the space-time tradeoffs of the graph implementation. + * + * @param directed if true the specifics should adjust the behavior to a directed graph + * otherwise undirected + * @return the specifics used by this graph + */ + protected IntervalSpecifics createSpecifics(boolean directed, ArrayList vertices) { + return new IntervalSpecifics<>(this, vertices); + } + /** * Create the specifics for the edges set of the graph. * * @param weighted if true the specifics should support weighted edges * @return the specifics used for the edge set of this graph */ - protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) - { + protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) { if (weighted) { return new WeightedIntrusiveEdgesSpecifics<>(); } else { @@ -480,8 +508,7 @@ protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean we } /** - * Adds edges between sourceVertex and every vertex from vertices - * This method should only be called from IntervalSpecifics, because interval graphs have by intervals defined edges. + * Adds edges between sourceVertex and every vertex from vertices. * * @param sourceVertex source vertex of all edges * @param targetVertices target vertices of edges diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 24456133438..ddbbb56bd86 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -43,6 +43,24 @@ public IntervalGraphVertexContainer() { this.intervalMap = new LinkedHashMap<>(); } + /** + * Constructs a vertex container for an interval graph with all necessary objects. + */ + public IntervalGraphVertexContainer(ArrayList vertices, ArrayList> undirectedEdgeContainers) { + this.vertexMap = new LinkedHashMap<>(); + this.intervalMap = new LinkedHashMap<>(); + + ArrayList> intervals = new ArrayList<>(vertices.size()); + + for(int i = 0; i < vertices.size(); ++i) { + intervals.add(i, vertices.get(i).getInterval()); + intervalMap.put(vertices.get(i).getInterval(), vertices.get(i)); + vertexMap.put(vertices.get(i), undirectedEdgeContainers.get(i)); + } + + this.intervalStructure = new IntervalTreeStructure<>(intervals); + } + /** * Returns the whole vertex set of the graph. * diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index 6c1f829586e..42f8be9539f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -3,6 +3,8 @@ import org.jgrapht.intervalgraph.interval.Interval; import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -19,7 +21,23 @@ public class IntervalTreeStructure> implements IntervalS private static final long serialVersionUID = 2834567756342332325L; - private IntervalTreeInterface>, IntervalTreeNodeValue, T>> tree = new RedBlackIntervalTree<>(); + private IntervalTreeInterface>, IntervalTreeNodeValue, T>> tree; + + public IntervalTreeStructure() { + this.tree = new RedBlackIntervalTree<>(); + } + + public IntervalTreeStructure(ArrayList> intervals) { + ArrayList>> keys = new ArrayList<>(intervals.size()); + ArrayList, T>> values = new ArrayList<>(intervals.size()); + + for(int i = 0; i < intervals.size(); ++i) { + keys.add(i, new IntervalTreeNodeKey<>(intervals.get(i), getComparator())); + values.add(i, new IntervalTreeNodeValue<>(intervals.get(i))); + } + + this.tree = new RedBlackIntervalTree<>(keys, values); + } /** * Returns all intervals that overlap with the given interval diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index aeeafde97c9..714e443c111 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -3,6 +3,7 @@ import org.jgrapht.intervalgraph.interval.Interval; import java.io.Serializable; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -19,10 +20,18 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class RedBlackIntervalTree, K extends Comparable, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface, Serializable { +public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>, T extends Comparable> extends RedBlackTree implements IntervalTreeInterface, Serializable { private static final long serialVersionUID = 4353687394654923429L; + public RedBlackIntervalTree() { + super(); + } + + public RedBlackIntervalTree(ArrayList keys, ArrayList values) { + super(keys, values); + } + @Override public List> overlapsWith(Interval interval) { List> result = new LinkedList<>(); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index e7577bd35b0..1742c6cadee 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -23,8 +23,7 @@ public Node getRoot() { return root; } - public RedBlackTree() { - } + public RedBlackTree() {} /** @@ -34,9 +33,7 @@ public RedBlackTree() { * @param keys * @param values */ - public RedBlackTree(List keys, List values) { - ArrayList keyList; - ArrayList valueList; + public RedBlackTree(ArrayList keys, ArrayList values) { int length = keys.size(); // exceptions @@ -47,36 +44,24 @@ public RedBlackTree(List keys, List values) { return; } - // transform to ArrayList for good performance - if (keys instanceof ArrayList) { - keyList = (ArrayList) keys; - } else { - keyList = new ArrayList<>(keys); - } - - if (values instanceof ArrayList) { - valueList = (ArrayList) values; - } else { - valueList = new ArrayList<>(values); - } - // check if list is sorted to use efficient insertion boolean isSorted = true; - K current = keyList.get(0); + K current = keys.get(0); for (int i = 1; i < length; i++) { - K next = keyList.get(i); + K next = keys.get(i); if (current.compareTo(next) > 0) { isSorted = false; break; } + current = next; } // use optimized insert if input is sorted, otherwise trivial insertion if (isSorted) { - root = sortedListToBST(keyList, valueList, 0, length - 1); + root = sortedListToBST(keys, values, 0, length - 1); } else { for (int i = 0; i < length; i++) { - this.insert(keyList.get(i), valueList.get(i)); + this.insert(keys.get(i), values.get(i)); } } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index fa13b91d1aa..e0cdde85997 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -14,7 +14,7 @@ public class RedBlackIntervalTreeStructureTest { List> sorted = new LinkedList<>(); - RedBlackIntervalTree>, IntervalTreeNodeValue, Integer>> tree = new RedBlackIntervalTree<>(); + RedBlackIntervalTree>, IntervalTreeNodeValue, Integer>, Integer> tree = new RedBlackIntervalTree<>(); @Before public void setUp() throws Exception { diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java index 105b77e7fbb..8d6416cf715 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java @@ -3,6 +3,7 @@ import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -84,9 +85,9 @@ private int countRightChildren(Node node, int currentBlackNumber) { @Test public void testListConstructor() { - List keyList = new LinkedList<>(); + ArrayList keyList = new ArrayList<>(20); for (int i = 0; i < 20; i++) { - keyList.add(i); + keyList.add(i, i); } RedBlackTree tree = new RedBlackTree<>(keyList, keyList); From c63d472b9e4a170eb30beb526a83afc4d7ec9dc6 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Thu, 3 May 2018 18:02:50 +0200 Subject: [PATCH 066/131] Change isIOrdering to use an array list instead of a hash map --- .../jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 3a9e1b5239a..7410f829f7e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -57,8 +57,6 @@ public IntervalGraphRecognizer(Graph graph) /** * check if the graph is an interval graph * - * @param the generic type representing vertices - * @param the generic type representing edges * @return */ public boolean isIntervalGraph(Graph graph) @@ -176,11 +174,11 @@ public boolean isIntervalGraph(Graph graph) private static boolean isIOrdering(HashMap sweep, Graph graph) { // Compute inverse sweep map to quickly find vertices at given indices - HashMap inverseSweep = new HashMap<>(); + ArrayList inverseSweep = new ArrayList<>(graph.vertexSet().size()); for (V vertex : graph.vertexSet()) { int index = sweep.get(vertex); - inverseSweep.put(index, vertex); + inverseSweep.set(index, vertex); } // Compute maximal neighbors w.r.t. sweep ordering for every vertex From 976750c77d79a742fa142470279a52cd9b226528 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 May 2018 18:53:07 +0200 Subject: [PATCH 067/131] finished first version of asIntervalGraph starring the longest generics fight in my life --- .../graph/specifics/IntervalSpecifics.java | 8 +- .../jgrapht/intervalgraph/IntervalGraph.java | 96 +++++++++++++++++-- .../IntervalGraphVertexContainer.java | 2 +- 3 files changed, 95 insertions(+), 11 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index 7a96b1f67be..38892329c05 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -22,11 +22,11 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class IntervalSpecifics, E, T extends Comparable> implements Specifics, Serializable { +public class IntervalSpecifics, E, VertexType, T extends Comparable> implements Specifics, Serializable { private static final long serialVersionUID = 1112673663745687843L; - private IntervalGraph intervalGraph; + private IntervalGraph intervalGraph; private IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; private EdgeSetFactory edgeSetFactory; @@ -35,7 +35,7 @@ public class IntervalSpecifics, E, T ext * * @param intervalGraph the graph for which these specifics are for */ - public IntervalSpecifics(IntervalGraph intervalGraph) { + public IntervalSpecifics(IntervalGraph intervalGraph) { this.intervalGraph = intervalGraph; this.intervalGraphVertexContainerInterface = new IntervalGraphVertexContainer<>(); this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); @@ -46,7 +46,7 @@ public IntervalSpecifics(IntervalGraph intervalGraph) { * * @param intervalGraph the graph for which these specifics are for */ - public IntervalSpecifics(IntervalGraph intervalGraph, ArrayList vertices) { + public IntervalSpecifics(IntervalGraph intervalGraph, ArrayList vertices) { this.intervalGraph = intervalGraph; this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 962116ae9f2..c6785303e14 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -4,8 +4,11 @@ import org.jgrapht.Graph; import org.jgrapht.GraphType; import org.jgrapht.Graphs; +import org.jgrapht.alg.util.Pair; import org.jgrapht.graph.*; import org.jgrapht.graph.specifics.IntervalSpecifics; +import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.intervalgraph.interval.IntervalVertex; import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; import org.jgrapht.util.TypeUtil; @@ -21,7 +24,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class IntervalGraph, E, T extends Comparable> extends AbstractGraph implements Graph, Cloneable, Serializable { +public class IntervalGraph, E, VertexType, T extends Comparable> extends AbstractGraph implements Graph, Cloneable, Serializable { private static final long serialVersionUID = 7835287075273098344L; @@ -31,7 +34,7 @@ public class IntervalGraph, E, T extends private EdgeFactory edgeFactory; private transient Set unmodifiableVertexSet = null; - private IntervalSpecifics specifics; + private IntervalSpecifics specifics; private IntrusiveEdgesSpecifics intrusiveEdgesSpecifics; private boolean directed; @@ -112,7 +115,22 @@ protected IntervalGraph( if(isSorted) { this.specifics = Objects.requireNonNull(createSpecifics(directed, vertices), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); - //TODO add edges + + ArrayList> edges = new ArrayList<>(vertices.size()); + + for(int i = 0; i < vertices.size(); ++i) { + edges.add(i, new LinkedList<>()); + for(int j = 0; j < i; ++j) { + if(vertices.get(j).getInterval().getEnd().compareTo(vertices.get(i).getInterval().getStart()) >= 0) { + edges.get(j).add(vertices.get(i)); + } + } + } + + for(int i = 0; i < vertices.size(); ++i) { + addIntervalEdges(vertices.get(i), edges.get(i)); + } + } else { this.specifics = Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); @@ -122,6 +140,72 @@ protected IntervalGraph( } } + /** + * Construct a new graph with given vertices. The graph can either be directed or undirected, depending on the + * specified edge factory. + * + * @param vertices initial vertices + * @param edges initial edges + * @param ef the edge factory of the new graph. + * @param directed if true the graph will be directed, otherwise undirected + * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. + * @param allowLoops whether to allow edges that are self-loops or not. + * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * + * @throws NullPointerException if the specified edge factory is + * null. + */ + private IntervalGraph(ArrayList vertices, Map, E> edges, EdgeFactory ef, + boolean directed, boolean allowMultipleEdges, boolean allowLoops, boolean weighted) { + + Objects.requireNonNull(ef); + + this.edgeFactory = ef; + this.allowingLoops = allowLoops; + this.allowingMultipleEdges = allowMultipleEdges; + this.directed = directed; + this.specifics = + Objects.requireNonNull(createSpecifics(directed, vertices), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + this.weighted = weighted; + this.intrusiveEdgesSpecifics = Objects.requireNonNull( + createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + + for(Pair v : edges.keySet()) { + addExistingIntervalEdges(v.getFirst(), v.getSecond(), edges.get(v)); + } + } + + private boolean addExistingIntervalEdges(V sourceVertex, V targetVertex, E edge) { + + assertVertexExist(sourceVertex); + assertVertexExist(targetVertex); + + if(intrusiveEdgesSpecifics.add(edge, sourceVertex, targetVertex)) { + specifics.addEdgeToTouchingVertices(edge); + } + + return true; + } + + /** + * returns interval graph representation if one exists, otherwise null + * + * @param graph the graph to check + * @return interval graph representation if one exists, otherwise null + */ + public static , E, VertexType, T extends Comparable> + IntervalGraph asIntervalGraph(Graph graph) { + ArrayList vertices = new ArrayList<>(); + Map, E> edges = new LinkedHashMap<>(); + + // TODO Intervall-Graph-Test ausführen + // TODO hier müssen noch die korrekten datenstrukturen vertices und edges brechnet werden!!! + + return new IntervalGraph<>(vertices, edges, (sourceVertex, targetVertex) -> graph.getEdgeFactory().createEdge(sourceVertex.getVertex(), targetVertex.getVertex()), + graph.getType().isDirected(), graph.getType().isAllowingMultipleEdges(), + graph.getType().isAllowingSelfLoops(), graph.getType().isWeighted()); + } + /** * {@inheritDoc} @@ -263,7 +347,7 @@ public V getEdgeTarget(E e) public Object clone() { try { - IntervalGraph newGraph = TypeUtil.uncheckedCast(super.clone()); + IntervalGraph newGraph = TypeUtil.uncheckedCast(super.clone()); newGraph.edgeFactory = this.edgeFactory; newGraph.unmodifiableVertexSet = null; @@ -477,7 +561,7 @@ public GraphType getType() * otherwise undirected * @return the specifics used by this graph */ - protected IntervalSpecifics createSpecifics(boolean directed) { + protected IntervalSpecifics createSpecifics(boolean directed) { return new IntervalSpecifics<>(this); } @@ -489,7 +573,7 @@ protected IntervalSpecifics createSpecifics(boolean directed) { * otherwise undirected * @return the specifics used by this graph */ - protected IntervalSpecifics createSpecifics(boolean directed, ArrayList vertices) { + protected IntervalSpecifics createSpecifics(boolean directed, ArrayList vertices) { return new IntervalSpecifics<>(this, vertices); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index ddbbb56bd86..74b76c2bb34 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -17,7 +17,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { +public class IntervalGraphVertexContainer, E, VertexType, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { private static final long serialVersionUID = 7768940080894764546L; From f05dc215c8b65f8f760cab1d49423c94b9a33905 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 3 May 2018 19:06:07 +0200 Subject: [PATCH 068/131] Added test class and some changes to treedecomposition for interval graphs --- .../CordalgraphDecomposition.java | 4 +- .../IntervalgraphDecomposition.java | 12 +++-- .../treedecomposition/TreeDecomposition.java | 2 +- .../IntervalgraphDecompositionTest.java | 49 +++++++++++++++++++ 4 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java index fb8be9e8208..764f805aabb 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java @@ -5,8 +5,8 @@ import org.jgrapht.*; import org.jgrapht.graph.*; -public class CordalgraphDecomposition - implements TreeDecomposition +public class CordalgraphDecomposition + implements TreeDecomposition { @Override diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index eab875a34a8..5a960429d28 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -7,20 +7,22 @@ import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; -public class IntervalgraphDecomposition> - implements TreeDecomposition +public class IntervalgraphDecomposition> + implements TreeDecomposition { - private Graph,DefaultEdge> treeDecomposition = null; - private Set currentVertex = null; + private Graph>,DefaultEdge> treeDecomposition = null; + private Set> currentVertex = null; private List> startSort, endSort; public IntervalgraphDecomposition(Graph graph) { + throw new UnsupportedOperationException("Not yet implemented"); //TODO } - public IntervalgraphDecomposition(IntervalGraph,E> graph) + public IntervalgraphDecomposition(IntervalGraphInterface graph) { + throw new UnsupportedOperationException("Not yet implemented"); //TODO } diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java index 0011a3a6e19..62661d0ec52 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java @@ -4,7 +4,7 @@ import org.jgrapht.*; import org.jgrapht.graph.*; -public interface TreeDecomposition +public interface TreeDecomposition { Graph,DefaultEdge> getTreeDecomposition(); } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java new file mode 100644 index 00000000000..972805dc855 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -0,0 +1,49 @@ +package org.jgrapht.alg.treedecompostion; + +import static org.junit.Assert.*; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.treedecomposition.*; +import org.jgrapht.event.*; +import org.jgrapht.graph.*; +import org.jgrapht.intervalgraph.*; +import org.jgrapht.intervalgraph.interval.*; +import org.junit.*; + +public class IntervalgraphDecompositionTest +{ + + @Test + public void testIntervalgraphDecompositionGraphOfVE() + { + Graph g = new DefaultUndirectedGraph<>(DefaultEdge.class); + //TODO: change g + IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(g); + Graph,DefaultEdge> decomp = decompositionAlg.getTreeDecomposition(); + //TODO: test here + assertNotEquals(decomp,decomp); + } + + @Test + public void testIntervalgraphDecompositionIntervalGraphOfIntervalVertexInterfaceOfVTE() + { + IntervalGraphInterface ig = new CenteredIntervalTree<>(); + //TODO: change ig + IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(ig); + } + + @Test + public void testIntervalgraphDecompositionListOfIntervalVertexOfVT() + { + fail("Not yet implemented"); + } + + @Test + public void testGetTreeDecomposition() + { + fail("Not yet implemented"); + } + +} From 3c104be29c7029a069f3ec370a6b1b2fad53d8fe Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 3 May 2018 19:08:36 +0200 Subject: [PATCH 069/131] Merge branch 'intervalGraphs' into intervalAlgoTest --- .../IntervalGraphRecognizer.java | 387 +++++++----- .../graph/specifics/IntervalSpecifics.java | 252 ++++++++ .../intervalgraph/BinarySearchTree.java | 184 ++++++ .../intervalgraph/CenteredIntervalTree.java | 2 +- .../jgrapht/intervalgraph/IntervalGraph.java | 528 ++++++++++++++++- .../intervalgraph/IntervalGraphInterface.java | 14 + .../IntervalGraphVertexContainer.java | 109 ++++ ...IntervalGraphVertexContainerInterface.java | 57 ++ .../IntervalStructureInterface.java | 48 ++ .../intervalgraph/IntervalTreeInterface.java | 36 ++ .../intervalgraph/IntervalTreeNodeValue.java | 89 +++ .../intervalgraph/IntervalTreeStructure.java | 60 ++ .../java/org/jgrapht/intervalgraph/Node.java | 177 ++++++ .../org/jgrapht/intervalgraph/RBNode.java | 146 +++++ .../intervalgraph/RedBlackComparatorTree.java | 534 +++++++++++++++++ .../RedBlackIntervalComparatorTree.java | 170 ++++++ .../intervalgraph/RedBlackIntervalTree.java | 161 +++++ .../jgrapht/intervalgraph/RedBlackTree.java | 551 ++++++++++++++++++ .../intervalgraph/interval/Interval.java | 22 + .../interval/IntervalVertex.java | 90 +++ .../interval/IntervalVertexInterface.java | 29 + .../traverse/LexBreadthFirstIterator.java | 17 + .../CenteredIntervalTreeStructureTest.java | 69 +++ .../IntervalTreeStructureTest.java | 39 ++ .../RedBlackComparatorTreeTest.java | 39 ++ .../RedBlackIntervalComparatorTreeTest.java | 41 ++ .../RedBlackIntervalTreeStructureTest.java | 40 ++ .../intervalgraph/RedBlackTreeTest.java | 82 +++ .../interval/IntervalGraphRecognizerTest.java | 19 +- 29 files changed, 3839 insertions(+), 153 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 941d70ccd6d..7410f829f7e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -8,153 +8,264 @@ import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; -public final class IntervalGraphRecognizer { - - /** - * check if the given graph is an interval graph - * - * @param graph the graph to be checked - * @param the generic type representing vertices - * @param the generic type representing edges - * @return - */ - public static boolean isIntervalGraph(Graph graph) { - - // An empty graph is an interval graph. - if (graph.vertexSet().isEmpty()) { - return true; - } - - // Step 1 - LBFS from an arbitrary vertex - // Input - random vertex r - // Output - the result of current sweep alpha, further last vertex a visited by current sweep - HashMap sweepAlpha = lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); - V vertexA = lastElementOf(sweepAlpha); - - // Step 2 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep alpha, vertex a - // Output - the result of current sweep beta, further last vertex b visited by current sweep - HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, sweepAlpha); - V vertexB = lastElementOf(sweepBeta); - - // Step 3 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep beta, vertex b - // Output - the result of current sweep gamma, further last vertex c visited by current sweep - HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, sweepBeta); - V vertexC = lastElementOf(sweepGamma); - - // Step 4 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep gamma, vertex c - // Output - the result of current sweep delta, further last vertex d visited by current sweep - HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, sweepGamma); - V vertexD = lastElementOf(sweepDelta); - - // Additionally, calculate the index and the corresponding A set for each vertex - - // Step 5 - LBFS+ from the last vertex of the previous sweep - // Input - the result of previous sweep delta, vertex d - // Output - the result of current sweep epsilon, further last vertex e visited by current sweep - HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, sweepDelta); - // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? - - // Additionally, calculate the index and the corresponding B set for each vertex - - // Step 6 - LBFS* with the resulting sweeps - // Input - the result of sweep gamma and sweep epsilon - // Output - the result of current sweep zeta - HashMap sweepZeta = lexBreadthFirstSearchStar(graph, vertexD, sweepDelta, sweepEpsilon); - - // if sweepZeta is umbrella-free, then the graph is interval. - // otherwise, the graph is not interval - //return isIOrdering(sweepZeta, graph); +/** + * A recognizer for interval graphs. + *

+ * An interval graph is a intersection graph of a set of intervals on the line, i.e. they contain a + * vertex for each interval and two vertices are connected if the corresponding intervals have a + * nonempty intersection. + *

+ * The recognizer uses the algorithm described in + * (The LBFS Structure + * and Recognition of Interval Graphs. SIAM J. Discrete Math.. 23. 1905-1953. + * 10.1137/S0895480100373455.) by Derek Corneil, Stephan Olariu and Lorna Stewart based on + * multiple lexicographical breadth-first search (LBFS) sweeps. + *

+ * For this recognizer to work correctly the graph must not be modified during iteration. + *

+ * + * @param the graph vertex type. + * @param the graph edge type. + * @author Team J + * @since April 2018 + */ +public final class IntervalGraphRecognizer +{ + + /** + * Stores whether or not the graph is an interval graph. + */ + private boolean isIntervalGraph; + + /** + * Stores the computed interval graph representation (or null if no such representation + * exists) of the graph. + */ + private Graph intervalRepresentation; // TODO: change to work with an actual interval + // graph after merge + + /** + * Creates (and runs) a new interval graph recognizer for the given graph. + * + * @param graph the graph to be tested. + */ + public IntervalGraphRecognizer(Graph graph) + { + isIntervalGraph(graph); + } + + /** + * check if the graph is an interval graph + * + * @return + */ + public boolean isIntervalGraph(Graph graph) + { + + // An empty graph is an interval graph. + if (graph.vertexSet().isEmpty()) { + return true; + } + + // Step 1 - LBFS from an arbitrary vertex + // Input - random vertex r + // Output - the result of current sweep alpha, further last vertex a visited by current + // sweep + HashMap sweepAlpha = + lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); + V vertexA = lastElementOf(sweepAlpha); + + // Step 2 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep alpha, vertex a + // Output - the result of current sweep beta, further last vertex b visited by current sweep + HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, sweepAlpha); + V vertexB = lastElementOf(sweepBeta); + + // Step 3 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep beta, vertex b + // Output - the result of current sweep gamma, further last vertex c visited by current + // sweep + HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, sweepBeta); + V vertexC = lastElementOf(sweepGamma); + + // Step 4 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep gamma, vertex c + // Output - the result of current sweep delta, further last vertex d visited by current + // sweep + HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, sweepGamma); + V vertexD = lastElementOf(sweepDelta); + + // Additionally, calculate the index and the corresponding A set for each vertex + + // Step 5 - LBFS+ from the last vertex of the previous sweep + // Input - the result of previous sweep delta, vertex d + // Output - the result of current sweep epsilon, further last vertex e visited by current + // sweep + HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, sweepDelta); + // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? + + // Additionally, calculate the index and the corresponding B set for each vertex + + // Step 6 - LBFS* with the resulting sweeps + // Input - the result of sweep gamma and sweep epsilon + // Output - the result of current sweep zeta + HashMap sweepZeta = + lexBreadthFirstSearchStar(graph, vertexD, sweepDelta, sweepEpsilon); + + // if sweepZeta is umbrella-free, then the graph is interval. + // otherwise, the graph is not interval + + if (isIOrdering(sweepZeta, graph)) { + this.isIntervalGraph = true; + + // Compute interval representation -- TODO: complete after merge + HashMap neighborIndex = new HashMap<>(); + for (V vertex : graph.vertexSet()) { + int maxNeighbor = 0; + + List neighbors = Graphs.neighborListOf(graph, vertex); + neighbors.add(vertex); + + for (V neighbor : neighbors) { + maxNeighbor = Math.max(maxNeighbor, sweepZeta.get(neighbor)); + } + + neighborIndex.put(vertex, maxNeighbor); + } + + HashMap> intervals = new HashMap<>(graph.vertexSet().size()); + ArrayList> sortedIntervals = + new ArrayList<>(graph.vertexSet().size()); + + // Compute intervals and store them associated by their starting point ... + for (V vertex : graph.vertexSet()) { + Interval vertexInterval = + new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); + + intervals.put(sweepZeta.get(vertex), vertexInterval); + } + + // ... and produce a list sorted by the starting points for an efficient construction of + // the graph + for (int i = 0; i < graph.vertexSet().size(); i++) { + sortedIntervals.add(intervals.get(i)); + } + + // TODO: build the actual interval graph + this.intervalRepresentation = null; + } else { + // set values negatively + this.isIntervalGraph = false; + this.intervalRepresentation = null; + } + + return isIOrdering(sweepZeta, graph); + } - // Compute interval representation -- TODO: complete after merge - HashMap neighborIndex = new HashMap<>(); - for(V vertex : graph.vertexSet()) { - int maxNeighbor = 0; + /** + * Calculates if the given sweep is an I-Ordering (according to the Graph graph) in linear time. + * + * @param + * + * @param sweep the order we want to check if its an I-Order + * @param graph the graph we want to check if its an I-Order + * @return true, if sweep is an I-Order according to graph + */ + private static boolean isIOrdering(HashMap sweep, Graph graph) + { + // Compute inverse sweep map to quickly find vertices at given indices + ArrayList inverseSweep = new ArrayList<>(graph.vertexSet().size()); + + for (V vertex : graph.vertexSet()) { + int index = sweep.get(vertex); + inverseSweep.set(index, vertex); + } - List neighbors = Graphs.neighborListOf(graph, vertex); - neighbors.add(vertex); + // Compute maximal neighbors w.r.t. sweep ordering for every vertex + HashMap maxNeighbors = new HashMap<>(graph.vertexSet().size()); - for(V neighbor : neighbors) { - maxNeighbor = Math.max(maxNeighbor, sweepZeta.get(neighbor)); + for(V vertex : graph.vertexSet()) { + List neighbors = Graphs.neighborListOf(graph, vertex); + V maxNeighbor = vertex; + + for(V neighbor : neighbors) { + if(sweep.get(neighbor) > sweep.get(maxNeighbor)) { + maxNeighbor = neighbor; + } + } + + maxNeighbors.put(vertex, maxNeighbor); } - neighborIndex.put(vertex, maxNeighbor); + // Check if every vertex is connected to all vertices between itself and its maximal neighbor + for(V vertex : graph.vertexSet()) { + int index = sweep.get(vertex); + int maxIndex = sweep.get(maxNeighbors.get(vertex)); + + for(int i = index; i < maxIndex; i++) { + if(!graph.containsEdge(vertex, inverseSweep.get(i))) { + // Found missing edge + return false; + } + } + } + + // No missing edge found + return true; } - ArrayList> intervals = new ArrayList<>(graph.vertexSet().size()); - - for(V vertex : graph.vertexSet()) { - Interval vertexInterval = new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); - intervals.add(vertexInterval); + + /** + * return the last element of the given map + * + * @param map + * @param the generic type representing vertices + * @return + */ + private static V lastElementOf(HashMap map) + { + return Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey(); } - - return isIOrdering(sweepZeta, graph); - } - - /** - * Calculates if the given sweep is an I-Ordering - * (according to the Graph graph) - * @param - * - * @param sweep the order we want to check if its an I-Order - * @param graph the graph we want to check if its an I-Order - * @return true, if sweep is an I-Order according to graph - */ - private static boolean isIOrdering(HashMap sweep, Graph graph) { - HashMap last = new HashMap<>(); - HashMap inverseSweep = new HashMap<>(); - - for(V vertex : graph.vertexSet()) { - int index = sweep.get(vertex); - inverseSweep.put(index, vertex); - } - - for (int i=0; i the generic type representing vertices - * @return - */ - private static V lastElementOf(HashMap map) { - return Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey(); - } - - /** - * return a random element of the given set - * - * @param set - * @param the generic type representing vertices - * @return - */ - private static V randomElementOf(Set set) { - if (set == null) { - throw new IllegalArgumentException("List parameter cannot be null."); + + /** + * return a random element of the given set + * + * @param set + * @param the generic type representing vertices + * @return + */ + private static V randomElementOf(Set set) + { + if (set == null) { + throw new IllegalArgumentException("Set parameter cannot be null."); + } + + int index = new Random().nextInt(set.size()); + Iterator iterator = set.iterator(); + for (int i = 0; i < index; i++) { + iterator.next(); + } + return iterator.next(); + } + + /** + * Returns whether or not the graph is an interval graph. + * + * @return true if the graph is an interval graph, otherwise false. + */ + public boolean isIntervalGraph() + { + return isIntervalGraph; } - int index = new Random().nextInt(set.size()); - Iterator iterator = set.iterator(); - for (int i = 0; i < index; i++) { - iterator.next(); + /** + * Returns an interval graph representation of the graph. + * + * @return an interval graph representation of the graph or null if the graph is not an + * interval graph. + */ + public Graph getIntervalGraphRepresentation() + { + return intervalRepresentation; } - return iterator.next(); - } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java new file mode 100644 index 00000000000..01e235b2838 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -0,0 +1,252 @@ +package org.jgrapht.graph.specifics; + +import org.jgrapht.graph.EdgeSetFactory; +import org.jgrapht.intervalgraph.IntervalGraph; +import org.jgrapht.intervalgraph.IntervalGraphVertexContainerInterface; +import org.jgrapht.intervalgraph.IntervalGraphVertexContainer; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; +import org.jgrapht.util.ArrayUnenforcedSet; + +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +/** + * Implementation of IntervalSpecifics. + * This class implements necessary methods for IntervalGraph. + * + * @param the vertex type + * @param the edge type + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public class IntervalSpecifics implements Specifics, Serializable { + + private static final long serialVersionUID = 1112673663745687843L; + + private IntervalGraph intervalGraph; + private IntervalGraphVertexContainerInterface intervalGraphVertexContainerInterface; + private EdgeSetFactory edgeSetFactory; + + /** + * Constructs new interval specifics. + * + * @param intervalGraph the graph for which these specifics are for + */ + public IntervalSpecifics(IntervalGraph intervalGraph) { + this.intervalGraph = intervalGraph; + this.intervalGraphVertexContainerInterface = new IntervalGraphVertexContainer<>(); + this.edgeSetFactory = new ArrayUnenforcedSetEdgeSetFactory<>(); + } + + /** + * {@inheritDoc} + */ + @Override + public void addVertex(V vertex) + { + getEdgeContainer(vertex); + } + + /** + * + */ + public List getOverlappingIntervalVertices(V vertex) { + return intervalGraphVertexContainerInterface.getOverlappingIntervalVertices(vertex); + } + + /** + * + */ + public void removeVertex(V v) { + intervalGraphVertexContainerInterface.remove(v); + } + + /** + * {@inheritDoc} + */ + @Override + public Set getVertexSet() + { + return intervalGraphVertexContainerInterface.getVertexSet(); + } + + /** + * {@inheritDoc} + */ + @Override + public Set getAllEdges(V sourceVertex, V targetVertex) + { + Set edges = null; + + if (intervalGraph.containsVertex(sourceVertex) + && intervalGraph.containsVertex(targetVertex)) + { + edges = new ArrayUnenforcedSet<>(); + + for (E e : getEdgeContainer(sourceVertex).vertexEdges) { + boolean equal = isEqualsStraightOrInverted(sourceVertex, targetVertex, e); + + if (equal) { + edges.add(e); + } + } + } + + return edges; + } + + /** + * {@inheritDoc} + */ + @Override + public E getEdge(V sourceVertex, V targetVertex) + { + if (intervalGraph.containsVertex(sourceVertex) + && intervalGraph.containsVertex(targetVertex)) + { + + for (E e : getEdgeContainer(sourceVertex).vertexEdges) { + boolean equal = isEqualsStraightOrInverted(sourceVertex, targetVertex, e); + + if (equal) { + return e; + } + } + } + + return null; + } + + private boolean isEqualsStraightOrInverted(Object sourceVertex, Object targetVertex, E e) + { + boolean equalStraight = sourceVertex.equals(intervalGraph.getEdgeSource(e)) + && targetVertex.equals(intervalGraph.getEdgeTarget(e)); + + boolean equalInverted = sourceVertex.equals(intervalGraph.getEdgeTarget(e)) + && targetVertex.equals(intervalGraph.getEdgeSource(e)); + return equalStraight || equalInverted; + } + + /** + * {@inheritDoc} + */ + @Override + public void addEdgeToTouchingVertices(E e) + { + V source = intervalGraph.getEdgeSource(e); + V target = intervalGraph.getEdgeTarget(e); + + getEdgeContainer(source).addEdge(e); + + if (!source.equals(target)) { + getEdgeContainer(target).addEdge(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public int degreeOf(V vertex) + { + if (intervalGraph.isAllowingLoops()) { // then we must count, and add loops twice + int degree = 0; + Set edges = getEdgeContainer(vertex).vertexEdges; + + for (E e : edges) { + if (intervalGraph.getEdgeSource(e).equals(intervalGraph.getEdgeTarget(e))) { + degree += 2; + } else { + degree += 1; + } + } + + return degree; + } else { + return getEdgeContainer(vertex).edgeCount(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public Set edgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * {@inheritDoc} + */ + @Override + public int inDegreeOf(V vertex) + { + return degreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set incomingEdgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * {@inheritDoc} + */ + @Override + public int outDegreeOf(V vertex) + { + return degreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set outgoingEdgesOf(V vertex) + { + return getEdgeContainer(vertex).getUnmodifiableVertexEdges(); + } + + /** + * {@inheritDoc} + */ + @Override + public void removeEdgeFromTouchingVertices(E e) + { + V source = intervalGraph.getEdgeSource(e); + V target = intervalGraph.getEdgeTarget(e); + + getEdgeContainer(source).removeEdge(e); + + if (!source.equals(target)) { + getEdgeContainer(target).removeEdge(e); + } + } + + /** + * Get the edge container for a specified vertex. + * + * @param vertex a vertex in this graph + * + * @return an edge container + */ + protected UndirectedEdgeContainer getEdgeContainer(V vertex) + { + UndirectedEdgeContainer ec = intervalGraphVertexContainerInterface.get(vertex); + + if (ec == null) { + ec = new UndirectedEdgeContainer<>(edgeSetFactory, vertex); + intervalGraphVertexContainerInterface.put(vertex, ec); + } + + return ec; + } + +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java new file mode 100644 index 00000000000..db0b01d6f64 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -0,0 +1,184 @@ +package org.jgrapht.intervalgraph; + +import java.util.NoSuchElementException; + +/** + * Interface for Binary Search Trees + * + * @param the key + * @param the value + * + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ +public interface BinarySearchTree { + + /******************************************************************************************************************* + * Search Operations * + ******************************************************************************************************************/ + + /** + * Returns the value associated with the given key + * + * @param key the key + * @return the value associated with the given key. If the key is not in the tree, null is returned. + * @throws IllegalArgumentException if key is null + */ + V get(K key); + + /** + * Returns whether a key is contained in the tree + * + * @param key the key + * @return true if tree contains key, false otherwise + * @throws IllegalArgumentException if key is null + */ + boolean contains(K key); + + + /******************************************************************************************************************* + * Insertion Operations * + ******************************************************************************************************************/ + + /** + * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * it overwrites the old value with the new. + * + * @param key the key + * @param val the value + * @throws IllegalArgumentException if key is null + */ + void insert(K key, V val); + + + /******************************************************************************************************************* + * Deletion Operations * + ******************************************************************************************************************/ + + /** + * Removes the specified key and its associated value from this tree + * + * @param key the key + * @throws IllegalArgumentException if key is null + */ + void delete(K key); + + /** + * Removes the smallest key and associated value from the tree. + * @throws NoSuchElementException if the tree is empty + */ + void deleteMin(); + + /** + * Removes the largest key and associated value from the tree. + * @throws NoSuchElementException if the tree is empty + */ + void deleteMax(); + + + /******************************************************************************************************************* + * Utility Operations * + ******************************************************************************************************************/ + + /** + * Returns the height of the BST. + * @return the height of the BST (a tree with 1 node has height 0) + */ + int height(); + + + /******************************************************************************************************************* + * Special Search Operations * + ******************************************************************************************************************/ + + /** + * Returns the smallest key in the tree. + * @return the smallest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + K min(); + /** + * Returns the largest key in the tree. + * @return the largest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + K max(); + + /** + * Returns the largest key in the tree less than or equal to key. + * + * @param key the key + * @return the largest key in the tree less than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + K floor(K key); + + /** + * Returns the smallest key in the tree greater than or equal to key. + * + * @param key the key + * @return the smallest key in the tree greater than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + K ceiling(K key); + + /** + * Return the key in the tree whose rank is k. + * This is the (k+1)st smallest key in the tree. + * + * @param k the position + * @return the key in the tree of rank k + * @throws IllegalArgumentException if k not in {0, ..., n-1} + */ + K select(int k); + + /** + * Return the number of keys in the tree strictly less than key. + * + * @param key the key + * @return the number of keys in the tree strictly less than key + * @throws IllegalArgumentException if key is null + */ + int rank(K key); + + + /******************************************************************************************************************* + * Range Search Operations * + ******************************************************************************************************************/ + + /** + * Returns all keys in the symbol table as an Iterable. + * To iterate over all of the keys in the symbol table named st, + * use the foreach notation: for (Key key : st.keys()). + * + * @return all keys in the symbol table as an Iterable + */ + Iterable keys(); + + /** + * Returns all keys in the symbol table in the given range, + * as an Iterable. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return all keys in the sybol table between min + * (inclusive) and max (inclusive) as an Iterable + * @throws IllegalArgumentException if either min or max + * is null + */ + Iterable keys(K min, K max); + + /** + * Returns the number of keys in the symbol table in the given range. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return the number of keys in the sybol table between min + * (inclusive) and max (inclusive) + * @throws IllegalArgumentException if either min or max + * is null + */ + int size(K min, K max); +} \ No newline at end of file diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java index fa05eb8f83a..cd7cfc62975 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -6,7 +6,7 @@ import org.jgrapht.Graph; import org.jgrapht.intervalgraph.interval.Interval; -public class CenteredIntervalTree> implements IntervalGraph{ +public class CenteredIntervalTree> implements IntervalGraphInterface { private T centerPoint; private CenteredIntervalTree leftTree; // contains all the intervals *completely* to the left of the center point private CenteredIntervalTree rightTree; // contains all the intervals *completely* to the right of the center point diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 6accde1abb8..55484946bad 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -1,14 +1,528 @@ package org.jgrapht.intervalgraph; -import java.util.Collection; - +import org.jgrapht.EdgeFactory; import org.jgrapht.Graph; -import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.GraphType; +import org.jgrapht.Graphs; +import org.jgrapht.graph.*; +import org.jgrapht.graph.specifics.IntervalSpecifics; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; +import org.jgrapht.util.TypeUtil; + +import java.io.Serializable; +import java.util.*; + +/** + * Implementation of an Interval Graph + * + * @param the vertex type + * @param the edge type + * + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ +public class IntervalGraph extends AbstractGraph implements Graph, Cloneable, Serializable { + + private static final long serialVersionUID = 7835287075273098344L; + + private static final String INTERVAL_GRAPH_ADD_EDGE = "Intervals of nodes define edges in interval graphs and cannot be modified manually"; + private static final String GRAPH_SPECIFICS_MUST_NOT_BE_NULL = "Graph specifics must not be null"; + + private EdgeFactory edgeFactory; + private transient Set unmodifiableVertexSet = null; + + private IntervalSpecifics specifics; + private IntrusiveEdgesSpecifics intrusiveEdgesSpecifics; + + private boolean directed; + private boolean weighted; + private boolean allowingMultipleEdges; + private boolean allowingLoops; + + /** + * Construct a new graph. The graph can either be directed or undirected, depending on the + * specified edge factory. + * + * @param ef the edge factory of the new graph. + * @param directed if true the graph will be directed, otherwise undirected + * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. + * @param allowLoops whether to allow edges that are self-loops or not. + * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * + * @throws NullPointerException if the specified edge factory is + * null. + */ + protected IntervalGraph( + EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, + boolean weighted) + { + Objects.requireNonNull(ef); + + this.edgeFactory = ef; + this.allowingLoops = allowLoops; + this.allowingMultipleEdges = allowMultipleEdges; + this.directed = directed; + this.specifics = + Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + this.weighted = weighted; + this.intrusiveEdgesSpecifics = Objects.requireNonNull( + createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + } + + /** + * Construct a new graph with given vertices. The graph can either be directed or undirected, depending on the + * specified edge factory. + * + * @param vertices initial vertices + * @param ef the edge factory of the new graph. + * @param directed if true the graph will be directed, otherwise undirected + * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. + * @param allowLoops whether to allow edges that are self-loops or not. + * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute + * + * @throws NullPointerException if the specified edge factory is + * null. + */ + protected IntervalGraph( + List vertices, EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, + boolean weighted) + { + Objects.requireNonNull(ef); + + this.edgeFactory = ef; + this.allowingLoops = allowLoops; + this.allowingMultipleEdges = allowMultipleEdges; + this.directed = directed; + this.specifics = + Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + this.weighted = weighted; + this.intrusiveEdgesSpecifics = Objects.requireNonNull( + createIntrusiveEdgesSpecifics(weighted), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); + + for(V vertex : vertices) { + this.addVertex(vertex); + } + } + + + /** + * {@inheritDoc} + */ + @Override + public Set getAllEdges(V sourceVertex, V targetVertex) + { + return specifics.getAllEdges(sourceVertex, targetVertex); + } + + /** + * Returns true if and only if self-loops are allowed in this graph. A self loop is + * an edge that its source and target vertices are the same. + * + * @return true if and only if graph loops are allowed. + */ + public boolean isAllowingLoops() + { + return allowingLoops; + } + + /** + * Returns true if and only if multiple (parallel) edges are allowed in this graph. The + * meaning of multiple edges is that there can be many edges going from vertex v1 to vertex v2. + * + * @return true if and only if multiple (parallel) edges are allowed. + */ + public boolean isAllowingMultipleEdges() + { + return allowingMultipleEdges; + } + + /** + * Returns true if and only if the graph supports edge weights. + * + * @return true if the graph supports edge weights, false otherwise. + */ + public boolean isWeighted() + { + return weighted; + } + + /** + * Returns true if the graph is directed, false if undirected. + * + * @return true if the graph is directed, false if undirected. + */ + public boolean isDirected() + { + return directed; + } + + /** + * {@inheritDoc} + */ + @Override + public E getEdge(V sourceVertex, V targetVertex) + { + return specifics.getEdge(sourceVertex, targetVertex); + } + + /** + * {@inheritDoc} + */ + @Override + public EdgeFactory getEdgeFactory() + { + return edgeFactory; + } + + /** + * This method an IllegalArgumentException in every case because you can not add edges to an interval graph manually. + * + * {@inheritDoc} + */ + @Override + public E addEdge(V sourceVertex, V targetVertex) + { + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + } + + /** + * This method an IllegalArgumentException in every case because you can not add edges to an interval graph manually. + * + * {@inheritDoc} + */ + @Override + public boolean addEdge(V sourceVertex, V targetVertex, E e) + { + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean addVertex(V v) + { + if (v == null) { + throw new NullPointerException(); + } else if (containsVertex(v)) { + return false; + } else { + specifics.addVertex(v); + // add all edges between the new vertex and vertices with intersecting intervals + addIntervalEdges(v, specifics.getOverlappingIntervalVertices(v)); + return true; + } + } + + /** + * {@inheritDoc} + */ + @Override + public V getEdgeSource(E e) + { + return intrusiveEdgesSpecifics.getEdgeSource(e); + } + + /** + * {@inheritDoc} + */ + @Override + public V getEdgeTarget(E e) + { + return intrusiveEdgesSpecifics.getEdgeTarget(e); + } + + /** + * Returns a shallow copy of this graph instance. Neither edges nor vertices are cloned. + * + * @return a shallow copy of this graph. + * + * @throws RuntimeException in case the clone is not supported + * + * @see java.lang.Object#clone() + */ + @Override + public Object clone() + { + try { + IntervalGraph newGraph = TypeUtil.uncheckedCast(super.clone()); + + newGraph.edgeFactory = this.edgeFactory; + newGraph.unmodifiableVertexSet = null; + + // NOTE: it's important for this to happen in an object + // method so that the new inner class instance gets associated with + // the right outer class instance + newGraph.specifics = newGraph.createSpecifics(this.directed); + newGraph.intrusiveEdgesSpecifics = + newGraph.createIntrusiveEdgesSpecifics(this.weighted); + + Graphs.addGraph(newGraph, this); + + return newGraph; + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + throw new RuntimeException(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean containsEdge(E e) + { + return intrusiveEdgesSpecifics.containsEdge(e); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean containsVertex(V v) + { + return specifics.getVertexSet().contains(v); + } + + /** + * {@inheritDoc} + */ + @Override + public int degreeOf(V vertex) + { + assertVertexExist(vertex); + return specifics.degreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set edgeSet() + { + return intrusiveEdgesSpecifics.getEdgeSet(); + } + + /** + * {@inheritDoc} + */ + @Override + public Set edgesOf(V vertex) + { + assertVertexExist(vertex); + return specifics.edgesOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public int inDegreeOf(V vertex) + { + assertVertexExist(vertex); + return specifics.inDegreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set incomingEdgesOf(V vertex) + { + assertVertexExist(vertex); + return specifics.incomingEdgesOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public int outDegreeOf(V vertex) + { + assertVertexExist(vertex); + return specifics.outDegreeOf(vertex); + } + + /** + * {@inheritDoc} + */ + @Override + public Set outgoingEdgesOf(V vertex) + { + assertVertexExist(vertex); + return specifics.outgoingEdgesOf(vertex); + } + + /** + * This method an IllegalArgumentException in every case because you can not remove edges from an interval graph manually. + * + * {@inheritDoc} + */ + @Override + public E removeEdge(V sourceVertex, V targetVertex) + { + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + } + + /** + * This method an IllegalArgumentException in every case because you can not remove edges from an interval graph manually. + * + * {@inheritDoc} + */ + @Override + public boolean removeEdge(E e) + { + throw new IllegalArgumentException(INTERVAL_GRAPH_ADD_EDGE); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean removeVertex(V v) + { + if (containsVertex(v)) { + removeAllEdgesFromVertex(v);//remove all edges from the given vertex to delete it safely + + specifics.removeVertex(v);// remove the vertex itself + + return true; + } else { + return false; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Set vertexSet() + { + if (unmodifiableVertexSet == null) { + unmodifiableVertexSet = Collections.unmodifiableSet(specifics.getVertexSet()); + } + + return unmodifiableVertexSet; + } + + /** + * {@inheritDoc} + */ + @Override + public double getEdgeWeight(E e) + { + if (e == null) { + throw new NullPointerException(); + } + return intrusiveEdgesSpecifics.getEdgeWeight(e); + } + + /** + * Set an edge weight. + * + * @param e the edge + * @param weight the weight + * @throws UnsupportedOperationException if the graph is not weighted + */ + @Override + public void setEdgeWeight(E e, double weight) + { + if (e == null) { + throw new NullPointerException(); + } + intrusiveEdgesSpecifics.setEdgeWeight(e, weight); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphType getType() + { + //TODO + if (directed) { + return new DefaultGraphType.Builder() + .directed().weighted(weighted).allowMultipleEdges(allowingMultipleEdges) + .allowSelfLoops(allowingLoops).build(); + } else { + return new DefaultGraphType.Builder() + .undirected().weighted(weighted).allowMultipleEdges(allowingMultipleEdges) + .allowSelfLoops(allowingLoops).build(); + } + } + + /** + * Create the specifics for this graph. Subclasses can override this method in order to adjust + * the specifics and thus the space-time tradeoffs of the graph implementation. + * + * @param directed if true the specifics should adjust the behavior to a directed graph + * otherwise undirected + * @return the specifics used by this graph + */ + protected IntervalSpecifics createSpecifics(boolean directed) + { + return new IntervalSpecifics<>(this); + } + + /** + * Create the specifics for the edges set of the graph. + * + * @param weighted if true the specifics should support weighted edges + * @return the specifics used for the edge set of this graph + */ + protected IntrusiveEdgesSpecifics createIntrusiveEdgesSpecifics(boolean weighted) + { + if (weighted) { + return new WeightedIntrusiveEdgesSpecifics<>(); + } else { + return new UniformIntrusiveEdgesSpecifics<>(); + } + } + + /** + * Adds edges between sourceVertex and every vertex from vertices + * This method should only be called from IntervalSpecifics, because interval graphs have by intervals defined edges. + * + * @param sourceVertex source vertex of all edges + * @param targetVertices target vertices of edges + */ + private boolean addIntervalEdges(V sourceVertex, Collection targetVertices) { + + assertVertexExist(sourceVertex); + + for(V targetVertex: targetVertices) { + assertVertexExist(targetVertex); + + E e = edgeFactory.createEdge(sourceVertex, targetVertex); + + if(intrusiveEdgesSpecifics.add(e, sourceVertex, targetVertex)) { + specifics.addEdgeToTouchingVertices(e); + } + } + return true; + } + + /** + * @see Graph#removeAllEdges(Collection) + */ + private boolean removeAllEdgesFromVertex(V vertex) { + Set touchingEdgesList = edgesOf(vertex); + + // cannot iterate over list - will cause + // ConcurrentModificationException + ArrayList edges = new ArrayList<>(touchingEdgesList); + + boolean modified = false; -public interface IntervalGraph> { - Collection> intersections(T queryInterval); + for (E e : edges) { - Collection> intersections(Interval queryInterval); + if (containsEdge(e)) { + specifics.removeEdgeFromTouchingVertices(e); + intrusiveEdgesSpecifics.remove(e); + modified = true; + } + } - Graph asGraph(); + return modified; + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java new file mode 100644 index 00000000000..930a139af15 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java @@ -0,0 +1,14 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.Graph; +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.Collection; + +public interface IntervalGraphInterface> { + Collection> intersections(T queryInterval); + + Collection> intersections(Interval queryInterval); + + Graph asGraph(); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java new file mode 100644 index 00000000000..24456133438 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -0,0 +1,109 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.graph.specifics.UndirectedEdgeContainer; +import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; + +import java.io.Serializable; +import java.util.*; + +/** + * Implementation of IntervalGraphVertexContainer + * + * @param the vertex type + * @param the edge type + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public class IntervalGraphVertexContainer, E, T extends Comparable> implements IntervalGraphVertexContainerInterface, Serializable { + + private static final long serialVersionUID = 7768940080894764546L; + + /** + * intervalStructure maintains all intervals in order to get intersecting intervals efficiently. + */ + private IntervalStructureInterface intervalStructure; + /** + * vertexMap maintains an EdgeContainer for every Vertex + */ + private Map> vertexMap; + /** + * intervalMap maintains the assignment of every interval to vertex + */ + private Map, V> intervalMap; + + /** + * Constructs a vertex container for an interval graph with all necessary objects. + */ + public IntervalGraphVertexContainer() { + this.intervalStructure = new IntervalTreeStructure<>(); + this.vertexMap = new LinkedHashMap<>(); + this.intervalMap = new LinkedHashMap<>(); + } + + /** + * Returns the whole vertex set of the graph. + * + * @return all vertices of the graph in a set + */ + @Override + public Set getVertexSet() { + return vertexMap.keySet(); + } + + /** + * returns a list of all vertices with overlapping interval w.r.t v + * + * @param vertex the vertex with interval + */ + @Override + public List getOverlappingIntervalVertices(V vertex) { + List> intervalList = intervalStructure.overlapsWith(vertex.getInterval()); + List vertexList = new LinkedList<>(); + + for(Interval interval: intervalList) { + vertexList.add(intervalMap.get(interval)); + } + + return vertexList; + } + + /** + * Returns the edge container to the vertex + * + * @param vertex the vertex + * @return the edge container to the vertex + */ + @Override + public UndirectedEdgeContainer get(V vertex) { + return vertexMap.get(vertex); + } + + /** + * puts the given edge container to the data structure + * + * @param vertex the vertex + * @param ec the edge container + */ + @Override + public UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec) { + intervalStructure.add(vertex.getInterval()); + intervalMap.put(vertex.getInterval(), vertex); + return vertexMap.put(vertex, ec); + } + + /** + * Removes a vertex from the data structure if it is present. + * + * @param vertex the vertex to be removed + * @return true if this data structure contained the specified element + */ + @Override + public UndirectedEdgeContainer remove(V vertex) { + intervalStructure.remove(vertex.getInterval()); + intervalMap.remove(vertex.getInterval()); + return vertexMap.remove(vertex); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java new file mode 100644 index 00000000000..6b339a33231 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java @@ -0,0 +1,57 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.graph.specifics.UndirectedEdgeContainer; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; + +import java.util.List; +import java.util.Set; + +/** + * Interface of IntervalGraphVertexContainer + * + * @param the vertex type + * @param the edge type + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public interface IntervalGraphVertexContainerInterface { + + /** + * Returns the whole vertex set of the graph. + * + * @return all vertices of the graph in a set + */ + Set getVertexSet(); + + /** + * returns a list of all vertices with overlapping interval w.r.t v + * + * @param v the vertex with interval + */ + List getOverlappingIntervalVertices(V v); + + /** + * Returns the edge container to the vertex + * + * @param vertex the vertex + * @return the edge container to the vertex + */ + UndirectedEdgeContainer get(V vertex); + + /** + * puts the given edge container to the data structure + * + * @param vertex the vertex + * @param ec the edge container + */ + UndirectedEdgeContainer put(V vertex, UndirectedEdgeContainer ec); + + /** + * Removes a vertex from the data structure if it is present. + * + * @param vertex the vertex to be removed + * @return true if this data structure contained the specified element + */ + UndirectedEdgeContainer remove(V vertex); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java new file mode 100644 index 00000000000..63b065b292f --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java @@ -0,0 +1,48 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.List; + +/** + * Interface of IntervalStructure + * This interface is used for an implementation of an efficient data structure to maintain intervals. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public interface IntervalStructureInterface> { + + /** + * Returns all intervals that overlap with the given interval + * + * @param interval the interval + * @return all intervals that overlap with the given interval + */ + List> overlapsWith(Interval interval); + + + /** + * Returns all intervals that overlap with the given point + * @param point the point + * @return all intervals that overlap with the given point + */ + List> overlapsWithPoint(T point); + + /** + * adds an interval to the interval tree + * + * @param interval the interval + */ + void add(Interval interval); + + /** + * removes an interval from the tree + * + * @param interval the interval + * @return + */ + void remove(Interval interval); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java new file mode 100644 index 00000000000..4c775653526 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -0,0 +1,36 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.List; + +/** + * Interface of IntervalTree + * This is the interface to an interval tree. It maintains intervals in order to find intersecting intervals and + * included points in O(log n + k), where n is the number of intervals and k the output size, + * i.e. the number of output intervals. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public interface IntervalTreeInterface, NodeValue extends IntervalTreeNodeValue, T>> extends BinarySearchTree { + + /** + * Returns all intervals of all vertices that intersect with the given interval + * + * @param interval the interval + * @return all intersecting intervals of vertices in the graph + */ + List> overlapsWith(Interval interval); + + /** + * Returns all intervals of all vertices that include the given point + * + * @param point the point + * @return all including intervals of vertices in the graph + */ + List> overlapsWith(T point); + +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java new file mode 100644 index 00000000000..7e8655f3e77 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -0,0 +1,89 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Implementation of IntervalTreeNodeValue + * This is a container class to store the necessary data for the (augmented) interval tree in the nodes of the tree. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public class IntervalTreeNodeValue, T extends Comparable> implements Serializable { + + private static final long serialVersionUID = 1111005364785643338L; + + /** + * The interval + */ + private Interval interval; + + /** + * the greatest end point of all intervals in the subtree rooted at that node. + */ + private T highValue; + + /** + * Create a new pair + * + * @param interval the first element + * @param highValue the second element + */ + public IntervalTreeNodeValue(I interval) { + this.interval = interval; + this.highValue = interval.getEnd(); + } + + /** + * Get the first element of the pair + * + * @return the first element of the pair + */ + public Interval getInterval() + { + return interval; + } + + /** + * Get the second element of the pair + * + * @return the second element of the pair + */ + public T getHighValue() + { + return highValue; + } + + public void setHighValue(T highValue) { + this.highValue = highValue; + } + + @Override + public String toString() + { + return "(" + interval + "," + highValue + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + else if (!(o instanceof IntervalTreeNodeValue)) + return false; + + @SuppressWarnings("unchecked") IntervalTreeNodeValue other = (IntervalTreeNodeValue) o; + return interval.equals(other.interval); + } + + @Override + public int hashCode() + { + return Objects.hash(interval, highValue); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java new file mode 100644 index 00000000000..5f82110b6e4 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -0,0 +1,60 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.io.Serializable; +import java.util.List; + +/** + * Implementation of IntervalTreeStructure + * This class realises the interval tree structure, which has a interval tree as maintaining object. + * + * @param the type of the interval + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public class IntervalTreeStructure> implements IntervalStructureInterface, Serializable { + + private static final long serialVersionUID = 2834567756342332325L; + + private IntervalTreeInterface, T>> tree = new RedBlackIntervalTree<>(); + + /** + * Returns all intervals that overlap with the given interval + * + * @param interval the interval + * @return all intervals that overlap with the given interval + */ + @Override + public List> overlapsWith(Interval interval) { + return tree.overlapsWith(interval); + } + + @Override + public List> overlapsWithPoint(T point) { + return tree.overlapsWith(point); + } + + + /** + * adds an interval to the interval tree + * + * @param interval the interval + */ + @Override + public void add(Interval interval) { + tree.insert(interval.getStart(), new IntervalTreeNodeValue<>(interval)); + } + + /** + * removes an interval from the tree + * + * @param interval the interval + * @return + */ + @Override + public void remove(Interval interval) { + tree.delete(interval.getStart()); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java new file mode 100644 index 00000000000..44009581c14 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -0,0 +1,177 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; + +/** + * Implementation of Node + * This class implements the node for a BST. + * + * @param the key + * @param the value + * + * @author Christoph Grüne (christophgruene) + * @author Daniel Mock (danielmock) + * @since Apr 26, 2018 + */ +public class Node implements Serializable { + + private static final long serialVersionUID = 5674337686253743843L; + + /** + * the key of the node + */ + private K key; + /** + * the value of the node + */ + private V val; + /** + * node's corresponding left and right children + */ + private Node leftChild, rightChild; + /** + * the color of the node (important for usage in red black tree)(not necessary for all implementations) + */ + private boolean red; + /** + * the size of the sub tree rooted at this node (not necessary for all implementations) + */ + private int size; + + /** + * constructs a node object + * + * @param key the key of the node + * @param val the value of the node + * @param red the color of the node + * @param size the size of the sub tree rooted at the node + */ + public Node(K key, V val, boolean red, int size) { + this.key = key; + this.val = val; + this.red = red; + this.size = size; + } + + /** + * sets a new left child of the node + * + * @param leftChild the node that should be new left child + */ + protected void setLeftChild(Node leftChild) { + this.leftChild = leftChild; + } + + /** + * sets a new right child of the node + * + * @param rightChild the node that should be new right child + */ + protected void setRightChild(Node rightChild) { + this.rightChild = rightChild; + } + + /** + * sets the color for the node + * + * @param red red: true, black: false + */ + protected void setRed(boolean red) { + this.red = red; + } + + /** + * sets the color of the node to red + */ + protected void setRed() { + this.red = true; + } + + /** + * sets the color of the node to black + */ + protected void setBlack() { + this.red = false; + } + + /** + * sets a new size for the sub tree rooted at this node + * + * @param size the size of the sub tree rooted at this node + */ + protected void setSize(int size) { + this.size = size; + } + + /** + * returns whether node is red or black + * + * @return red:true, black:false + */ + protected boolean isRed() { + return red; + } + + /** + * Getter for key + * + * @return the key + */ + protected K getKey() { + return key; + } + + /** + * Getter for val + * + * @return the value of the node + */ + protected V getVal() { + return val; + } + + /** + * Setter for val + * + * @param val the new value of the node + */ + public void setVal(V val) { + this.val = val; + } + + /** + * Getter for leftChild + * + * @return the left child of the node + */ + protected Node getLeftChild() { + return leftChild; + } + + /** + * Getter for rightChild + * + * @return the right child of the node + */ + protected Node getRightChild() { + return rightChild; + } + + /** + * Getter for size + * + * @return the size of the sub tree rooted at the node, if maintained + */ + protected int getSize() { + return size; + } + + /** + * sets a new key element for this node + * + * @param key the new key of the node + */ + public void setKey(K key) { + this.key = key; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java new file mode 100644 index 00000000000..7a629b1acd3 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java @@ -0,0 +1,146 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; + +/** + * Implementation of Node + * This class implements the node for a BST. + * + * @param the value + * @author Christoph Grüne (christophgruene) + * @author Daniel Mock (danielmock) + * @since Apr 26, 2018 + */ +public class RBNode implements Serializable { + + private static final long serialVersionUID = 5674337686253743843L; + + /** + * the value of the node + */ + private V val; + /** + * node's corresponding left and right children + */ + private RBNode leftChild, rightChild; + /** + * the color of the node (important for usage in red black tree)(not necessary for all implementations) + */ + private boolean red; + /** + * the size of the sub tree rooted at this node (not necessary for all implementations) + */ + private int size; + + /** + * constructs a node object + * + * @param val the value of the node + * @param red the color of the node + * @param size the size of the sub tree rooted at the node + */ + public RBNode(V val, boolean red, int size) { + this.val = val; + this.red = red; + this.size = size; + } + + /** + * sets a new left child of the node + * + * @param leftChild the node that should be new left child + */ + protected void setLeftChild(RBNode leftChild) { + this.leftChild = leftChild; + } + + /** + * sets a new right child of the node + * + * @param rightChild the node that should be new right child + */ + protected void setRightChild(RBNode rightChild) { + this.rightChild = rightChild; + } + + /** + * sets the color for the node + * + * @param red red: true, black: false + */ + protected void setRed(boolean red) { + this.red = red; + } + + /** + * sets the color of the node to red + */ + protected void setRed() { + this.red = true; + } + + /** + * sets the color of the node to black + */ + protected void setBlack() { + this.red = false; + } + + /** + * sets a new size for the sub tree rooted at this node + * + * @param size the size of the sub tree rooted at this node + */ + protected void setSize(int size) { + this.size = size; + } + + /** + * returns whether node is red or black + * + * @return red:true, black:false + */ + protected boolean isRed() { + return red; + } + + /** + * Getter for val + * + * @return the value of the node + */ + protected V getVal() { + return val; + } + + public void setVal(V val) { + this.val = val; + } + + /** + * Getter for leftChild + * + * @return the left child of the node + */ + protected RBNode getLeftChild() { + return leftChild; + } + + /** + * Getter for rightChild + * + * @return the right child of the node + */ + protected RBNode getRightChild() { + return rightChild; + } + + /** + * Getter for size + * + * @return the size of the sub tree rooted at the node, if maintained + */ + protected int getSize() { + return size; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java new file mode 100644 index 00000000000..d9541c33534 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -0,0 +1,534 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * Implementation of a Red-Black-Tree + * + * @param the value + * + * @author Daniel Mock (danielmock) + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ +public class RedBlackComparatorTree implements Serializable { + + private static final long serialVersionUID = 1199228564356373435L; + + protected RBNode root; + + public final Comparator comparator; + public final Comparator> nodeComparator; + + public RedBlackComparatorTree(Comparator comparator) { + this.comparator = comparator; + this.nodeComparator = (o1, o2) -> comparator.compare(o1.getVal(), o2.getVal()); + } + + public RBNode getRoot() { + return root; + } + + private boolean isRed(RBNode node){ + return node == null ? false : node.isRed(); + } + + /** + * Returns whether a key is contained in the tree + * + * @return true if tree contains key, false otherwise + * @throws IllegalArgumentException if key is null + */ + + public boolean contains(V val) { + if (val == null) { + throw new IllegalArgumentException("Val is null"); + } + + return searchNode(val) != null; + } + + /** + * Inserts the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * it overwrites the old value with the new. + * + * @param val the value + * @throws IllegalArgumentException if key is null + */ + + public void insert(V val) { + if (val == null) { + throw new IllegalArgumentException("Value is null"); + } + + root = insert(root, val); + root.setBlack(); + } + + protected RBNode insert(RBNode current, V val) { + if (current == null){ + return new RBNode<>(val, true, 1); + } + + if (val.equals(current.getVal())) { + current.setVal(val); + } else if (comparator.compare(val, current.getVal()) < 0) { + current.setLeftChild(insert(current.getLeftChild(), val)); + } else { + current.setRightChild(insert(current.getRightChild(), val)); + } + + // Fixup + + if (isRed(current.getRightChild()) && !isRed(current.getLeftChild())) { + current = rotateLeft(current); + } + if (isRed(current.getLeftChild()) && isRed(current.getLeftChild().getLeftChild())) { + current = rotateRight(current); + } + if (isRed(current.getLeftChild()) && isRed(current.getRightChild())) { + changeColor(current); + } + current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); + + return current; + } + + /** + * Removes the specified key and its associated value from this tree + * + * @throws IllegalArgumentException if key is null + */ + + public void delete(V val) { + if (val == null) { + throw new IllegalArgumentException("Key is null"); + } + if (!contains(val)) { + return; + } + + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = delete(root, val); + if (!isEmpty()) { + root.setBlack(); + } + } + + private boolean isEmpty() { + return root == null; + } + + protected RBNode delete(RBNode current, V val) { + if (comparator.compare(val, current.getVal()) < 0) { + if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { + current = moveRedLeft(current); + } + current.setLeftChild(delete(current.getLeftChild(), val)); + } else { + if (isRed(current.getLeftChild())) { + current = rotateRight(current); + } + if (comparator.compare(val, current.getVal()) == 0 && current.getRightChild() == null) { + return null; + } + if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { + current = moveRedRight(current); + } + if (comparator.compare(val, current.getVal()) == 0) { + RBNode node = min(current.getRightChild()); + current.setVal(node.getVal()); + current.setRightChild(deleteMin(current.getRightChild())); + } + else current.setRightChild(delete(current.getRightChild(), val)); + } + + return balance(current); + } + + protected RBNode balance(RBNode node) { + if (isRed(node.getRightChild())) { + node = rotateLeft(node); + } + if (isRed(node.getLeftChild()) && isRed(node.getLeftChild().getLeftChild())) { + node = rotateRight(node); + } + if (isRed(node.getLeftChild()) && isRed(node.getRightChild())) { + changeColor(node); + } + + node.setSize(size(node.getLeftChild()) + size(node.getRightChild() ) + 1); + return node; + } + + /** + * Removes the smallest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + + public void deleteMin() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = deleteMin(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private RBNode deleteMin(RBNode node) { + if (node.getLeftChild() == null) { + return null; + } + + if (!isRed(node.getLeftChild()) && !isRed(node.getLeftChild().getLeftChild())) { + root = moveRedLeft(node); + } + + node.setLeftChild(deleteMin(node.getLeftChild())); + return balance(node); + } + + /** + * Removes the largest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + + public void deleteMax() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + + if (!isRed(root.getRightChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = deleteMax(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private RBNode deleteMax(RBNode node) { + if (isRed(node.getLeftChild())) { + node = rotateRight(node); + } + if (node.getRightChild() == null) { + return null; + } + if (!isRed(node.getRightChild()) && !isRed(node.getRightChild().getLeftChild())) { + node = moveRedRight(node); + } + + node.setRightChild(deleteMax(node.getRightChild())); + + return balance(node); + } + + /** + * Returns the height of the BST. + * + * @return the height of the BST (a tree with 1 node has height 0) + */ + + public int height() { + return height(root); + } + + private int height(RBNode node) { + if (node == null) { + return -1; + } + + return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); + } + + /** + * Returns the smallest key in the tree. + * + * @return the smallest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + + public V min() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return min(root).getVal(); + } + + private RBNode min(RBNode node) { + if (node.getLeftChild() == null) { + return node; + } + return min(node.getLeftChild()); + } + + /** + * Returns the largest key in the tree. + * + * @return the largest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + + public V max() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return max(root.getRightChild()).getVal(); + } + + private RBNode max(RBNode node) { + if (node.getRightChild() == null) { + return node; + } + + return max(node.getRightChild()); + } + + /** + * Returns the largest key in the tree less than or equal to key. + * + * @return the largest key in the tree less than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + + public V floor(V val) { + return null; + } + + /** + * Returns the smallest key in the tree greater than or equal to key. + * + * @return the smallest key in the tree greater than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + + public V ceiling(V val) { + return null; + } + + /** + * Return the key in the tree whose rank is k. + * This is the (k+1)st smallest key in the tree. + * + * @param k the position + * @return the key in the tree of rank k + * @throws IllegalArgumentException if k not in {0, ..., n-1} + */ + + public V select(int k) { + return null; + } + + /** + * Return the number of keys in the tree strictly less than key. + * + * @param val the value + * @return the number of keys in the tree strictly less than key + * @throws IllegalArgumentException if key is null + */ + + public int rank(V val) { + return 0; + } + + /** + * Returns all keys in the symbol table as an Iterable. + * To iterate over all of the keys in the symbol table named st, + * use the foreach notation: for (Key key : st.keys()). + * + * @return all keys in the symbol table as an Iterable + */ + + public Iterable keys() { + return null; + } + + /** + * Returns all keys in the symbol table in the given range, + * as an Iterable. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return all keys in the sybol table between min + * (inclusive) and max (inclusive) as an Iterable + * @throws IllegalArgumentException if either min or max + * is null + */ + + public Iterable keys(V min, V max) { + return null; + } + + /** + * Returns the number of keys in the symbol table in the given range. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return the number of keys in the sybol table between min + * (inclusive) and max (inclusive) + * @throws IllegalArgumentException if either min or max + * is null + */ + + public int size(V min, V max) { + return 0; + } + + public int size(RBNode node) { + if (node == null) { + return 0; + } + + return getSize(node); + } + + /******************************************************************************************************************* + * HELPER METHODS * + ******************************************************************************************************************/ + + protected RBNode rotateLeft(RBNode node) { + RBNode rightChild = node.getRightChild(); + node.setRightChild(rightChild.getLeftChild()); + rightChild.setLeftChild(node); + rightChild.setRed(isRed(rightChild.getLeftChild())); + rightChild.getLeftChild().setRed(true); + rightChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); + return rightChild; + } + + private int getSize(RBNode node) { + return node != null ? node.getSize() : 0; + } + + protected RBNode rotateRight(RBNode node) { + RBNode leftChild = node.getLeftChild(); + node.setLeftChild(leftChild.getRightChild()); + leftChild.setRightChild(node); + leftChild.setRed(isRed(leftChild.getRightChild())); + leftChild.getRightChild().setRed(true); + leftChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); + return leftChild; + } + + private void changeColor(RBNode node) { + node.setRed(!isRed(node)); + node.getRightChild().setRed(!isRed(node.getRightChild())); + node.getLeftChild().setRed(!isRed(node.getLeftChild())); + } + + private RBNode searchNode(V val) { + RBNode current = root; + while (current != null) { + if (current.getVal().equals(val)) { + return current; + } else if (comparator.compare(current.getVal(), val) < 0) { + current = current.getRightChild(); + } else { + current = current.getLeftChild(); + } + } + + return null; + } + + private RBNode moveRedRight(RBNode node) { + changeColor(node); + if (isRed(node.getLeftChild().getLeftChild())) { + node = rotateRight(node); + changeColor(node); + } + + return node; + } + + private RBNode moveRedLeft(RBNode node) { + changeColor(node); + if (isRed(node.getRightChild().getLeftChild())) { + node.setRightChild(rotateRight(node.getRightChild())); + node = rotateLeft(node); + changeColor(node); + } + + return node; + } + + // returns the nodes inorder + private List> inorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + inorder(root, result); + return result; + } + + private void inorder(RBNode current, List> result) { + if (current == null) { + return; + } + + inorder(current.getLeftChild(), result); + result.add(current); + inorder(current.getRightChild(), result); + } + + public List inorderValues(){ + List> inorder = inorder(); + List result = new ArrayList<>(inorder.size()); + for (RBNode node: inorder) { + result.add(node.getVal()); + } + return result; + } + + private List> preorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + preorder(root, result); + return result; + } + + private void preorder(RBNode current, List> result) { + if (current == null) { + return; + } + + result.add(current); + inorder(current.getLeftChild(), result); + inorder(current.getRightChild(), result); + } + + // returns the minimum node in the subtree of input node + private RBNode getMin(RBNode node) { + while (node.getLeftChild() != null) { + node = node.getLeftChild(); + } + return node; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java new file mode 100644 index 00000000000..8d3f6f7c3dd --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java @@ -0,0 +1,170 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +public class RedBlackIntervalComparatorTree, + NodeValue extends IntervalTreeNodeValue, T>> + extends RedBlackComparatorTree { + public RedBlackIntervalComparatorTree(Comparator> comparator) { + super((o1, o2) -> comparator.compare(o1.getInterval(), o2.getInterval())); + } + + + /** + * Constructs a new instance. The comparator compares the start value of both intervals. + * In a tie, it compares the end values. + */ + public RedBlackIntervalComparatorTree() { + this((o1, o2) -> { + int startCompare = o1.getStart().compareTo(o2.getStart()); + if (startCompare != 0) { + return startCompare; + } else { + return o1.getEnd().compareTo(o2.getEnd()); + } + }); + } + + private static final long serialVersionUID = 4353687394654923429L; + + + public List> overlapsWith(Interval interval) { + List> result = new LinkedList<>(); + + overlapsWith(this.getRoot(), interval, result); + + return result; + } + + + public List> overlapsWith(T point) { + List> result = new LinkedList<>(); + + overlapsWithPoint(this.getRoot(), point, result); + return result; + } + + + protected RBNode rotateRight(RBNode node) { + // Perform rotation as usual + RBNode result = super.rotateRight(node); + + // update hi vals + result.getVal().setHighValue(node.getVal().getHighValue()); + updateHi(node); + + return result; + } + + + protected RBNode rotateLeft(RBNode node) { + // Perform rotation as usual + RBNode result = super.rotateLeft(node); + + // update hi vals + result.getVal().setHighValue(node.getVal().getHighValue()); + updateHi(node); + + return result; + } + + @Override + protected RBNode delete(RBNode current, NodeValue val) { + RBNode result = super.delete(current, val); + updateHi(result); + return result; + } + + + protected RBNode insert(RBNode current, NodeValue val) { + RBNode result = super.insert(current, val); + updateHi(result); + return result; + } + + + protected RBNode balance(RBNode node) { + RBNode result = super.balance(node); + updateHi(result); + return result; + } + + // sets the hi attribute of the given node to the max of the subtree or itself + private void updateHi(RBNode node) { + if (node == null) { + return; + } + + T result = node.getVal().getInterval().getEnd(); + if (node.getRightChild() != null) { + result = max(result, node.getRightChild().getVal().getHighValue()); + } + + if (node.getLeftChild() != null) { + result = max(result, node.getLeftChild().getVal().getHighValue()); + } + + node.getVal().setHighValue(result); + } + + + // returns the max of two values + public T max(T t1, T t2) { + if (t1.compareTo(t2) > 0) { + return t1; + } else { + return t2; + } + } + + private void overlapsWith(RBNode node, Interval interval, List> result) { + if (node == null) { + return; + } + + // query starts strictly after any interval in the subtree + if (interval.getStart().compareTo(node.getVal().getHighValue()) > 0) { + return; + } + + // node and query overlap + if (node.getVal().getInterval().isIntersecting(interval)) { + result.add(node.getVal().getInterval()); + } + + // if the node starts before the query ends, check right children + if (node.getVal().getInterval().getStart().compareTo(interval.getEnd()) <= 0) { + overlapsWith(node.getRightChild(), interval, result); + } + + overlapsWith(node.getLeftChild(), interval, result); + } + + private void overlapsWithPoint(RBNode node, T point, List> result) { + if (node == null) { + return; + } + + // point is bigger than the endpoint of any interval in the subtree + if (point.compareTo(node.getVal().getHighValue()) > 0) { + return; + } + + // check left subtrees + overlapsWithPoint(node.getLeftChild(), point, result); + + // add node interval if it contains the query point + if (node.getVal().getInterval().contains(point)) { + result.add(node.getVal().getInterval()); + } + + // check right subtree if their start values are smaller (equal) than query point + if (point.compareTo(node.getVal().getInterval().getStart()) >= 0) { + overlapsWithPoint(node.getRightChild(), point, result); + } + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java new file mode 100644 index 00000000000..2afe6c223bc --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -0,0 +1,161 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.Interval; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +/** + * Implementation of RedBlackIntervalTree + * This class implements the augmented interval tree. Essentially, this class updates the highValue + * after any operation on this tree. The highValue equals to the highest endpoint in the subtree + * + * @param the type of the interval + * @param the type of the node value + * + * @author Daniel Mock (danielmock) + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface, Serializable { + + private static final long serialVersionUID = 4353687394654923429L; + + @Override + public List> overlapsWith(Interval interval) { + List> result = new LinkedList<>(); + + overlapsWith(this.getRoot(), interval, result); + + return result; + } + + @Override + public List> overlapsWith(T point) { + List> result = new LinkedList<>(); + + overlapsWithPoint(this.getRoot(), point, result); + return result; + } + + @Override + protected Node rotateRight(Node node) { + // Perform rotation as usual + Node result = super.rotateRight(node); + + // update hi vals + result.getVal().setHighValue(node.getVal().getHighValue()); + updateHi(node); + + return result; + } + + @Override + protected Node rotateLeft(Node node) { + // Perform rotation as usual + Node result = super.rotateLeft(node); + + // update hi vals + result.getVal().setHighValue(node.getVal().getHighValue()); + updateHi(node); + + return result; + } + + @Override + protected Node delete(Node current, T key) { + Node result = super.delete(current, key); + updateHi(result); + return result; + } + + @Override + protected Node insert(Node current, T key, NodeValue val) { + Node result = super.insert(current, key, val); + updateHi(result); + return result; + } + + @Override + protected Node balance(Node node) { + Node result = super.balance(node); + updateHi(result); + return result; + } + + // sets the hi attribute of the given node to the max of the subtree or itself + private void updateHi(Node node) { + if (node == null) { + return; + } + + T result = node.getVal().getInterval().getEnd(); + if (node.getRightChild() != null) { + result = max(result, node.getRightChild().getVal().getHighValue()); + } + + if (node.getLeftChild() != null) { + result = max(result, node.getLeftChild().getVal().getHighValue()); + } + + node.getVal().setHighValue(result); + } + + + // returns the max of two values + public T max(T t1, T t2) { + if (t1.compareTo(t2) > 0) { + return t1; + } else { + return t2; + } + } + + private void overlapsWith(Node node, Interval interval, List> result) { + if (node == null) { + return; + } + + // query starts strictly after any interval in the subtree + if (interval.getStart().compareTo(node.getVal().getHighValue()) > 0) { + return; + } + + // node and query overlap + if (node.getVal().getInterval().isIntersecting(interval)) { + result.add(node.getVal().getInterval()); + } + + // if the node starts before the query ends, check right children + if (node.getVal().getInterval().getStart().compareTo(interval.getEnd()) <= 0) { + overlapsWith(node.getRightChild(), interval, result); + } + + overlapsWith(node.getLeftChild(), interval, result); + } + + private void overlapsWithPoint(Node node, T point, List> result) { + if (node == null) { + return; + } + + // point is bigger than the endpoint of any interval in the subtree + if (point.compareTo(node.getVal().getHighValue()) > 0) { + return; + } + + // check left subtrees + overlapsWithPoint(node.getLeftChild(), point, result); + + // add node interval if it contains the query point + if (node.getVal().getInterval().contains(point)) { + result.add(node.getVal().getInterval()); + } + + // check right subtree if their start values are smaller (equal) than query point + if (point.compareTo(node.getVal().getInterval().getStart()) >= 0) { + overlapsWithPoint(node.getRightChild(), point, result); + } + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java new file mode 100644 index 00000000000..dfc04a5080f --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -0,0 +1,551 @@ +package org.jgrapht.intervalgraph; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * Implementation of a Red-Black-Tree + * + * @param the key + * @param the value + * + * @author Daniel Mock (danielmock) + * @author Christoph Grüne (christophgruene) + * @since Apr 18, 2018 + */ +public class RedBlackTree, V> implements BinarySearchTree, Serializable { + + private static final long serialVersionUID = 1199228564356373435L; + + protected Node root; + + public Node getRoot() { + return root; + } + + /** + * Returns the value associated with the given key + * + * @param key the key + * @return the value associated with the given key. If the key is not in the tree, null is returned. + * @throws IllegalArgumentException if key is null + */ + @Override + public V get(K key) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + return searchNode(key).getVal(); + } + + private boolean isRed(Node node){ + if (node == null) { + return false; + } + return node.isRed(); + } + + /** + * Returns whether a key is contained in the tree + * + * @param key the key + * @return true if tree contains key, false otherwise + * @throws IllegalArgumentException if key is null + */ + @Override + public boolean contains(K key) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + return searchNode(key) != null; + } + + /** + * Inserts the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * it overwrites the old value with the new. + * + * @param key the key + * @param val the value + * @throws IllegalArgumentException if key is null + */ + @Override + public void insert(K key, V val) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + + root = insert(root, key, val); + root.setBlack(); + } + + protected Node insert(Node current, K key, V val) { + if (current == null){ + return new Node<>(key, val, true, 1); + } + + if (key.equals(current.getKey())) { + current.setVal(val); + } else if (key.compareTo(current.getKey()) < 0) { + current.setLeftChild(insert(current.getLeftChild(), key, val)); + } else { + current.setRightChild(insert(current.getRightChild(), key, val)); + } + + // Fixup + + if (isRed(current.getRightChild()) && !isRed(current.getLeftChild())) { + current = rotateLeft(current); + } + if (isRed(current.getLeftChild()) && isRed(current.getLeftChild().getLeftChild())) { + current = rotateRight(current); + } + if (isRed(current.getLeftChild()) && isRed(current.getRightChild())) { + changeColor(current); + } + current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); + + return current; + } + + /** + * Removes the specified key and its associated value from this tree + * + * @param key the key + * @throws IllegalArgumentException if key is null + */ + @Override + public void delete(K key) { + if (key == null) { + throw new IllegalArgumentException("Key is null"); + } + if (!contains(key)) { + return; + } + + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = delete(root, key); + if (!isEmpty()) { + root.setBlack(); + } + } + + private boolean isEmpty() { + return root == null; + } + + protected Node delete(Node current, K key) { + if (key.compareTo(current.getKey()) < 0) { + if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { + current = moveRedLeft(current); + } + current.setLeftChild(delete(current.getLeftChild(), key)); + } else { + if (isRed(current.getLeftChild())) { + current = rotateRight(current); + } + if (key.compareTo(current.getKey()) == 0 && current.getRightChild() == null) { + return null; + } + if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { + current = moveRedRight(current); + } + if (key.compareTo(current.getKey()) == 0) { + Node node = min(current.getRightChild()); + current.setKey(node.getKey()); + current.setVal(node.getVal()); + current.setRightChild(deleteMin(current.getRightChild())); + } + else current.setRightChild(delete(current.getRightChild(), key)); + } + + return balance(current); + } + + protected Node balance(Node node) { + if (isRed(node.getRightChild())) { + node = rotateLeft(node); + } + if (isRed(node.getLeftChild()) && isRed(node.getLeftChild().getLeftChild())) { + node = rotateRight(node); + } + if (isRed(node.getLeftChild()) && isRed(node.getRightChild())) { + changeColor(node); + } + + node.setSize(size(node.getLeftChild()) + size(node.getRightChild() ) + 1); + return node; + } + + /** + * Removes the smallest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + @Override + public void deleteMin() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = deleteMin(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private Node deleteMin(Node node) { + if (node.getLeftChild() == null) { + return null; + } + + if (!isRed(node.getLeftChild()) && !isRed(node.getLeftChild().getLeftChild())) { + root = moveRedLeft(node); + } + + node.setLeftChild(deleteMin(node.getLeftChild())); + return balance(node); + } + + /** + * Removes the largest key and associated value from the tree. + * + * @throws NoSuchElementException if the tree is empty + */ + @Override + public void deleteMax() { + if (isEmpty()) { + throw new NoSuchElementException(); + } + + if (!isRed(root.getRightChild()) && !isRed(root.getRightChild())) { + root.setRed(); + } + + root = deleteMax(root); + if (!isEmpty()) { + root.setBlack(); + } + } + + private Node deleteMax(Node node) { + if (isRed(node.getLeftChild())) { + node = rotateRight(node); + } + if (node.getRightChild() == null) { + return null; + } + if (!isRed(node.getRightChild()) && !isRed(node.getRightChild().getLeftChild())) { + node = moveRedRight(node); + } + + node.setRightChild(deleteMax(node.getRightChild())); + + return balance(node); + } + + /** + * Returns the height of the BST. + * + * @return the height of the BST (a tree with 1 node has height 0) + */ + @Override + public int height() { + return height(root); + } + + private int height(Node node) { + if (node == null) { + return -1; + } + + return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); + } + + /** + * Returns the smallest key in the tree. + * + * @return the smallest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + @Override + public K min() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return min(root).getKey(); + } + + private Node min(Node node) { + if (node.getLeftChild() == null) { + return node; + } + return max(node.getLeftChild()); + } + + /** + * Returns the largest key in the tree. + * + * @return the largest key in the tree + * @throws NoSuchElementException if the tree is empty + */ + @Override + public K max() { + if (isEmpty()) { + throw new NoSuchElementException("empty tree"); + } + + return max(root.getRightChild()).getKey(); + } + + private Node max(Node node) { + if (node.getRightChild() == null) { + return node; + } + + return max(node.getRightChild()); + } + + /** + * Returns the largest key in the tree less than or equal to key. + * + * @param key the key + * @return the largest key in the tree less than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + @Override + public K floor(K key) { + return null; + } + + /** + * Returns the smallest key in the tree greater than or equal to key. + * + * @param key the key + * @return the smallest key in the tree greater than or equal to key + * @throws NoSuchElementException if there is no such key + * @throws IllegalArgumentException if key is null + */ + @Override + public K ceiling(K key) { + return null; + } + + /** + * Return the key in the tree whose rank is k. + * This is the (k+1)st smallest key in the tree. + * + * @param k the position + * @return the key in the tree of rank k + * @throws IllegalArgumentException if k not in {0, ..., n-1} + */ + @Override + public K select(int k) { + return null; + } + + /** + * Return the number of keys in the tree strictly less than key. + * + * @param key the key + * @return the number of keys in the tree strictly less than key + * @throws IllegalArgumentException if key is null + */ + @Override + public int rank(K key) { + return 0; + } + + /** + * Returns all keys in the symbol table as an Iterable. + * To iterate over all of the keys in the symbol table named st, + * use the foreach notation: for (Key key : st.keys()). + * + * @return all keys in the symbol table as an Iterable + */ + @Override + public Iterable keys() { + return null; + } + + /** + * Returns all keys in the symbol table in the given range, + * as an Iterable. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return all keys in the sybol table between min + * (inclusive) and max (inclusive) as an Iterable + * @throws IllegalArgumentException if either min or max + * is null + */ + @Override + public Iterable keys(K min, K max) { + return null; + } + + /** + * Returns the number of keys in the symbol table in the given range. + * + * @param min minimum endpoint + * @param max maximum endpoint + * @return the number of keys in the sybol table between min + * (inclusive) and max (inclusive) + * @throws IllegalArgumentException if either min or max + * is null + */ + @Override + public int size(K min, K max) { + return 0; + } + + public int size(Node node) { + if (node == null) { + return 0; + } + + return getSize(node); + } + + /******************************************************************************************************************* + * HELPER METHODS * + ******************************************************************************************************************/ + + protected Node rotateLeft(Node node) { + Node rightChild = node.getRightChild(); + node.setRightChild(rightChild.getLeftChild()); + rightChild.setLeftChild(node); + rightChild.setRed(isRed(rightChild.getLeftChild())); + rightChild.getLeftChild().setRed(true); + rightChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); + return rightChild; + } + + private int getSize(Node node) { + return node != null ? node.getSize() : 0; + } + + protected Node rotateRight(Node node) { + Node leftChild = node.getLeftChild(); + node.setLeftChild(leftChild.getRightChild()); + leftChild.setRightChild(node); + leftChild.setRed(isRed(leftChild.getRightChild())); + leftChild.getRightChild().setRed(true); + leftChild.setSize(getSize(node)); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); + return leftChild; + } + + private void changeColor(Node node) { + node.setRed(!isRed(node)); + node.getRightChild().setRed(!isRed(node.getRightChild())); + node.getLeftChild().setRed(!isRed(node.getLeftChild())); + } + + private Node searchNode(K key) { + Node current = root; + while (current != null) { + if (current.getKey().equals(key)) { + return current; + } else if (current.getKey().compareTo(key) < 0) { + current = current.getRightChild(); + } else { + current = current.getLeftChild(); + } + } + + return null; + } + + private Node moveRedRight(Node node) { + changeColor(node); + if (isRed(node.getLeftChild().getLeftChild())) { + node = rotateRight(node); + changeColor(node); + } + + return node; + } + + private Node moveRedLeft(Node node) { + changeColor(node); + if (isRed(node.getRightChild().getLeftChild())) { + node.setRightChild(rotateRight(node.getRightChild())); + node = rotateLeft(node); + changeColor(node); + } + + return node; + } + + // returns the nodes inorder + private List> inorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + inorder(root, result); + return result; + } + + private void inorder(Node current, List> result) { + if (current == null) { + return; + } + + inorder(current.getLeftChild(), result); + result.add(current); + inorder(current.getRightChild(), result); + } + + public List inorderValues(){ + List> inorder = inorder(); + List result = new ArrayList<>(inorder.size()); + for (Node node: inorder) { + result.add(node.getVal()); + } + return result; + } + + private List> preorder() { + if (root == null) { + return new ArrayList<>(); + } + + List> result = new ArrayList<>(getSize(root)); + preorder(root, result); + return result; + } + + private void preorder(Node current, List> result) { + if (current == null) { + return; + } + + result.add(current); + inorder(current.getLeftChild(), result); + inorder(current.getRightChild(), result); + } + + // returns the minimum node in the subtree of input node + private Node getMin(Node node) { + while (node.getLeftChild() != null) { + node = node.getLeftChild(); + } + return node; + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 587ed37c7f4..154def1ea18 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -1,5 +1,7 @@ package org.jgrapht.intervalgraph.interval; +import java.util.Objects; + public class Interval> implements Comparable> { private T start; private T end; @@ -67,4 +69,24 @@ public int compareTo(Interval o) { public boolean isValid() { return getStart().compareTo(getEnd()) <= 0; } + + @Override + public String toString() { + return "Interval[" + start + ", " + end + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Interval interval = (Interval) o; + return Objects.equals(start, interval.start) && + Objects.equals(end, interval.end); + } + + @Override + public int hashCode() { + + return Objects.hash(start, end); + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java new file mode 100644 index 00000000000..f150244194c --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertex.java @@ -0,0 +1,90 @@ +package org.jgrapht.intervalgraph.interval; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Implementation for IntervalVertex + * This class implements the container class for vertices in an interval graph. + * + * @param the vertex + * @param the interval element + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public class IntervalVertex> implements IntervalVertexInterface, Serializable { + private V vertex; + private Interval interval; + + private static final long serialVersionUID = 7632653463458053425L; + + /** + * Constructor for an IntervalVertex (container class for vertices in interval graphs) + * + * @param vertex the vertex + * @param interval the interval + */ + private IntervalVertex(V vertex, Interval interval) { + this.vertex = vertex; + this.interval = interval; + } + + /** + * Getter for interval + * + * @return the interval + */ + @Override + public Interval getInterval() { + return interval; + } + + /** + * Getter for vertex + * + * @return the vertex + */ + @Override + public V getVertex() { + return vertex; + } + + @Override + public String toString() + { + return "(" + vertex + "," + interval + ")"; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + else if (!(o instanceof IntervalVertex)) + return false; + + @SuppressWarnings("unchecked") IntervalVertex other = (IntervalVertex) o; + return Objects.equals(vertex, other.vertex) && Objects.equals(interval, other.interval); + } + + @Override + public int hashCode() + { + return Objects.hash(vertex, interval); + } + + /** + * Creates new IntervalVertex of elements pulling of the necessity to provide corresponding types of the + * elements supplied. + * + * @param the vertex type + * @param the interval element type + * @param vertex the vertex + * @param interval the interval + * @return new pair + */ + public static > IntervalVertex of(V vertex, Interval interval) { + return new IntervalVertex<>(vertex, interval); + } +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java new file mode 100644 index 00000000000..2abcb0d79b5 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntervalVertexInterface.java @@ -0,0 +1,29 @@ +package org.jgrapht.intervalgraph.interval; + +/** + * Interface for IntervalVertex + * This interface provides necessary getters for the container of vertices in an interval graph + * as every vertex needs to have an interval. + * + * @param the vertex + * @param the interval element + * + * @author Christoph Grüne (christophgruene) + * @since Apr 26, 2018 + */ +public interface IntervalVertexInterface> { + + /** + * Getter for vertex + * + * @return the vertex + */ + V getVertex(); + + /** + * Getter for interval + * + * @return the interval + */ + Interval getInterval(); +} diff --git a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java index d6d3d2a5798..90a0e5293fe 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java +++ b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java @@ -613,8 +613,17 @@ boolean isEmpty() { class PriorityComparator implements Comparator { + /** + * Contains the priorities of the vertices. + */ private final HashMap priority; + /** + * Creates a new priority comparator for the vertex set with given priorities. + * + * @param priority the (integer-valued) priorities of the vertices. + * @throws IllegalArgumentException if the priorities are null. + */ public PriorityComparator(HashMap priority) throws IllegalArgumentException { if(priority == null) { throw new IllegalArgumentException("Priority map must not be null"); @@ -623,6 +632,14 @@ public PriorityComparator(HashMap priority) throws IllegalArgumentEx } @Override + /** + * Compares the priorities of the given vertices. + * + * @param vertex1 the first vertex to be compared. + * @param vertex2 the second vertex to be compared. + * + * @return Returns a positive integer (zero/a negative integer) if the priority of vertex1 is larger (equal to/smaller) than the one of vertex2. + */ public int compare(V vertex1, V vertex2) { return (priority.get(vertex1) - priority.get(vertex2)); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java new file mode 100644 index 00000000000..12a2f6db49f --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java @@ -0,0 +1,69 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.jgrapht.intervalgraph.interval.Interval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class CenteredIntervalTreeStructureTest { + + List> list; + + @Test + public void testCompareToPoint() { + IntegerInterval interval = new IntegerInterval(0, 1); + assertEquals(-1, interval.compareToPoint(-1)); + assertEquals(0, interval.compareToPoint(0)); + assertEquals(0, interval.compareToPoint(1)); + assertEquals(1, interval.compareToPoint(2)); + } + + @Test + public void testEmptyTree() { + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-2).size()); + assertEquals(0, tree.intersections(0).size()); + assertEquals(0, tree.intersections((2)).size()); + } + + @Test + public void testSingleInterval() { + list.add(new IntegerInterval(0, 2)); + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-1).size()); + assertEquals(1, tree.intersections(0).size()); + assertEquals(1, tree.intersections(1).size()); + assertEquals(1, tree.intersections(2).size()); + assertEquals(0, tree.intersections(3).size()); + } + + @Test + public void testPath() { + list.add(new IntegerInterval(0, 1)); + list.add(new IntegerInterval(1, 2)); + list.add(new IntegerInterval(2, 3)); + list.add(new IntegerInterval(3, 4)); + list.add(new IntegerInterval(4, 5)); + list.add(new IntegerInterval(5, 6)); + CenteredIntervalTree tree = new CenteredIntervalTree<>(list); + assertEquals(0, tree.intersections(-1).size()); + assertEquals(1, tree.intersections(0).size()); + assertEquals(2, tree.intersections(1).size()); + assertEquals(2, tree.intersections(2).size()); + assertEquals(2, tree.intersections(3).size()); + assertEquals(2, tree.intersections(4).size()); + assertEquals(2, tree.intersections(5).size()); + assertEquals(1, tree.intersections(6).size()); + assertEquals(0, tree.intersections(7).size()); + } + + @Before + public void setUp() { + list = new LinkedList<>(); + } +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java new file mode 100644 index 00000000000..bb24b3165fe --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java @@ -0,0 +1,39 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class IntervalTreeStructureTest { + List sorted = new LinkedList<>(); + IntervalTreeStructure tree = new IntervalTreeStructure<>(); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 20; i++) { + IntegerInterval interval = new IntegerInterval(i, i+3); + tree.add(interval); + sorted.add(interval); + } + } + + @Test + public void test1() { + for (int i = 3; i < 20; i++) { + assertEquals("loop " + i, 4, tree.overlapsWithPoint(i).size()); + } + } + + @Test + public void testIntervalOverlap() { + assertEquals(4, tree.overlapsWith(new IntegerInterval(0,3)).size()); + assertEquals(1 , tree.overlapsWith(new IntegerInterval(0,0)).size()); + assertEquals(0, tree.overlapsWith(new IntegerInterval(-3, -1)).size()); + assertEquals(20, tree.overlapsWith(new IntegerInterval(-5, 20)).size()); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java new file mode 100644 index 00000000000..38056c076cf --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java @@ -0,0 +1,39 @@ +package org.jgrapht.intervalgraph; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class RedBlackComparatorTreeTest { + + RedBlackComparatorTree tree = new RedBlackComparatorTree<>(Integer::compareTo); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 100; i++) { + tree.insert(i); + } + + tree.delete(5); + tree.delete(73); + tree.delete(200); + } + + @Test + public void isOrdered() { + for (int i = 0; i < 100; i++) { + assertEquals(i, (int) tree.inorderValues().get(i)); + } + } + + @Test + public void testContains() { + assertTrue(tree.contains(0)); + assertTrue(tree.contains(4)); + + assertFalse(tree.contains(5)); + assertFalse(tree.contains(73)); + assertFalse(tree.contains(200)); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java new file mode 100644 index 00000000000..3da0ba50ef1 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java @@ -0,0 +1,41 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.jgrapht.intervalgraph.interval.Interval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class RedBlackIntervalComparatorTreeTest { + + List sorted = new LinkedList<>(); + RedBlackIntervalComparatorTree, Integer>> tree = new RedBlackIntervalComparatorTree<>(); + + @Before + public void setUp() { + for (int i = 0; i < 20; i++) { + IntegerInterval interval = new IntegerInterval(i, i+3); + tree.insert(new IntervalTreeNodeValue<>(interval)); + sorted.add(interval); + } + } + + @Test + public void testInorder() { + List, Integer>> result = tree.inorderValues(); + for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { + Interval i = result.get(i1).getInterval(); + assertEquals("fault at " + i1,i, sorted.get(i1)); + } + + + assertTrue(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); + tree.delete(new IntervalTreeNodeValue<>(new IntegerInterval(5,8))); + assertFalse(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); + assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java new file mode 100644 index 00000000000..1ddcfffcbad --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -0,0 +1,40 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.intervalgraph.interval.IntegerInterval; +import org.jgrapht.intervalgraph.interval.Interval; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.*; + +public class RedBlackIntervalTreeStructureTest { + + List sorted = new LinkedList<>(); + RedBlackIntervalTree, Integer>> tree = new RedBlackIntervalTree<>(); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 20; i++) { + IntegerInterval interval = new IntegerInterval(i, i+3); + tree.insert(i, new IntervalTreeNodeValue<>(interval)); + sorted.add(interval); + } + } + + @Test + public void testInorder() { + List, Integer>> result = tree.inorderValues(); + for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { + Interval i = result.get(i1).getInterval(); + assertEquals("fault at " + i1,i, sorted.get(i1)); + } + + + tree.delete(5); + assertFalse(tree.contains(5)); + assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); + } +} \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java new file mode 100644 index 00000000000..d2c581e9eef --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java @@ -0,0 +1,82 @@ +package org.jgrapht.intervalgraph; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +/** + * Test important properties of red-black tree + */ +public class RedBlackTreeTest { + + private RedBlackTree redBlackTree = new RedBlackTree<>(); + + @Before + public void setUp() { + redBlackTree.insert(13, 13); + redBlackTree.insert(8, 8); + redBlackTree.insert(17, 17); + redBlackTree.insert(1, 1); + redBlackTree.insert(11, 11); + redBlackTree.insert(15, 15); + redBlackTree.insert(25, 25); + redBlackTree.insert(6, 6); + redBlackTree.insert(22, 22); + redBlackTree.insert(27, 27); + } + + /** + * The root is black + */ + @Test + public void testBlackRoot() { + assertFalse(redBlackTree.getRoot().isRed()); + } + + /** + * If a node is red, then both its children are black + */ + @Test + public void testBlackChildren() { + testBlackChildren(redBlackTree.getRoot()); + } + + private void testBlackChildren(Node currentNode) { + Node leftChild = currentNode.getLeftChild(); + if (leftChild != null) { + if (currentNode.isRed()) { + assertFalse(leftChild.isRed()); + } + testBlackChildren(leftChild); + } + + Node rightChild = currentNode.getRightChild(); + if (rightChild != null) { + if (currentNode.isRed()) { + assertFalse(rightChild.isRed()); + } + testBlackChildren(rightChild); + } + } + + /** + * Every path from a given node to any of its descendant leaves contains the same number of black nodes + */ + @Test + public void testBlackNodeNumber() { + assertEquals(countLeftChildren(redBlackTree.getRoot(), 0), countRightChildren(redBlackTree.getRoot(), 0)); + } + + private int countLeftChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); + } + + private int countRightChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); + } + +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 347380a85fa..a93add39452 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -20,9 +20,10 @@ public class IntervalGraphRecognizerTest { */ @Test public void testEmptyGraph() { - Graph g = new SimpleGraph<>(DefaultEdge.class); + Graph emptyGraph = new SimpleGraph<>(DefaultEdge.class); - assertTrue(IntervalGraphRecognizer.isIntervalGraph(g)); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(emptyGraph); + assertTrue(recognizer.isIntervalGraph()); } /** @@ -44,7 +45,8 @@ public void testForbiddenSubgraphBiclawWithAT() { builder.addEdge(2, 5); builder.addEdge(3, 6); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } /** @@ -71,7 +73,8 @@ public void testForbiddenSubgraphLekkerkerkerBoland() { builder.addEdge(3, 6); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { @@ -87,7 +90,8 @@ public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { builder.addEdge(n - 1, n); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } /** @@ -143,8 +147,9 @@ public boolean isCnAnIntervalGraph(int n) { for(int i = 0; i < n; i++) { builder.addEdge(i, (i + 1) % n); } - - return IntervalGraphRecognizer.isIntervalGraph(builder.build()); + + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + return recognizer.isIntervalGraph(); } /** From d99f7c0fad663f16aadcb483958ad594d7dd43eb Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 3 May 2018 19:17:33 +0200 Subject: [PATCH 070/131] changed the tests to the new interface --- .../interval/IntervalGraphRecognizerTest.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index a93add39452..87b14e8e8f4 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -126,7 +126,8 @@ public void isForbiddenSubgraphLekkerkerkerBolandFamily2(int n) { builder.addEdge(n, 2); builder.addEdge(n, 4); - assertFalse(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertFalse(recognizer.isIntervalGraph()); } /** @@ -173,7 +174,8 @@ public void isCompleteAnIntervalGraph(int n) { cgg.generateGraph(cg, new IntegerVertexFactory(), null); //Every complete Graph is an interval graph - assertTrue(IntervalGraphRecognizer.isIntervalGraph(cg)); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(cg); + assertTrue(recognizer.isIntervalGraph()); } /* @@ -197,7 +199,8 @@ public void isUnconnectedAnIntervalGraph(int n) { } //Every complete Graph is an interval graph - assertTrue(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertTrue(recognizer.isIntervalGraph()); } /* @@ -221,7 +224,8 @@ public void isLinearAnIntervalGraph(int n) { } //Every complete Graph is an interval graph - assertTrue(IntervalGraphRecognizer.isIntervalGraph(builder.build())); + IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); + assertTrue(recognizer.isIntervalGraph()); } /* From 80c64ea277f59f56caeb3e7fd9370512bc410e9d Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 3 May 2018 19:43:46 +0200 Subject: [PATCH 071/131] added GraphTests.isIntervalGraph() implementation --- jgrapht-core/src/main/java/org/jgrapht/GraphTests.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java index a8f0b722b82..b2c124a9be0 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java +++ b/jgrapht-core/src/main/java/org/jgrapht/GraphTests.java @@ -22,6 +22,7 @@ import org.jgrapht.alg.connectivity.KosarajuStrongConnectivityInspector; import org.jgrapht.alg.cycle.ChordalityInspector; import org.jgrapht.alg.cycle.HierholzerEulerianCycle; +import org.jgrapht.alg.intervalgraph.*; import java.util.*; import java.util.stream.Collectors; @@ -506,11 +507,12 @@ public static boolean isChordal(Graph graph){ * @param the graph vertex type * @param the graph edge type * @return true if the graph is an interval graph, false otherwise - * @see TODO + * @see IntervalGraphRecognizer#isIntervalGraph() * */ public static boolean isIntervalGraph(Graph graph) { - throw new UnsupportedOperationException("Not yet implemented!"); //TODO: Implement + Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL); + return new IntervalGraphRecognizer<>(graph).isIntervalGraph(); } /** From 58280ab521bc3c241c37fc809947ecabb3575f55 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Thu, 3 May 2018 22:17:22 +0200 Subject: [PATCH 072/131] Fix bugs in the interval graph detection algorithm --- .../IntervalGraphRecognizer.java | 57 +++++++------------ .../intervalgraph/LexBreadthFirstSearch.java | 13 ++--- .../traverse/LexBreadthFirstIterator.java | 44 +++++++------- .../interval/IntervalGraphRecognizerTest.java | 4 +- 4 files changed, 47 insertions(+), 71 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 7410f829f7e..41f29123185 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -51,7 +51,7 @@ public final class IntervalGraphRecognizer */ public IntervalGraphRecognizer(Graph graph) { - isIntervalGraph(graph); + this.isIntervalGraph = isIntervalGraph(graph); } /** @@ -73,27 +73,23 @@ public boolean isIntervalGraph(Graph graph) // sweep HashMap sweepAlpha = lexBreadthFirstSearch(graph, randomElementOf(graph.vertexSet())); - V vertexA = lastElementOf(sweepAlpha); // Step 2 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep alpha, vertex a // Output - the result of current sweep beta, further last vertex b visited by current sweep - HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, vertexA, sweepAlpha); - V vertexB = lastElementOf(sweepBeta); + HashMap sweepBeta = lexBreadthFirstSearchPlus(graph, sweepAlpha); // Step 3 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep beta, vertex b // Output - the result of current sweep gamma, further last vertex c visited by current // sweep - HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, vertexB, sweepBeta); - V vertexC = lastElementOf(sweepGamma); + HashMap sweepGamma = lexBreadthFirstSearchPlus(graph, sweepBeta); // Step 4 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep gamma, vertex c // Output - the result of current sweep delta, further last vertex d visited by current // sweep - HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, vertexC, sweepGamma); - V vertexD = lastElementOf(sweepDelta); + HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, sweepGamma); // Additionally, calculate the index and the corresponding A set for each vertex @@ -101,7 +97,7 @@ public boolean isIntervalGraph(Graph graph) // Input - the result of previous sweep delta, vertex d // Output - the result of current sweep epsilon, further last vertex e visited by current // sweep - HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, vertexD, sweepDelta); + HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, sweepDelta); // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? // Additionally, calculate the index and the corresponding B set for each vertex @@ -110,13 +106,12 @@ public boolean isIntervalGraph(Graph graph) // Input - the result of sweep gamma and sweep epsilon // Output - the result of current sweep zeta HashMap sweepZeta = - lexBreadthFirstSearchStar(graph, vertexD, sweepDelta, sweepEpsilon); + lexBreadthFirstSearchStar(graph, sweepDelta, sweepEpsilon); // if sweepZeta is umbrella-free, then the graph is interval. // otherwise, the graph is not interval if (isIOrdering(sweepZeta, graph)) { - this.isIntervalGraph = true; // Compute interval representation -- TODO: complete after merge HashMap neighborIndex = new HashMap<>(); @@ -153,13 +148,14 @@ public boolean isIntervalGraph(Graph graph) // TODO: build the actual interval graph this.intervalRepresentation = null; + + return true; } else { // set values negatively - this.isIntervalGraph = false; this.intervalRepresentation = null; - } - return isIOrdering(sweepZeta, graph); + return false; + } } /** @@ -171,61 +167,48 @@ public boolean isIntervalGraph(Graph graph) * @param graph the graph we want to check if its an I-Order * @return true, if sweep is an I-Order according to graph */ + @SuppressWarnings({"unchecked"}) private static boolean isIOrdering(HashMap sweep, Graph graph) { // Compute inverse sweep map to quickly find vertices at given indices - ArrayList inverseSweep = new ArrayList<>(graph.vertexSet().size()); + V[] inverseSweep = (V[])new Object[graph.vertexSet().size()]; for (V vertex : graph.vertexSet()) { int index = sweep.get(vertex); - inverseSweep.set(index, vertex); + inverseSweep[index] = vertex; } - // Compute maximal neighbors w.r.t. sweep ordering for every vertex HashMap maxNeighbors = new HashMap<>(graph.vertexSet().size()); - + for(V vertex : graph.vertexSet()) { List neighbors = Graphs.neighborListOf(graph, vertex); V maxNeighbor = vertex; - + for(V neighbor : neighbors) { if(sweep.get(neighbor) > sweep.get(maxNeighbor)) { maxNeighbor = neighbor; } } - + maxNeighbors.put(vertex, maxNeighbor); } - + // Check if every vertex is connected to all vertices between itself and its maximal neighbor for(V vertex : graph.vertexSet()) { int index = sweep.get(vertex); int maxIndex = sweep.get(maxNeighbors.get(vertex)); - + for(int i = index; i < maxIndex; i++) { - if(!graph.containsEdge(vertex, inverseSweep.get(i))) { + if(vertex != inverseSweep[i] && !graph.containsEdge(vertex, inverseSweep[i])) { // Found missing edge return false; } } } - + // No missing edge found return true; } - - - /** - * return the last element of the given map - * - * @param map - * @param the generic type representing vertices - * @return - */ - private static V lastElementOf(HashMap map) - { - return Collections.max(map.entrySet(), Map.Entry.comparingByValue()).getKey(); - } /** * return a random element of the given set diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java index 22a032ad0cd..efd2e1a599a 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java @@ -36,10 +36,10 @@ public static HashMap lexBreadthFirstSearch(Graph graph * @return an array of vertices representing the order in which the vertices were found */ - public static HashMap lexBreadthFirstSearchPlus(Graph graph, V startingVertex, HashMap priority) + public static HashMap lexBreadthFirstSearchPlus(Graph graph, HashMap priority) { HashMap result = new HashMap<>(graph.vertexSet().size()); - LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority, startingVertex); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority); for(int i = 0; i < graph.vertexSet().size(); i++) { result.put(lbfIterator.next(), i); @@ -52,13 +52,12 @@ public static HashMap lexBreadthFirstSearchPlus(Graph g * Performs LBFS* starting at {@code startingVertex} using two previous orderings {@code prevOrdering1} and {@code prevOrdering2}. * * @param graph the graph we want to perform LBFS on - * @param startingVertex the starting vertex of the LBFS - * @param priority1 the first priority of vertices for tiebreaking - * @param priority2 the second priority of vertices for tiebreaking + * @param priorityA the first priority of vertices for tiebreaking + * @param priorityB the second priority of vertices for tiebreaking * @return an array of vertices representing the order in which the vertices were found */ - public static HashMap lexBreadthFirstSearchStar(Graph graph, V startingVertex, HashMap priorityA, HashMap priorityB) + public static HashMap lexBreadthFirstSearchStar(Graph graph, HashMap priorityA, HashMap priorityB) { HashMap neighborIndexA = new HashMap<>(); HashMap neighborIndexB = new HashMap<>(); @@ -102,7 +101,7 @@ public static HashMap lexBreadthFirstSearchStar(Graph g } HashMap result = new HashMap<>(graph.vertexSet().size()); - LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets, startingVertex); + LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets); for(int i = 0; i < graph.vertexSet().size(); i++) { result.put(lbfIterator.next(), i); diff --git a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java index 90a0e5293fe..21ad472b5ed 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java +++ b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java @@ -97,33 +97,36 @@ public LexBreadthFirstIterator(Graph graph, V startingVertex) { * * @param graph the graph to be iterated. * @param priority the vertex array sorted by their priorities. - * @param startingVertex the initial vertex. */ - public LexBreadthFirstIterator(Graph graph, HashMap priority, V startingVertex) { + public LexBreadthFirstIterator(Graph graph, HashMap priority) { super(graph); GraphTests.requireUndirected(graph); Set copyOfSet = new HashSet<>(); copyOfSet.addAll(graph.vertexSet()); - bucketList = new BucketList(copyOfSet, new PriorityComparator(priority), startingVertex); + bucketList = new BucketList(copyOfSet, new PriorityComparator(priority)); } /** * Creates new lexicographical breadth-first iterator with a static priority list for {@code graph}. * * @param graph the graph to be iterated. - * @param priority the vertex array sorted by their priorities. - * @param startingVertex the initial vertex. */ - public LexBreadthFirstIterator(Graph graph, HashMap priorityA, HashMap priorityB, HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets, V startingVertex) { + public LexBreadthFirstIterator(Graph graph, + HashMap priorityA, + HashMap priorityB, + HashMap neighborIndexA, + HashMap neighborIndexB, + HashMap> ASets, + HashMap> BSets) { super(graph); GraphTests.requireUndirected(graph); Set copyOfSet = new HashSet<>(); copyOfSet.addAll(graph.vertexSet()); - bucketList = new BucketList(copyOfSet, priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets, startingVertex); + bucketList = new BucketList(copyOfSet, priorityA, priorityB, neighborIndexA, neighborIndexB, ASets, BSets); } /** @@ -291,17 +294,14 @@ class BucketList { * @param priorityComparator a comparator which defines a priority for tiebreaking. * @param startingVertex the initial vertex. */ - BucketList(Collection vertices, Comparator priorityComparator, V startingVertex) { + BucketList(Collection vertices, Comparator priorityComparator) { bucketMap = new HashMap<>(vertices.size()); // Split off starting vertex into its own bucket - vertices.remove(startingVertex); - head = new Bucket(startingVertex, priorityComparator); - head.insertBefore(new Bucket(vertices, priorityComparator)); + head = new Bucket(vertices, priorityComparator); - bucketMap.put(startingVertex, head); for (V vertex : vertices) { - bucketMap.put(vertex, head.next); + bucketMap.put(vertex, head); } } @@ -309,10 +309,8 @@ class BucketList { * Creates a {@code BucketList} with a single bucket and all specified {@code vertices} in it. * * @param vertices the vertices of the graph, that should be stored in the {@code head} bucket. - * @param priorityComparator a comparator which defines a priority for tiebreaking. - * @param startingVertex the initial vertex. */ - BucketList(Collection vertices, HashMap priorityA, HashMap priorityB, HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets, V startingVertex) { + BucketList(Collection vertices, HashMap priorityA, HashMap priorityB, HashMap neighborIndexA, HashMap neighborIndexB, HashMap> ASets, HashMap> BSets) { this.neighborIndexA = neighborIndexA; this.neighborIndexB = neighborIndexB; this.ASets = ASets; @@ -321,15 +319,11 @@ class BucketList { this.priorityB = priorityB; bucketMap = new HashMap<>(vertices.size()); - - // Split off starting vertex into its own bucket - vertices.remove(startingVertex); - head = new Bucket(startingVertex, new PriorityComparator(priorityA), new PriorityComparator(priorityB)); - head.insertBefore(new Bucket(vertices, new PriorityComparator(priorityA), new PriorityComparator(priorityB))); - bucketMap.put(startingVertex, head); + head = new Bucket(vertices, new PriorityComparator(priorityA), new PriorityComparator(priorityB)); + for (V vertex : vertices) { - bucketMap.put(vertex, head.next); + bucketMap.put(vertex, head); } } @@ -638,11 +632,11 @@ public PriorityComparator(HashMap priority) throws IllegalArgumentEx * @param vertex1 the first vertex to be compared. * @param vertex2 the second vertex to be compared. * - * @return Returns a positive integer (zero/a negative integer) if the priority of vertex1 is larger (equal to/smaller) than the one of vertex2. + * @return Returns a positive integer (zero/a negative integer) if the priority of vertex1 is smaller (equal to/higher) than the one of vertex2. */ public int compare(V vertex1, V vertex2) { - return (priority.get(vertex1) - priority.get(vertex2)); + return priority.get(vertex2) - priority.get(vertex1); } } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 87b14e8e8f4..99da92d109d 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -91,7 +91,7 @@ public void testForbiddenSubgraphLekkerkerkerBolandFamily(int n) { builder.addEdge(n - 1, n); IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); - assertFalse(recognizer.isIntervalGraph()); + assertEquals("n was " + n, n <= 4, recognizer.isIntervalGraph()); } /** @@ -234,7 +234,7 @@ public void isLinearAnIntervalGraph(int n) { @Test public void linearGraphTest() { - for(int i=0; i<20; i++) { + for(int i=4; i<20; i++) { isLinearAnIntervalGraph(i); } From 47a97325b9224f138519a09160b5148f77281799 Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Fri, 4 May 2018 12:58:03 +0200 Subject: [PATCH 073/131] Fix typos --- .../java/org/jgrapht/intervalgraph/BinarySearchTree.java | 2 +- .../org/jgrapht/intervalgraph/IntervalTreeNodeValue.java | 1 - .../org/jgrapht/intervalgraph/IntervalTreeStructure.java | 1 - .../src/main/java/org/jgrapht/intervalgraph/Node.java | 8 ++++---- .../src/main/java/org/jgrapht/intervalgraph/RBNode.java | 8 ++++++-- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java index db0b01d6f64..50439cfebef 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -41,7 +41,7 @@ public interface BinarySearchTree { ******************************************************************************************************************/ /** - * Insertes the given (key, value) pair into the tree. If the tree contains already a symbol with the given key + * Inserts the given (key, value) pair into the tree. If the tree contains already a symbol with the given key * it overwrites the old value with the new. * * @param key the key diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java index 7e8655f3e77..2935009e236 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -32,7 +32,6 @@ public class IntervalTreeNodeValue, T extends Comparable> overlapsWithPoint(T point) { return tree.overlapsWith(point); } - /** * adds an interval to the interval tree * diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java index 44009581c14..ff997225f54 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/Node.java @@ -28,7 +28,7 @@ public class Node implements Serializable { /** * node's corresponding left and right children */ - private Node leftChild, rightChild; + private Node leftChild, rightChild; /** * the color of the node (important for usage in red black tree)(not necessary for all implementations) */ @@ -58,7 +58,7 @@ public Node(K key, V val, boolean red, int size) { * * @param leftChild the node that should be new left child */ - protected void setLeftChild(Node leftChild) { + protected void setLeftChild(Node leftChild) { this.leftChild = leftChild; } @@ -67,7 +67,7 @@ protected void setLeftChild(Node leftChild) { * * @param rightChild the node that should be new right child */ - protected void setRightChild(Node rightChild) { + protected void setRightChild(Node rightChild) { this.rightChild = rightChild; } @@ -115,7 +115,7 @@ protected boolean isRed() { /** * Getter for key * - * @return the key + * @return the key of the node */ protected K getKey() { return key; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java index 7a629b1acd3..082328bb378 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java @@ -3,8 +3,7 @@ import java.io.Serializable; /** - * Implementation of Node - * This class implements the node for a BST. + * Implementation of red-black tree node * * @param the value * @author Christoph Grüne (christophgruene) @@ -113,6 +112,11 @@ protected V getVal() { return val; } + /** + * Setter for val + * + * @param val + */ public void setVal(V val) { this.val = val; } From 9f42f43ad8e53bf66a7e93394e83f374e73eb882 Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Fri, 4 May 2018 12:59:08 +0200 Subject: [PATCH 074/131] Refactoring --- .../intervalgraph/RedBlackComparatorTree.java | 63 ++++--------------- .../RedBlackIntervalComparatorTree.java | 26 +++----- .../intervalgraph/RedBlackIntervalTree.java | 12 +--- .../jgrapht/intervalgraph/RedBlackTree.java | 56 ++++++++--------- 4 files changed, 51 insertions(+), 106 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java index d9541c33534..c5a89b28dd6 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -7,7 +7,7 @@ import java.util.NoSuchElementException; /** - * Implementation of a Red-Black-Tree + * Implementation of red-black comparator tree * * @param the value * @@ -34,7 +34,7 @@ public RBNode getRoot() { } private boolean isRed(RBNode node){ - return node == null ? false : node.isRed(); + return node != null && node.isRed(); } /** @@ -43,7 +43,6 @@ private boolean isRed(RBNode node){ * @return true if tree contains key, false otherwise * @throws IllegalArgumentException if key is null */ - public boolean contains(V val) { if (val == null) { throw new IllegalArgumentException("Val is null"); @@ -59,7 +58,6 @@ public boolean contains(V val) { * @param val the value * @throws IllegalArgumentException if key is null */ - public void insert(V val) { if (val == null) { throw new IllegalArgumentException("Value is null"); @@ -93,7 +91,7 @@ protected RBNode insert(RBNode current, V val) { if (isRed(current.getLeftChild()) && isRed(current.getRightChild())) { changeColor(current); } - current.setSize(size(current.getLeftChild()) + size(current.getRightChild()) + 1); + current.setSize(getSize(current.getLeftChild()) + getSize(current.getRightChild()) + 1); return current; } @@ -103,7 +101,6 @@ protected RBNode insert(RBNode current, V val) { * * @throws IllegalArgumentException if key is null */ - public void delete(V val) { if (val == null) { throw new IllegalArgumentException("Key is null"); @@ -143,7 +140,7 @@ protected RBNode delete(RBNode current, V val) { current = moveRedRight(current); } if (comparator.compare(val, current.getVal()) == 0) { - RBNode node = min(current.getRightChild()); + RBNode node = getLeftChild(current.getRightChild()); current.setVal(node.getVal()); current.setRightChild(deleteMin(current.getRightChild())); } @@ -164,7 +161,7 @@ protected RBNode balance(RBNode node) { changeColor(node); } - node.setSize(size(node.getLeftChild()) + size(node.getRightChild() ) + 1); + node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild() ) + 1); return node; } @@ -173,7 +170,6 @@ protected RBNode balance(RBNode node) { * * @throws NoSuchElementException if the tree is empty */ - public void deleteMin() { if (isEmpty()) { throw new NoSuchElementException("empty tree"); @@ -207,7 +203,6 @@ private RBNode deleteMin(RBNode node) { * * @throws NoSuchElementException if the tree is empty */ - public void deleteMax() { if (isEmpty()) { throw new NoSuchElementException(); @@ -244,7 +239,6 @@ private RBNode deleteMax(RBNode node) { * * @return the height of the BST (a tree with 1 node has height 0) */ - public int height() { return height(root); } @@ -263,20 +257,16 @@ private int height(RBNode node) { * @return the smallest key in the tree * @throws NoSuchElementException if the tree is empty */ - public V min() { if (isEmpty()) { throw new NoSuchElementException("empty tree"); } - return min(root).getVal(); + return getLeftChild(root).getVal(); } - private RBNode min(RBNode node) { - if (node.getLeftChild() == null) { - return node; - } - return min(node.getLeftChild()); + private RBNode getLeftChild(RBNode node) { + return node.getLeftChild() == null ? node : getLeftChild(node.getLeftChild()); } /** @@ -285,21 +275,16 @@ private RBNode min(RBNode node) { * @return the largest key in the tree * @throws NoSuchElementException if the tree is empty */ - public V max() { if (isEmpty()) { throw new NoSuchElementException("empty tree"); } - return max(root.getRightChild()).getVal(); + return getRightChild(root).getVal(); } - private RBNode max(RBNode node) { - if (node.getRightChild() == null) { - return node; - } - - return max(node.getRightChild()); + private RBNode getRightChild(RBNode node) { + return node.getRightChild() == null ? node : getRightChild(node.getRightChild()); } /** @@ -309,7 +294,6 @@ private RBNode max(RBNode node) { * @throws NoSuchElementException if there is no such key * @throws IllegalArgumentException if key is null */ - public V floor(V val) { return null; } @@ -321,7 +305,6 @@ public V floor(V val) { * @throws NoSuchElementException if there is no such key * @throws IllegalArgumentException if key is null */ - public V ceiling(V val) { return null; } @@ -334,7 +317,6 @@ public V ceiling(V val) { * @return the key in the tree of rank k * @throws IllegalArgumentException if k not in {0, ..., n-1} */ - public V select(int k) { return null; } @@ -346,7 +328,6 @@ public V select(int k) { * @return the number of keys in the tree strictly less than key * @throws IllegalArgumentException if key is null */ - public int rank(V val) { return 0; } @@ -358,7 +339,6 @@ public int rank(V val) { * * @return all keys in the symbol table as an Iterable */ - public Iterable keys() { return null; } @@ -374,7 +354,6 @@ public Iterable keys() { * @throws IllegalArgumentException if either min or max * is null */ - public Iterable keys(V min, V max) { return null; } @@ -389,17 +368,12 @@ public Iterable keys(V min, V max) { * @throws IllegalArgumentException if either min or max * is null */ - public int size(V min, V max) { return 0; } - public int size(RBNode node) { - if (node == null) { - return 0; - } - - return getSize(node); + public int getSize(RBNode node) { + return node == null ? 0 : node.getSize(); } /******************************************************************************************************************* @@ -417,10 +391,6 @@ protected RBNode rotateLeft(RBNode node) { return rightChild; } - private int getSize(RBNode node) { - return node != null ? node.getSize() : 0; - } - protected RBNode rotateRight(RBNode node) { RBNode leftChild = node.getLeftChild(); node.setLeftChild(leftChild.getRightChild()); @@ -524,11 +494,4 @@ private void preorder(RBNode current, List> result) { inorder(current.getRightChild(), result); } - // returns the minimum node in the subtree of input node - private RBNode getMin(RBNode node) { - while (node.getLeftChild() != null) { - node = node.getLeftChild(); - } - return node; - } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java index 8d3f6f7c3dd..5d07d136245 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java @@ -6,14 +6,20 @@ import java.util.LinkedList; import java.util.List; +/** + * Implementation of red-black comparator tree with support for interval tree + * + * @param + * @param + */ public class RedBlackIntervalComparatorTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackComparatorTree { + public RedBlackIntervalComparatorTree(Comparator> comparator) { super((o1, o2) -> comparator.compare(o1.getInterval(), o2.getInterval())); } - /** * Constructs a new instance. The comparator compares the start value of both intervals. * In a tie, it compares the end values. @@ -31,24 +37,18 @@ public RedBlackIntervalComparatorTree() { private static final long serialVersionUID = 4353687394654923429L; - public List> overlapsWith(Interval interval) { List> result = new LinkedList<>(); - overlapsWith(this.getRoot(), interval, result); - return result; } - public List> overlapsWith(T point) { List> result = new LinkedList<>(); - overlapsWithPoint(this.getRoot(), point, result); return result; } - protected RBNode rotateRight(RBNode node) { // Perform rotation as usual RBNode result = super.rotateRight(node); @@ -60,7 +60,6 @@ protected RBNode rotateRight(RBNode node) { return result; } - protected RBNode rotateLeft(RBNode node) { // Perform rotation as usual RBNode result = super.rotateLeft(node); @@ -79,14 +78,12 @@ protected RBNode delete(RBNode current, NodeValue val) { return result; } - protected RBNode insert(RBNode current, NodeValue val) { RBNode result = super.insert(current, val); updateHi(result); return result; } - protected RBNode balance(RBNode node) { RBNode result = super.balance(node); updateHi(result); @@ -111,14 +108,11 @@ private void updateHi(RBNode node) { node.getVal().setHighValue(result); } - - // returns the max of two values public T max(T t1, T t2) { - if (t1.compareTo(t2) > 0) { - return t1; - } else { - return t2; + if (t1 == null || t2 == null) { + throw new IllegalArgumentException("Parameter cannot be null."); } + return t1.compareTo(t2) > 0 ? t1 : t2; } private void overlapsWith(RBNode node, Interval interval, List> result) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index 2afe6c223bc..d8eacf25b36 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -25,16 +25,13 @@ public class RedBlackIntervalTree, NodeValue extends Int @Override public List> overlapsWith(Interval interval) { List> result = new LinkedList<>(); - overlapsWith(this.getRoot(), interval, result); - return result; } @Override public List> overlapsWith(T point) { List> result = new LinkedList<>(); - overlapsWithPoint(this.getRoot(), point, result); return result; } @@ -102,14 +99,11 @@ private void updateHi(Node node) { node.getVal().setHighValue(result); } - - // returns the max of two values public T max(T t1, T t2) { - if (t1.compareTo(t2) > 0) { - return t1; - } else { - return t2; + if (t1 == null || t2 == null) { + throw new IllegalArgumentException("Parameter cannot be null."); } + return t1.compareTo(t2) > 0 ? t1 : t2; } private void overlapsWith(Node node, Interval interval, List> result) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index dfc04a5080f..61de0612fc2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -42,10 +42,7 @@ public V get(K key) { } private boolean isRed(Node node){ - if (node == null) { - return false; - } - return node.isRed(); + return node != null && node.isRed(); } /** @@ -141,31 +138,32 @@ private boolean isEmpty() { } protected Node delete(Node current, K key) { - if (key.compareTo(current.getKey()) < 0) { - if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { - current = moveRedLeft(current); - } - current.setLeftChild(delete(current.getLeftChild(), key)); + if (key.compareTo(current.getKey()) < 0) { + if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { + current = moveRedLeft(current); + } + current.setLeftChild(delete(current.getLeftChild(), key)); + } else { + if (isRed(current.getLeftChild())) { + current = rotateRight(current); + } + if (key.compareTo(current.getKey()) == 0 && current.getRightChild() == null) { + return null; + } + if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { + current = moveRedRight(current); + } + if (key.compareTo(current.getKey()) == 0) { + Node node = min(current.getRightChild()); + current.setKey(node.getKey()); + current.setVal(node.getVal()); + current.setRightChild(deleteMin(current.getRightChild())); } else { - if (isRed(current.getLeftChild())) { - current = rotateRight(current); - } - if (key.compareTo(current.getKey()) == 0 && current.getRightChild() == null) { - return null; - } - if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { - current = moveRedRight(current); - } - if (key.compareTo(current.getKey()) == 0) { - Node node = min(current.getRightChild()); - current.setKey(node.getKey()); - current.setVal(node.getVal()); - current.setRightChild(deleteMin(current.getRightChild())); - } - else current.setRightChild(delete(current.getRightChild(), key)); + current.setRightChild(delete(current.getRightChild(), key)); } + } - return balance(current); + return balance(current); } protected Node balance(Node node) { @@ -265,11 +263,7 @@ public int height() { } private int height(Node node) { - if (node == null) { - return -1; - } - - return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); + return node == null ? -1 : 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); } /** From a7c8ba0a7d23115d52bc34d433c25cf7ecfca2c6 Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Fri, 4 May 2018 14:00:53 +0200 Subject: [PATCH 075/131] Refactoring and documentation for Interval --- .../interval/IntegerInterval.java | 20 ++++- .../intervalgraph/interval/Interval.java | 85 ++++++++++++++----- .../RedBlackIntervalComparatorTreeTest.java | 1 - .../RedBlackIntervalTreeStructureTest.java | 1 - .../interval/IntegerIntervalTest.java | 17 ++-- 5 files changed, 89 insertions(+), 35 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java index 81131e8a52a..eeb7415c53f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java @@ -1,16 +1,32 @@ package org.jgrapht.intervalgraph.interval; +/** + * Model of an integer interval in the interval graph + */ public class IntegerInterval extends Interval { + + /** + * Construct an integer interval + * + * @param start interval start + * @param end interval end + * @throws IllegalArgumentException if interval start or end is null, or if interval start is greater than interval end + */ public IntegerInterval(int start, int end) { super(start, end); } + /** + * Get the duration of the interval + * + * @return the duration of the interval + */ public int length() { - return getEnd() - getStart(); + return end - start; } @Override public String toString() { - return "[" + getStart() + ", " + getEnd() + "]"; + return "IntegerInterval[" + start + ", " + end + "]"; } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 154def1ea18..a77d022cf4c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -2,60 +2,104 @@ import java.util.Objects; +/** + * Model of an interval in the interval graph + * + * @param the type of the interval + */ public class Interval> implements Comparable> { - private T start; - private T end; - public Interval(T start, T end) { + protected T start; + protected T end; + + /** + * Construct an interval + * + * @param start interval start + * @param end interval end + * @throws IllegalArgumentException if interval start or end is null, or if interval start is greater than interval end + */ + public Interval(T start, T end) { + if (start == null || end == null) { + throw new IllegalArgumentException("Interval start or end cannot be null."); + } + if (start.compareTo(end) > 0) { + throw new IllegalArgumentException("Interval start must be smaller than or equal to interval end."); + } + this.start = start; this.end = end; - - if (start == null || end == null || !isValid()) - throw new IllegalArgumentException(); } + /** + * Get the start point of the interval + * + * @return the start point of the interval + */ public T getStart() { return start; } + + /** + * Get the end point of the interval + * + * @return the end point of the interval + */ public T getEnd() { return end; } + /** + * Check if current interval intersects with the given interval + * + * @param other the interval to be tested + * @return true if current interval intersects with the given interval, false otherwise + */ public boolean isIntersecting(Interval other) { return this.contains(other.getStart()) || this.contains(other.getEnd()) || other.contains(this.getStart()); } + /** + * Check if current interval contains the given point + * + * @param point the point to be tested + * @return true if current interval contains the given point, false otherwise + */ public boolean contains(T point) { if (point == null) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Point to be tested cannot be null."); } - boolean result = point.compareTo(getStart()) >= 0 && point.compareTo(getEnd()) <= 0; + boolean result = point.compareTo(start) >= 0 && point.compareTo(end) <= 0; assert result == (compareToPoint(point) == 0); return result; } - - public int compareToPoint(T o) { - if (o == null) { - throw new IllegalArgumentException(); + /** + * Compare current interval with the given point + * + * @param point the point to be tested + * @return 0 if current interval contains the given point, comparison result with the interval start otherwise + */ + public int compareToPoint(T point) { + if (point == null) { + throw new IllegalArgumentException("Point to be tested cannot be null."); } - int relativeStart = getStart().compareTo(o); - int relativeEnd = getEnd().compareTo(o); + int relativeStart = start.compareTo(point); + int relativeEnd = end.compareTo(point); if (relativeStart <= 0 && relativeEnd >= 0) { return 0; - } else { + } else { return relativeStart; } } - @Override public int compareTo(Interval o) { - int isLeft = getEnd().compareTo(o.getStart()); // < 0 if this ends before other starts - int isRight = getStart().compareTo(o.getEnd()); // > 0 if this starts before other ends + int isLeft = end.compareTo(o.getStart()); // < 0 if this ends before other starts + int isRight = start.compareTo(o.getEnd()); // > 0 if this starts before other ends if (isLeft >= 0 && isRight <= 0) { return 0; @@ -66,10 +110,6 @@ public int compareTo(Interval o) { } } - public boolean isValid() { - return getStart().compareTo(getEnd()) <= 0; - } - @Override public String toString() { return "Interval[" + start + ", " + end + "]"; @@ -86,7 +126,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(start, end); } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java index 3da0ba50ef1..d76381f8037 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java @@ -32,7 +32,6 @@ public void testInorder() { assertEquals("fault at " + i1,i, sorted.get(i1)); } - assertTrue(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); tree.delete(new IntervalTreeNodeValue<>(new IntegerInterval(5,8))); assertFalse(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index 1ddcfffcbad..db3a19e7562 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -32,7 +32,6 @@ public void testInorder() { assertEquals("fault at " + i1,i, sorted.get(i1)); } - tree.delete(5); assertFalse(tree.contains(5)); assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java index 0ce6e35a274..4baaa4dfe7e 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.*; public class IntegerIntervalTest { + IntegerInterval i00 = new IntegerInterval(0,0); IntegerInterval i01 = new IntegerInterval(0,1); IntegerInterval i56 = new IntegerInterval(5,6); @@ -24,10 +25,6 @@ public void contains() { assertFalse(i00.contains(1)); } - @Test - public void relativeDistance() { - } - @Test public void compareTo() { assertEquals(i00.compareTo(i01), 0); @@ -36,9 +33,13 @@ public void compareTo() { assertEquals(i00.compareTo(i56), -1); } - @Test - public void isValid() { - assertTrue(i00.isValid()); - assertTrue(i01.isValid()); + @Test(expected = IllegalArgumentException.class) + public void testInvalidInterval1() { + new Interval(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidInterval2() { + new IntegerInterval(6, 5); } } From e35e5b1338c1374bc973dc7b7998e78138c2180f Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Fri, 4 May 2018 14:52:34 +0200 Subject: [PATCH 076/131] Add tests for RedBlackComparatorTree --- .../IntervalStructureInterface.java | 1 - .../intervalgraph/IntervalTreeStructure.java | 1 - .../org/jgrapht/intervalgraph/RBNode.java | 2 +- .../RedBlackIntervalComparatorTree.java | 3 +- .../intervalgraph/RedBlackIntervalTree.java | 4 +- .../jgrapht/intervalgraph/RedBlackTree.java | 3 +- .../CenteredIntervalTreeStructureTest.java | 7 +- .../CenteredIntervalTreeTest.java | 7 +- .../IntervalTreeStructureTest.java | 5 +- .../RedBlackComparatorTreeTest.java | 91 +++++++-- .../RedBlackIntervalComparatorTreeTest.java | 4 +- ...est.java => RedBlackIntervalTreeTest.java} | 3 +- .../intervalgraph/RedBlackTreeTest.java | 181 +++++++++++------- .../interval/IntegerIntervalTest.java | 12 +- 14 files changed, 211 insertions(+), 113 deletions(-) rename jgrapht-core/src/test/java/org/jgrapht/intervalgraph/{RedBlackIntervalTreeStructureTest.java => RedBlackIntervalTreeTest.java} (96%) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java index 63b065b292f..cbfadc40632 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java @@ -42,7 +42,6 @@ public interface IntervalStructureInterface> { * removes an interval from the tree * * @param interval the interval - * @return */ void remove(Interval interval); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index 6b847e86421..3e45ede8cab 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -50,7 +50,6 @@ public void add(Interval interval) { * removes an interval from the tree * * @param interval the interval - * @return */ @Override public void remove(Interval interval) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java index 082328bb378..bc0f9bb5e36 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java @@ -5,7 +5,7 @@ /** * Implementation of red-black tree node * - * @param the value + * @param the type of the node * @author Christoph Grüne (christophgruene) * @author Daniel Mock (danielmock) * @since Apr 26, 2018 diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java index 5d07d136245..c417131fed5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java @@ -12,8 +12,7 @@ * @param * @param */ -public class RedBlackIntervalComparatorTree, - NodeValue extends IntervalTreeNodeValue, T>> +public class RedBlackIntervalComparatorTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackComparatorTree { public RedBlackIntervalComparatorTree(Comparator> comparator) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index d8eacf25b36..62212580448 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -18,7 +18,9 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackTree implements IntervalTreeInterface, Serializable { +public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>> + extends RedBlackTree + implements IntervalTreeInterface, Serializable { private static final long serialVersionUID = 4353687394654923429L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 61de0612fc2..9fc30447ee8 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -15,7 +15,8 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class RedBlackTree, V> implements BinarySearchTree, Serializable { +public class RedBlackTree, V> + implements BinarySearchTree, Serializable { private static final long serialVersionUID = 1199228564356373435L; diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java index 12a2f6db49f..dfb171355f2 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java @@ -12,7 +12,7 @@ public class CenteredIntervalTreeStructureTest { - List> list; + private List> list = new LinkedList<>(); @Test public void testCompareToPoint() { @@ -61,9 +61,4 @@ public void testPath() { assertEquals(1, tree.intersections(6).size()); assertEquals(0, tree.intersections(7).size()); } - - @Before - public void setUp() { - list = new LinkedList<>(); - } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java index 1a813030206..b17c4611387 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java @@ -12,7 +12,7 @@ public class CenteredIntervalTreeTest { - List> list; + private List> list = new LinkedList<>(); @Test public void testCompareToPoint() { @@ -61,9 +61,4 @@ public void testPath() { assertEquals(1, tree.intersections(6).size()); assertEquals(0, tree.intersections(7).size()); } - - @Before - public void setUp() { - list = new LinkedList<>(); - } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java index bb24b3165fe..6caadb8cc09 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java @@ -10,8 +10,9 @@ import static org.junit.Assert.*; public class IntervalTreeStructureTest { - List sorted = new LinkedList<>(); - IntervalTreeStructure tree = new IntervalTreeStructure<>(); + + private List sorted = new LinkedList<>(); + private IntervalTreeStructure tree = new IntervalTreeStructure<>(); @Before public void setUp() throws Exception { diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java index 38056c076cf..ea344b5fdda 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java @@ -7,33 +7,96 @@ public class RedBlackComparatorTreeTest { - RedBlackComparatorTree tree = new RedBlackComparatorTree<>(Integer::compareTo); + private RedBlackComparatorTree redBlackComparatorTree = new RedBlackComparatorTree<>(Integer::compareTo); @Before - public void setUp() throws Exception { + public void setUp() { for (int i = 0; i < 100; i++) { - tree.insert(i); + redBlackComparatorTree.insert(i); } - - tree.delete(5); - tree.delete(73); - tree.delete(200); } @Test - public void isOrdered() { + public void testOrdered() { for (int i = 0; i < 100; i++) { - assertEquals(i, (int) tree.inorderValues().get(i)); + assertEquals(i, (int) redBlackComparatorTree.inorderValues().get(i)); } } @Test public void testContains() { - assertTrue(tree.contains(0)); - assertTrue(tree.contains(4)); + assertTrue(redBlackComparatorTree.contains(0)); + assertTrue(redBlackComparatorTree.contains(4)); + } + + @Test + public void testContainsNegative() { + redBlackComparatorTree.delete(5); + redBlackComparatorTree.delete(73); + redBlackComparatorTree.delete(200); + + assertFalse(redBlackComparatorTree.contains(5)); + assertFalse(redBlackComparatorTree.contains(73)); + assertFalse(redBlackComparatorTree.contains(200)); + } + + @Test + public void testDelete() { + redBlackComparatorTree.delete(25); + redBlackComparatorTree.delete(25); + } + + // Test important properties of red-black tree + + /** + * The root is black + */ + @Test + public void testBlackRoot() { + assertFalse(redBlackComparatorTree.getRoot().isRed()); + } + + /** + * If a node is red, then both its children are black + */ + @Test + public void testBlackChildren() { + testBlackChildren(redBlackComparatorTree.getRoot()); + } + + private void testBlackChildren(RBNode currentNode) { + RBNode leftChild = currentNode.getLeftChild(); + if (leftChild != null) { + if (currentNode.isRed()) { + assertFalse(leftChild.isRed()); + } + testBlackChildren(leftChild); + } + + RBNode rightChild = currentNode.getRightChild(); + if (rightChild != null) { + if (currentNode.isRed()) { + assertFalse(rightChild.isRed()); + } + testBlackChildren(rightChild); + } + } + + /** + * Every path from a given node to any of its descendant leaves contains the same number of black nodes + */ + @Test + public void testBlackNodeNumber() { + assertEquals(countLeftChildren(redBlackComparatorTree.getRoot(), 0), countRightChildren(redBlackComparatorTree.getRoot(), 0)); + } + + private int countLeftChildren(RBNode node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); + } - assertFalse(tree.contains(5)); - assertFalse(tree.contains(73)); - assertFalse(tree.contains(200)); + private int countRightChildren(RBNode node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); } } \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java index d76381f8037..747de1debec 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java @@ -12,8 +12,8 @@ public class RedBlackIntervalComparatorTreeTest { - List sorted = new LinkedList<>(); - RedBlackIntervalComparatorTree, Integer>> tree = new RedBlackIntervalComparatorTree<>(); + private List sorted = new LinkedList<>(); + private RedBlackIntervalComparatorTree, Integer>> tree = new RedBlackIntervalComparatorTree<>(); @Before public void setUp() { diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java similarity index 96% rename from jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java rename to jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java index db3a19e7562..44ce8110dad 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeTest.java @@ -10,7 +10,7 @@ import static org.junit.Assert.*; -public class RedBlackIntervalTreeStructureTest { +public class RedBlackIntervalTreeTest { List sorted = new LinkedList<>(); RedBlackIntervalTree, Integer>> tree = new RedBlackIntervalTree<>(); @@ -36,4 +36,5 @@ public void testInorder() { assertFalse(tree.contains(5)); assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); } + } \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java index d2c581e9eef..c7c842b868b 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java @@ -2,81 +2,124 @@ import org.junit.Before; import org.junit.Test; +import org.junit.rules.ExpectedException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.*; -/** - * Test important properties of red-black tree - */ public class RedBlackTreeTest { - private RedBlackTree redBlackTree = new RedBlackTree<>(); - - @Before - public void setUp() { - redBlackTree.insert(13, 13); - redBlackTree.insert(8, 8); - redBlackTree.insert(17, 17); - redBlackTree.insert(1, 1); - redBlackTree.insert(11, 11); - redBlackTree.insert(15, 15); - redBlackTree.insert(25, 25); - redBlackTree.insert(6, 6); - redBlackTree.insert(22, 22); - redBlackTree.insert(27, 27); - } - - /** - * The root is black - */ - @Test - public void testBlackRoot() { - assertFalse(redBlackTree.getRoot().isRed()); - } - - /** - * If a node is red, then both its children are black - */ - @Test - public void testBlackChildren() { - testBlackChildren(redBlackTree.getRoot()); - } - - private void testBlackChildren(Node currentNode) { - Node leftChild = currentNode.getLeftChild(); - if (leftChild != null) { - if (currentNode.isRed()) { - assertFalse(leftChild.isRed()); - } - testBlackChildren(leftChild); + private RedBlackTree redBlackTree = new RedBlackTree<>(); + + @Before + public void setUp() { + redBlackTree.insert(13, 13); + redBlackTree.insert(8, 8); + redBlackTree.insert(17, 17); + redBlackTree.insert(1, 1); + redBlackTree.insert(11, 11); + redBlackTree.insert(15, 15); + redBlackTree.insert(25, 25); + redBlackTree.insert(6, 6); + redBlackTree.insert(22, 22); + redBlackTree.insert(27, 27); + } + + @Test + public void testGet() { + assertEquals(8, redBlackTree.get(8).intValue()); + assertEquals(6, redBlackTree.get(6).intValue()); + assertNull(redBlackTree.get(30)); + assertNull(redBlackTree.get(35)); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetNegative() { + redBlackTree.get(null); + } + + @Test + public void testContains(){ + assertTrue(redBlackTree.contains(1)); + assertTrue(redBlackTree.contains(11)); + assertFalse(redBlackTree.contains(30)); + assertFalse(redBlackTree.contains(35)); + } + + @Test(expected = IllegalArgumentException.class) + public void testContainsNegative() { + redBlackTree.contains(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertNegative() { + redBlackTree.insert(null, null); + } + + @Test + public void testDelete() { + redBlackTree.delete(15); + redBlackTree.delete(15); + redBlackTree.delete(30); + redBlackTree.delete(35); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeleteNegative() { + redBlackTree.delete(null); + } + + // Test important properties of red-black tree + + /** + * The root is black + */ + @Test + public void testBlackRoot() { + assertFalse(redBlackTree.getRoot().isRed()); + } + + /** + * If a node is red, then both its children are black + */ + @Test + public void testBlackChildren() { + testBlackChildren(redBlackTree.getRoot()); + } + + private void testBlackChildren(Node currentNode) { + Node leftChild = currentNode.getLeftChild(); + if (leftChild != null) { + if (currentNode.isRed()) { + assertFalse(leftChild.isRed()); + } + testBlackChildren(leftChild); + } + + Node rightChild = currentNode.getRightChild(); + if (rightChild != null) { + if (currentNode.isRed()) { + assertFalse(rightChild.isRed()); + } + testBlackChildren(rightChild); + } + } + + /** + * Every path from a given node to any of its descendant leaves contains the same number of black nodes + */ + @Test + public void testBlackNodeNumber() { + assertEquals(countLeftChildren(redBlackTree.getRoot(), 0), countRightChildren(redBlackTree.getRoot(), 0)); + } + + private int countLeftChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); } - Node rightChild = currentNode.getRightChild(); - if (rightChild != null) { - if (currentNode.isRed()) { - assertFalse(rightChild.isRed()); - } - testBlackChildren(rightChild); + private int countRightChildren(Node node, int currentBlackNumber) { + currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; + return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); } - } - - /** - * Every path from a given node to any of its descendant leaves contains the same number of black nodes - */ - @Test - public void testBlackNodeNumber() { - assertEquals(countLeftChildren(redBlackTree.getRoot(), 0), countRightChildren(redBlackTree.getRoot(), 0)); - } - - private int countLeftChildren(Node node, int currentBlackNumber) { - currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; - return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); - } - - private int countRightChildren(Node node, int currentBlackNumber) { - currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; - return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); - } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java index 4baaa4dfe7e..9b62f675e30 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntegerIntervalTest.java @@ -7,26 +7,26 @@ public class IntegerIntervalTest { - IntegerInterval i00 = new IntegerInterval(0,0); - IntegerInterval i01 = new IntegerInterval(0,1); - IntegerInterval i56 = new IntegerInterval(5,6); + private IntegerInterval i00 = new IntegerInterval(0,0); + private IntegerInterval i01 = new IntegerInterval(0,1); + private IntegerInterval i56 = new IntegerInterval(5,6); @Test - public void isIntersecting() { + public void testIntersecting() { assertTrue(i00.isIntersecting(i01)); assertTrue(i01.isIntersecting(i01)); assertFalse(i56.isIntersecting(i01)); } @Test - public void contains() { + public void testContains() { assertTrue(i00.contains(0)); assertTrue(i01.contains(0)); assertFalse(i00.contains(1)); } @Test - public void compareTo() { + public void testCompareTo() { assertEquals(i00.compareTo(i01), 0); assertEquals(i01.compareTo(i00), 0); assertEquals(i56.compareTo(i01), 1); From 87a67e7dbf082a9f7c41eb97732ea79b9e600ee2 Mon Sep 17 00:00:00 2001 From: Jiong Fu Date: Fri, 4 May 2018 15:42:46 +0200 Subject: [PATCH 077/131] Fix NullPointerException in RedBlackTree --- .../jgrapht/intervalgraph/RedBlackTree.java | 39 +++++++++++-------- .../intervalgraph/RedBlackTreeTest.java | 3 ++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 9fc30447ee8..d12a49c5b55 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -22,6 +22,11 @@ public class RedBlackTree, V> protected Node root; + /** + * Get the root of the red-black tree + * + * @return the root of the red-black tree + */ public Node getRoot() { return root; } @@ -36,14 +41,11 @@ public Node getRoot() { @Override public V get(K key) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("Key cannot be null."); } - return searchNode(key).getVal(); - } - - private boolean isRed(Node node){ - return node != null && node.isRed(); + Node searchResult = searchNode(key); + return searchResult != null ? searchResult.getVal() : null; } /** @@ -55,11 +57,7 @@ private boolean isRed(Node node){ */ @Override public boolean contains(K key) { - if (key == null) { - throw new IllegalArgumentException("Key is null"); - } - - return searchNode(key) != null; + return get(key) != null; } /** @@ -73,7 +71,7 @@ public boolean contains(K key) { @Override public void insert(K key, V val) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("Key cannot be null."); } root = insert(root, key, val); @@ -118,7 +116,7 @@ protected Node insert(Node current, K key, V val) { @Override public void delete(K key) { if (key == null) { - throw new IllegalArgumentException("Key is null"); + throw new IllegalArgumentException("Key cannot be null."); } if (!contains(key)) { return; @@ -138,6 +136,10 @@ private boolean isEmpty() { return root == null; } + private boolean isRed(Node node){ + return node != null && node.isRed(); + } + protected Node delete(Node current, K key) { if (key.compareTo(current.getKey()) < 0) { if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { @@ -249,7 +251,6 @@ private Node deleteMax(Node node) { } node.setRightChild(deleteMax(node.getRightChild())); - return balance(node); } @@ -278,7 +279,6 @@ public K min() { if (isEmpty()) { throw new NoSuchElementException("empty tree"); } - return min(root).getKey(); } @@ -300,7 +300,6 @@ public K max() { if (isEmpty()) { throw new NoSuchElementException("empty tree"); } - return max(root.getRightChild()).getKey(); } @@ -308,7 +307,6 @@ private Node max(Node node) { if (node.getRightChild() == null) { return node; } - return max(node.getRightChild()); } @@ -450,8 +448,15 @@ private void changeColor(Node node) { node.getLeftChild().setRed(!isRed(node.getLeftChild())); } + /** + * Search tree node associated to the given key + * + * @param key the key of the tree node + * @return the tree node associated to the given key, null if the tree node doesn't exist + */ private Node searchNode(K key) { Node current = root; + while (current != null) { if (current.getKey().equals(key)) { return current; diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java index c7c842b868b..e604fcee95e 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackTreeTest.java @@ -57,8 +57,11 @@ public void testInsertNegative() { @Test public void testDelete() { + assertTrue(redBlackTree.contains(15)); redBlackTree.delete(15); redBlackTree.delete(15); + assertFalse(redBlackTree.contains(15)); + redBlackTree.delete(30); redBlackTree.delete(35); } From ca5d0eeb2f0b70498f0cf90bb93a6792d139f2a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 May 2018 15:59:25 +0200 Subject: [PATCH 078/131] rewrite constructor with initial vertices, init of asIntervalGraph() -> has to be finished --- .../jgrapht/intervalgraph/IntervalGraph.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index c6785303e14..0db6fd1ee27 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -194,16 +194,38 @@ private boolean addExistingIntervalEdges(V sourceVertex, V targetVertex, E edge) * @return interval graph representation if one exists, otherwise null */ public static , E, VertexType, T extends Comparable> - IntervalGraph asIntervalGraph(Graph graph) { + IntervalGraph asIntervalGraph(Graph graph) { + + + /* + IntervalGraphRecognizer intervalGraphRecognizer = new IntervalGraphRecongnizer(); + + if(!isIntervalGraph()) { + return null; + } + + ArrayList oldVertices = intervalGraphRecognizer.getIntervalGraphRepresentation(); ArrayList vertices = new ArrayList<>(); - Map, E> edges = new LinkedHashMap<>(); + Map, E> edges = new LinkedHashMap<>(); + + for(V vertex : vertices) { + for(Iterator it = graph.outgoingEdgesOf(vertex.getVertex()).iterator(); it.hasNext();) { + E edge = it.next(); + edges.put(Pair.of(vertex.getVertex(), graph.getEdgeTarget(edge)), edge); + } + } + // TODO Intervall-Graph-Test ausführen // TODO hier müssen noch die korrekten datenstrukturen vertices und edges brechnet werden!!! + + return new IntervalGraph<>(vertices, edges, (sourceVertex, targetVertex) -> graph.getEdgeFactory().createEdge(sourceVertex.getVertex(), targetVertex.getVertex()), graph.getType().isDirected(), graph.getType().isAllowingMultipleEdges(), graph.getType().isAllowingSelfLoops(), graph.getType().isWeighted()); + */ + return null; } @@ -541,7 +563,6 @@ public void setEdgeWeight(E e, double weight) @Override public GraphType getType() { - //TODO if (directed) { return new DefaultGraphType.Builder() .directed().weighted(weighted).allowMultipleEdges(allowingMultipleEdges) @@ -604,10 +625,12 @@ private boolean addIntervalEdges(V sourceVertex, Collection targetVertices) { for(V targetVertex: targetVertices) { assertVertexExist(targetVertex); - E e = edgeFactory.createEdge(sourceVertex, targetVertex); + if(!sourceVertex.equals(targetVertex)) { + E e = edgeFactory.createEdge(sourceVertex, targetVertex); - if(intrusiveEdgesSpecifics.add(e, sourceVertex, targetVertex)) { - specifics.addEdgeToTouchingVertices(e); + if (intrusiveEdgesSpecifics.add(e, sourceVertex, targetVertex)) { + specifics.addEdgeToTouchingVertices(e); + } } } return true; From 3149d457f2b0ae6747af80d57e3f117cca86ed58 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 4 May 2018 16:10:30 +0200 Subject: [PATCH 079/131] changed signature of interval graph constructors such that they are of undirected, simple, without self-loop type --- .../jgrapht/intervalgraph/IntervalGraph.java | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 0db6fd1ee27..44e3553503d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -47,24 +47,20 @@ public class IntervalGraph, E, * specified edge factory. * * @param ef the edge factory of the new graph. - * @param directed if true the graph will be directed, otherwise undirected - * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. - * @param allowLoops whether to allow edges that are self-loops or not. * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute * * @throws NullPointerException if the specified edge factory is * null. */ protected IntervalGraph( - EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, - boolean weighted) + EdgeFactory ef, boolean weighted) { Objects.requireNonNull(ef); this.edgeFactory = ef; - this.allowingLoops = allowLoops; - this.allowingMultipleEdges = allowMultipleEdges; - this.directed = directed; + this.allowingLoops = false; + this.allowingMultipleEdges = false; + this.directed = false; this.specifics = Objects.requireNonNull(createSpecifics(directed), GRAPH_SPECIFICS_MUST_NOT_BE_NULL); this.weighted = weighted; @@ -78,17 +74,13 @@ protected IntervalGraph( * * @param vertices initial vertices * @param ef the edge factory of the new graph. - * @param directed if true the graph will be directed, otherwise undirected - * @param allowMultipleEdges whether to allow multiple (parallel) edges or not. - * @param allowLoops whether to allow edges that are self-loops or not. * @param weighted whether the graph is weighted, i.e. the edges support a weight attribute * * @throws NullPointerException if the specified edge factory is * null. */ protected IntervalGraph( - ArrayList vertices, EdgeFactory ef, boolean directed, boolean allowMultipleEdges, boolean allowLoops, - boolean weighted) + ArrayList vertices, EdgeFactory ef, boolean weighted) { Objects.requireNonNull(ef); @@ -105,9 +97,9 @@ protected IntervalGraph( } this.edgeFactory = ef; - this.allowingLoops = allowLoops; - this.allowingMultipleEdges = allowMultipleEdges; - this.directed = directed; + this.allowingLoops = false; + this.allowingMultipleEdges = false; + this.directed = false; this.weighted = weighted; this.intrusiveEdgesSpecifics = Objects.requireNonNull( From 61d97483f4297104d38f4df96c5470667021eb06 Mon Sep 17 00:00:00 2001 From: Abdallah Date: Sun, 6 May 2018 18:47:21 +0200 Subject: [PATCH 080/131] Tests for IntervalGraph --- .../intervalgraph/IntervalGraphTest.java | 277 ++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java new file mode 100644 index 00000000000..b611eb77527 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java @@ -0,0 +1,277 @@ +package org.jgrapht.intervalgraph; + +import org.jgrapht.EdgeFactory; +import org.jgrapht.graph.ClassBasedEdgeFactory; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.intervalgraph.interval.Interval; +import org.jgrapht.intervalgraph.interval.IntervalVertex; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * @author Abdallah Atouani + * @since 02 May 2018 + */ +public class IntervalGraphTest { + + private IntervalGraph intervalGraph; + + @Before + public void setUp() { + EdgeFactory edgeFactory = new ClassBasedEdgeFactory<>(DefaultEdge.class); + intervalGraph = new IntervalGraph<>( + edgeFactory, false, false, false, false + ); + } + + @Test(expected = IllegalArgumentException.class) + public void addEdge() { + Interval interval1 = new Interval<>(1, 2); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(1, 10); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + intervalGraph.addEdge(vertex1, vertex2); + } + + @Test(expected = IllegalArgumentException.class) + public void removeEdge() { + Interval interval1 = new Interval<>(1, 2); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(1, 10); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + intervalGraph.removeEdge(vertex1, vertex2); + } + + @Test + public void containsEdge() { + Interval interval1 = new Interval<>(5, 19); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(9, 100); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(6, 11); + IntervalVertex vertex3 = IntervalVertex.of(3, interval3); + intervalGraph.addVertex(vertex3); + + Interval interval4 = new Interval<>(1000, 1001); + IntervalVertex vertex4 = IntervalVertex.of(4, interval4); + intervalGraph.addVertex(vertex4); + + assertTrue(intervalGraph.containsEdge(vertex2, vertex1)); + assertTrue(intervalGraph.containsEdge(vertex1, vertex2)); + assertTrue(intervalGraph.containsEdge(vertex1, vertex3)); + assertTrue(intervalGraph.containsEdge(vertex3, vertex1)); + assertTrue(intervalGraph.containsEdge(vertex2, vertex3)); + assertTrue(intervalGraph.containsEdge(vertex3, vertex2)); + assertFalse(intervalGraph.containsEdge(vertex1, vertex4)); + assertFalse(intervalGraph.containsEdge(vertex2, vertex4)); + assertFalse(intervalGraph.containsEdge(vertex3, vertex4)); + + /* + assertFalse(intervalGraph.containsEdge(vertex1, vertex1)); + assertFalse(intervalGraph.containsEdge(vertex2, vertex2)); + assertFalse(intervalGraph.containsEdge(vertex3, vertex3)); + assertFalse(intervalGraph.containsEdge(vertex4, vertex4)); + */ + } + + @Test + public void addVertex() { + Interval interval1 = new Interval<>(1, 2); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + IntervalVertex vertex2 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex2); + + assertTrue(intervalGraph.vertexSet().contains(vertex1)); + assertTrue(intervalGraph.vertexSet().contains(vertex2)); + assertEquals(intervalGraph.vertexSet().size(), 1); + + IntervalVertex vertex3 = IntervalVertex.of(2, interval1); + intervalGraph.addVertex(vertex3); + + assertTrue(intervalGraph.vertexSet().contains(vertex3)); + assertEquals(intervalGraph.vertexSet().size(), 2); + + Interval interval2 = new Interval<>(2, 10); + IntervalVertex vertex4 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex4); + + assertTrue(intervalGraph.vertexSet().contains(vertex4)); + assertEquals(intervalGraph.vertexSet().size(), 3); + } + + @Test + public void removeVertex() { + Interval interval1 = new Interval<>(3, 20); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(4, 100); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + assertTrue(intervalGraph.vertexSet().contains(vertex1)); + assertTrue(intervalGraph.vertexSet().contains(vertex2)); + + intervalGraph.removeVertex(vertex1); + + assertTrue(intervalGraph.vertexSet().contains(vertex2)); + assertFalse(intervalGraph.vertexSet().contains(vertex1)); + + assertEquals(intervalGraph.vertexSet().size(), 1); + + intervalGraph.removeVertex(vertex2); + + assertFalse(intervalGraph.vertexSet().contains(vertex1)); + assertFalse(intervalGraph.vertexSet().contains(vertex2)); + + assertEquals(intervalGraph.vertexSet().size(), 0); + } + + @Test + public void containsVertex() { + Interval interval1 = new Interval<>(8, 9); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(27, 56); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + assertTrue(intervalGraph.containsVertex(vertex1)); + assertTrue(intervalGraph.containsVertex(vertex2)); + assertEquals(intervalGraph.vertexSet().size(), 2); + + intervalGraph.removeVertex(vertex1); + + assertFalse(intervalGraph.containsVertex(vertex1)); + assertTrue(intervalGraph.containsVertex(vertex2)); + assertEquals(intervalGraph.vertexSet().size(), 1); + } + + @Test + public void getEdgeSource() { + Interval interval1 = new Interval<>(10, 14); + IntervalVertex vertex1 = IntervalVertex.of(2, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(1, 18); + IntervalVertex vertex2 = IntervalVertex.of(1, interval2); + intervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(-3, 2); + IntervalVertex vertex3 = IntervalVertex.of(3, interval3); + intervalGraph.addVertex(vertex3); + + DefaultEdge edge = intervalGraph.getEdge(vertex1, vertex2); + DefaultEdge edge1 = intervalGraph.getEdge(vertex2, vertex3); + + assertEquals(intervalGraph.getEdgeSource(edge), vertex2); + assertEquals(intervalGraph.getEdgeSource(edge1), vertex3); + } + + @Test + public void getEdgeTarget() { + Interval interval1 = new Interval<>(2, 4); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(1, 7); + IntervalVertex vertex2 = IntervalVertex.of(3, interval2); + intervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(0, 4); + IntervalVertex vertex3 = IntervalVertex.of(2, interval3); + intervalGraph.addVertex(vertex3); + + DefaultEdge edge = intervalGraph.getEdge(vertex1, vertex2); + DefaultEdge edge1 = intervalGraph.getEdge(vertex2, vertex3); + + assertEquals(intervalGraph.getEdgeTarget(edge), vertex1); + assertEquals(intervalGraph.getEdgeTarget(edge1), vertex2); + + } + + @Test + public void edgeSet() { + Interval interval1 = new Interval<>(29, 30); + IntervalVertex vertex1 = IntervalVertex.of(3, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(27, 56); + IntervalVertex vertex2 = IntervalVertex.of(1, interval2); + intervalGraph.addVertex(vertex2); + + assertEquals(intervalGraph.edgeSet().size(), 2); + + } + + @Test + public void vertexSet() { + Interval interval1 = new Interval<>(-10, 1); + IntervalVertex vertex1 = IntervalVertex.of(29, interval1); + intervalGraph.addVertex(vertex1); + + assertTrue(intervalGraph.vertexSet().contains(vertex1)); + + Interval interval2 = new Interval<>(-38, 0); + IntervalVertex vertex2 = IntervalVertex.of(1, interval2); + intervalGraph.addVertex(vertex2); + + assertTrue(intervalGraph.vertexSet().contains(vertex1)); + assertTrue(intervalGraph.vertexSet().contains(vertex2)); + + Interval interval3 = new Interval<>(100, 293); + IntervalVertex vertex3 = IntervalVertex.of(1, interval3); + intervalGraph.addVertex(vertex3); + + assertTrue(intervalGraph.vertexSet().contains(vertex1)); + assertTrue(intervalGraph.vertexSet().contains(vertex2)); + assertTrue(intervalGraph.vertexSet().contains(vertex3)); + + intervalGraph.removeVertex(vertex2); + intervalGraph.removeVertex(vertex3); + + assertTrue(intervalGraph.vertexSet().contains(vertex1)); + assertFalse(intervalGraph.vertexSet().contains(vertex2)); + assertFalse(intervalGraph.vertexSet().contains(vertex3)); + } + + @Test + public void getEdgeWeight() { + Interval interval1 = new Interval<>(-3, 1); + IntervalVertex vertex1 = IntervalVertex.of(29, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(0, 3); + IntervalVertex vertex2 = IntervalVertex.of(7, interval2); + intervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(1, 29); + IntervalVertex vertex3 = IntervalVertex.of(9, interval3); + intervalGraph.addVertex(vertex3); + + DefaultEdge edge = intervalGraph.getEdge(vertex3, vertex1); + DefaultEdge edge1 = intervalGraph.getEdge(vertex2, vertex1); + + assertEquals(intervalGraph.getEdgeWeight(edge), 1, 0); + assertEquals(intervalGraph.getEdgeWeight(edge1), 1, 0); + } + + +} \ No newline at end of file From 2bb071e80a836096dcf41dfaf5ab3c7507745308 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 14:03:21 +0200 Subject: [PATCH 081/131] Implement the required interface to build an interval graph --- .../IntervalGraphRecognizer.java | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 41f29123185..3ddffcdfab8 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -5,6 +5,8 @@ import java.util.*; import org.jgrapht.*; +import org.jgrapht.graph.ClassBasedEdgeFactory; +import org.jgrapht.graph.DefaultEdge; import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; @@ -41,14 +43,15 @@ public final class IntervalGraphRecognizer * Stores the computed interval graph representation (or null if no such representation * exists) of the graph. */ - private Graph intervalRepresentation; // TODO: change to work with an actual interval - // graph after merge + private List> intervalsSortedByStartingPoint; + private Map, V> intervalVertexMap; /** * Creates (and runs) a new interval graph recognizer for the given graph. * * @param graph the graph to be tested. */ + @SuppressWarnings({"unchecked"}) public IntervalGraphRecognizer(Graph graph) { this.isIntervalGraph = isIntervalGraph(graph); @@ -113,7 +116,6 @@ public boolean isIntervalGraph(Graph graph) if (isIOrdering(sweepZeta, graph)) { - // Compute interval representation -- TODO: complete after merge HashMap neighborIndex = new HashMap<>(); for (V vertex : graph.vertexSet()) { int maxNeighbor = 0; @@ -128,32 +130,33 @@ public boolean isIntervalGraph(Graph graph) neighborIndex.put(vertex, maxNeighbor); } - HashMap> intervals = new HashMap<>(graph.vertexSet().size()); - ArrayList> sortedIntervals = + Interval[] intervals = (Interval[])new Object[graph.vertexSet().size()]; + this.intervalsSortedByStartingPoint = new ArrayList<>(graph.vertexSet().size()); + // Initialize the vertex map. Because we know the number of vertices we can make sure the hashmap does not + // need to rehash by setting the capacity to the number of vertices divided by the default load factor + // of 0.75. + this.intervalVertexMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); + // Compute intervals and store them associated by their starting point ... for (V vertex : graph.vertexSet()) { Interval vertexInterval = new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); - intervals.put(sweepZeta.get(vertex), vertexInterval); + intervals[sweepZeta.get(vertex)] = vertexInterval) + + this.intervalVertexMap.put(vertexInterval, vertex); } // ... and produce a list sorted by the starting points for an efficient construction of // the graph for (int i = 0; i < graph.vertexSet().size(); i++) { - sortedIntervals.add(intervals.get(i)); + this.intervalsSortedByStartingPoint.add(intervals[i]); } - // TODO: build the actual interval graph - this.intervalRepresentation = null; - return true; } else { - // set values negatively - this.intervalRepresentation = null; - return false; } } @@ -242,13 +245,22 @@ public boolean isIntervalGraph() } /** - * Returns an interval graph representation of the graph. + * Returns the list of all intervals sorted by starting point, or null, if the graph was not an interval graph. + * + * @return The list of all intervals sorted by starting point, or null, if the graph was not an interval graph. + */ + public List> getIntervalsSortedByStartingPoint() + { + return this.intervalsSortedByStartingPoint; + } + + /** + * Returns a mapping of the constructed intervals to the vertices of the original graph, or null, if the graph was not an interval graph. * - * @return an interval graph representation of the graph or null if the graph is not an - * interval graph. + * @return A mapping of the constructed intervals to the vertices of the original graph, or null, if the graph was not an interval graph. */ - public Graph getIntervalGraphRepresentation() + public Map, V> getIntervalVertexMap() { - return intervalRepresentation; + return this.intervalVertexMap; } } From a1a37d450dae2178bc65a90ac7322058425f03a9 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 14:22:56 +0200 Subject: [PATCH 082/131] Add a mapping from the vertices to the intervals --- .../intervalgraph/IntervalGraphRecognizer.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 3ddffcdfab8..1943245076f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -45,6 +45,7 @@ public final class IntervalGraphRecognizer */ private List> intervalsSortedByStartingPoint; private Map, V> intervalVertexMap; + private Map> vertexIntervalMap; /** * Creates (and runs) a new interval graph recognizer for the given graph. @@ -138,15 +139,17 @@ public boolean isIntervalGraph(Graph graph) // need to rehash by setting the capacity to the number of vertices divided by the default load factor // of 0.75. this.intervalVertexMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); + this.vertexIntervalMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); // Compute intervals and store them associated by their starting point ... for (V vertex : graph.vertexSet()) { Interval vertexInterval = new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); - intervals[sweepZeta.get(vertex)] = vertexInterval) + intervals[sweepZeta.get(vertex)] = vertexInterval); this.intervalVertexMap.put(vertexInterval, vertex); + this.vertexIntervalMap.put(vertex, vertexInterval); } // ... and produce a list sorted by the starting points for an efficient construction of @@ -263,4 +266,14 @@ public Map, V> getIntervalVertexMap() { return this.intervalVertexMap; } + + /** + * Returns a mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. + * + * @return A mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. + */ + public Map> getVertexIntervalMap() + { + return this.vertexIntervalMap; + } } From 75fdc976a1360dfc3cfad1c8d4465dd72cc5b9bf Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 14:26:26 +0200 Subject: [PATCH 083/131] Make the isIntervalGraph method private --- .../jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 1943245076f..6619d362f35 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -63,7 +63,7 @@ public IntervalGraphRecognizer(Graph graph) * * @return */ - public boolean isIntervalGraph(Graph graph) + private boolean isIntervalGraph(Graph graph) { // An empty graph is an interval graph. @@ -146,7 +146,7 @@ public boolean isIntervalGraph(Graph graph) Interval vertexInterval = new Interval<>(sweepZeta.get(vertex), neighborIndex.get(vertex)); - intervals[sweepZeta.get(vertex)] = vertexInterval); + intervals[sweepZeta.get(vertex)] = vertexInterval; this.intervalVertexMap.put(vertexInterval, vertex); this.vertexIntervalMap.put(vertex, vertexInterval); From c95fd67b004a882a999deb2d1587575e9c89caa8 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 14:34:23 +0200 Subject: [PATCH 084/131] Return interval vertices instead of intervals --- .../jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 6619d362f35..5504e9bb316 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -45,7 +45,7 @@ public final class IntervalGraphRecognizer */ private List> intervalsSortedByStartingPoint; private Map, V> intervalVertexMap; - private Map> vertexIntervalMap; + private Map> vertexIntervalMap; /** * Creates (and runs) a new interval graph recognizer for the given graph. @@ -149,7 +149,7 @@ private boolean isIntervalGraph(Graph graph) intervals[sweepZeta.get(vertex)] = vertexInterval; this.intervalVertexMap.put(vertexInterval, vertex); - this.vertexIntervalMap.put(vertex, vertexInterval); + this.vertexIntervalMap.put(vertex, IntervalVertex.of(vertex, vertexInterval)); } // ... and produce a list sorted by the starting points for an efficient construction of @@ -272,7 +272,7 @@ public Map, V> getIntervalVertexMap() * * @return A mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. */ - public Map> getVertexIntervalMap() + public Map> getVertexIntervalMap() { return this.vertexIntervalMap; } From 1ee683c9e74e8148f862dd7c8499d2db3d3609a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2018 17:05:50 +0200 Subject: [PATCH 085/131] finished asIntervalGraph(Graph) --- .../jgrapht/intervalgraph/IntervalGraph.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 44e3553503d..42d96f467a2 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -187,36 +187,37 @@ private boolean addExistingIntervalEdges(V sourceVertex, V targetVertex, E edge) */ public static , E, VertexType, T extends Comparable> IntervalGraph asIntervalGraph(Graph graph) { +/* + IntervalGraphRecognizer intervalGraphRecognizer = new IntervalGraphRecongnizer(Graph intervalGraphRecognizer = new IntervalGraphRecongnizer(); + ArrayList> sortedIntervalList = intervalGraphRecognizer.getIntervalsSortedByStartingPoint(); + Map, VertexType> intervalVertexMap = intervalGraphRecognizer.getIntervalVertexMap(); + Map vertexIntervalMap = intervalGraphRecognizer.getVertexIntervalMap(); - if(!isIntervalGraph()) { - return null; + ArrayList vertices = new ArrayList<>(sortedIntervalList.size()); + + for(int i = 0; i < sortedIntervalList.size(); ++i) { + vertices.add(i, vertexIntervalMap.get(intervalVertexMap.get(sortedIntervalList.get(i)))); } - ArrayList oldVertices = intervalGraphRecognizer.getIntervalGraphRepresentation(); - ArrayList vertices = new ArrayList<>(); - Map, E> edges = new LinkedHashMap<>(); + Map, E> edges = new LinkedHashMap<>(); for(V vertex : vertices) { for(Iterator it = graph.outgoingEdgesOf(vertex.getVertex()).iterator(); it.hasNext();) { E edge = it.next(); - edges.put(Pair.of(vertex.getVertex(), graph.getEdgeTarget(edge)), edge); + edges.put(Pair.of(vertex, vertexIntervalMap.get(graph.getEdgeTarget(edge))), edge); } } - // TODO Intervall-Graph-Test ausführen - // TODO hier müssen noch die korrekten datenstrukturen vertices und edges brechnet werden!!! - - - return new IntervalGraph<>(vertices, edges, (sourceVertex, targetVertex) -> graph.getEdgeFactory().createEdge(sourceVertex.getVertex(), targetVertex.getVertex()), graph.getType().isDirected(), graph.getType().isAllowingMultipleEdges(), graph.getType().isAllowingSelfLoops(), graph.getType().isWeighted()); - */ + */ return null; } From 87d58672d23247ed3df45f03c99ed4fbd9b245dc Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 17:20:00 +0200 Subject: [PATCH 086/131] Address PR feedback --- .../IntervalGraphRecognizer.java | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 5504e9bb316..562edb87de5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -5,9 +5,6 @@ import java.util.*; import org.jgrapht.*; -import org.jgrapht.graph.ClassBasedEdgeFactory; -import org.jgrapht.graph.DefaultEdge; -import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; /** @@ -43,9 +40,9 @@ public final class IntervalGraphRecognizer * Stores the computed interval graph representation (or null if no such representation * exists) of the graph. */ - private List> intervalsSortedByStartingPoint; - private Map, V> intervalVertexMap; - private Map> vertexIntervalMap; + private ArrayList> intervalsSortedByStartingPoint; + private Map, V> intervalToVertexMap; + private Map> vertexToIntervalMap; /** * Creates (and runs) a new interval graph recognizer for the given graph. @@ -138,8 +135,8 @@ private boolean isIntervalGraph(Graph graph) // Initialize the vertex map. Because we know the number of vertices we can make sure the hashmap does not // need to rehash by setting the capacity to the number of vertices divided by the default load factor // of 0.75. - this.intervalVertexMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); - this.vertexIntervalMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); + this.intervalToVertexMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); + this.vertexToIntervalMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); // Compute intervals and store them associated by their starting point ... for (V vertex : graph.vertexSet()) { @@ -148,8 +145,8 @@ private boolean isIntervalGraph(Graph graph) intervals[sweepZeta.get(vertex)] = vertexInterval; - this.intervalVertexMap.put(vertexInterval, vertex); - this.vertexIntervalMap.put(vertex, IntervalVertex.of(vertex, vertexInterval)); + this.intervalToVertexMap.put(vertexInterval, vertex); + this.vertexToIntervalMap.put(vertex, IntervalVertex.of(vertex, vertexInterval)); } // ... and produce a list sorted by the starting points for an efficient construction of @@ -252,7 +249,7 @@ public boolean isIntervalGraph() * * @return The list of all intervals sorted by starting point, or null, if the graph was not an interval graph. */ - public List> getIntervalsSortedByStartingPoint() + public ArrayList> getIntervalsSortedByStartingPoint() { return this.intervalsSortedByStartingPoint; } @@ -262,9 +259,9 @@ public List> getIntervalsSortedByStartingPoint() * * @return A mapping of the constructed intervals to the vertices of the original graph, or null, if the graph was not an interval graph. */ - public Map, V> getIntervalVertexMap() + public Map, V> getIntervalToVertexMap() { - return this.intervalVertexMap; + return this.intervalToVertexMap; } /** @@ -272,8 +269,8 @@ public Map, V> getIntervalVertexMap() * * @return A mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. */ - public Map> getVertexIntervalMap() + public Map> getVertexToIntervalMap() { - return this.vertexIntervalMap; + return this.vertexToIntervalMap; } } From 1f2404cd16765d85e87d2bdbbc964d7ddea5f76c Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 19:48:50 +0200 Subject: [PATCH 087/131] Remove old comments --- .../jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java | 5 ----- .../java/org/jgrapht/intervalgraph/BinarySearchTree.java | 2 +- .../java/org/jgrapht/intervalgraph/IntervalGraphTest.java | 4 +--- .../org/jgrapht/intervalgraph/IntervalTreeStructureTest.java | 2 +- .../jgrapht/intervalgraph/RedBlackComparatorTreeTest.java | 2 +- .../intervalgraph/RedBlackIntervalComparatorTreeTest.java | 2 +- .../intervalgraph/RedBlackIntervalTreeStructureTest.java | 2 +- .../intervalgraph/interval/IntervalGraphRecognizerTest.java | 2 +- 8 files changed, 7 insertions(+), 14 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 562edb87de5..2f860d2746d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -92,16 +92,11 @@ private boolean isIntervalGraph(Graph graph) // sweep HashMap sweepDelta = lexBreadthFirstSearchPlus(graph, sweepGamma); - // Additionally, calculate the index and the corresponding A set for each vertex - // Step 5 - LBFS+ from the last vertex of the previous sweep // Input - the result of previous sweep delta, vertex d // Output - the result of current sweep epsilon, further last vertex e visited by current // sweep HashMap sweepEpsilon = lexBreadthFirstSearchPlus(graph, sweepDelta); - // V vertexE = lastElementOf(sweepEpsilon); TODO: not used? - - // Additionally, calculate the index and the corresponding B set for each vertex // Step 6 - LBFS* with the resulting sweeps // Input - the result of sweep gamma and sweep epsilon diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java index 8578d1cc370..e25645ebae5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/BinarySearchTree.java @@ -181,4 +181,4 @@ public interface BinarySearchTree { * is null */ int size(K min, K max); -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java index b611eb77527..e995dc0bcdf 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java @@ -272,6 +272,4 @@ public void getEdgeWeight() { assertEquals(intervalGraph.getEdgeWeight(edge), 1, 0); assertEquals(intervalGraph.getEdgeWeight(edge1), 1, 0); } - - -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java index bb24b3165fe..9bcd79ab6c4 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalTreeStructureTest.java @@ -36,4 +36,4 @@ public void testIntervalOverlap() { assertEquals(0, tree.overlapsWith(new IntegerInterval(-3, -1)).size()); assertEquals(20, tree.overlapsWith(new IntegerInterval(-5, 20)).size()); } -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java index 38056c076cf..5d9d4dcde78 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java @@ -36,4 +36,4 @@ public void testContains() { assertFalse(tree.contains(73)); assertFalse(tree.contains(200)); } -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java index 3da0ba50ef1..6d241b0cc92 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java @@ -38,4 +38,4 @@ public void testInorder() { assertFalse(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); } -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java index e0cdde85997..a4a0fbda55c 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalTreeStructureTest.java @@ -49,4 +49,4 @@ private Comparator> getComparator() { } }; } -} \ No newline at end of file +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 99da92d109d..27dee98b15d 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -239,4 +239,4 @@ public void linearGraphTest() } } -} \ No newline at end of file +} From cc59205fde8bb312c2c8a1d1ef32bf17c2be4575 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Mon, 7 May 2018 19:59:53 +0200 Subject: [PATCH 088/131] again changed some interfaces --- .../CordalgraphDecomposition.java | 19 ------------ .../IntervalgraphDecomposition.java | 29 +++++++++---------- .../treedecomposition/TreeDecomposition.java | 10 ------- .../IntervalgraphDecompositionTest.java | 19 +++++++----- 4 files changed, 25 insertions(+), 52 deletions(-) delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java deleted file mode 100644 index 764f805aabb..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/CordalgraphDecomposition.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.jgrapht.alg.treedecomposition; - -import java.util.*; - -import org.jgrapht.*; -import org.jgrapht.graph.*; - -public class CordalgraphDecomposition - implements TreeDecomposition -{ - - @Override - public Graph,DefaultEdge> getTreeDecomposition() - { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index 5a960429d28..3e283b13f88 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -7,14 +7,13 @@ import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; -public class IntervalgraphDecomposition> - implements TreeDecomposition +public class IntervalgraphDecomposition> { - private Graph>,DefaultEdge> treeDecomposition = null; - private Set> currentVertex = null; + private Graph>, DefaultEdge> treeDecomposition = null; + private Set> currentVertex = null; private List> startSort, endSort; - public IntervalgraphDecomposition(Graph graph) + public IntervalgraphDecomposition(Graph graph) { throw new UnsupportedOperationException("Not yet implemented"); //TODO @@ -46,41 +45,41 @@ private void computeTreeDecomposition() while(endSort.get(endIndex).getInterval().getEnd().compareTo( iv.getInterval().getStart()) < 0) { - addForget(endSort.get(endIndex).getVertex()); + addForget(endSort.get(endIndex)); endIndex++; } - addIntroduce(iv.getVertex()); + addIntroduce(iv); } } private void initTreeDecomposition() { - treeDecomposition = new DefaultUndirectedGraph,DefaultEdge>(DefaultEdge.class); - Set root = new HashSet(0); + treeDecomposition = new DefaultUndirectedGraph>,DefaultEdge>(DefaultEdge.class); + Set> root = new HashSet>(0); treeDecomposition.addVertex(root); currentVertex = root; } - private void addIntroduce(V vertex) + private void addIntroduce(IntervalVertex vertex) { - Set nextVertex = new HashSet(currentVertex); + Set> nextVertex = new HashSet>(currentVertex); nextVertex.add(vertex); treeDecomposition.addVertex(nextVertex); treeDecomposition.addEdge(currentVertex, nextVertex); currentVertex = nextVertex; } - private void addForget(V vertex) + private void addForget(IntervalVertex vertex) { - Set nextVertex = new HashSet(currentVertex); + Set> nextVertex = new HashSet>(currentVertex); nextVertex.remove(vertex); treeDecomposition.addVertex(nextVertex); treeDecomposition.addEdge(currentVertex, nextVertex); currentVertex = nextVertex; } - @Override - public Graph,DefaultEdge> getTreeDecomposition() + + public Graph>,DefaultEdge> getTreeDecomposition() { computeTreeDecomposition(); return treeDecomposition; diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java deleted file mode 100644 index 62661d0ec52..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/TreeDecomposition.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.jgrapht.alg.treedecomposition; - -import java.util.*; -import org.jgrapht.*; -import org.jgrapht.graph.*; - -public interface TreeDecomposition -{ - Graph,DefaultEdge> getTreeDecomposition(); -} diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index 972805dc855..d14e24e8830 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -16,28 +16,31 @@ public class IntervalgraphDecompositionTest { @Test - public void testIntervalgraphDecompositionGraphOfVE() + public void testIntervalgraphDecompositionForRegularGraphs() { Graph g = new DefaultUndirectedGraph<>(DefaultEdge.class); //TODO: change g - IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(g); - Graph,DefaultEdge> decomp = decompositionAlg.getTreeDecomposition(); + //IntervalgraphDecomposition> decompositionAlg = new IntervalgraphDecomposition<>(g); + //Graph,DefaultEdge> decomp = decompositionAlg.getTreeDecomposition(); //TODO: test here - assertNotEquals(decomp,decomp); + //assertNotEquals(decomp,decomp); } @Test - public void testIntervalgraphDecompositionIntervalGraphOfIntervalVertexInterfaceOfVTE() + public void testIntervalgraphDecompositionForIntervalGraphs() { IntervalGraphInterface ig = new CenteredIntervalTree<>(); //TODO: change ig - IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(ig); + //IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(ig); } @Test - public void testIntervalgraphDecompositionListOfIntervalVertexOfVT() + public void testIntervalgraphDecompositionForIntervalLists() { - fail("Not yet implemented"); + List> list = new ArrayList>(); + for(int i = 0; i<1; i++) + { + } } @Test From 3f55e9dd4b868347faa8fafa87c411dc31174797 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 20:15:33 +0200 Subject: [PATCH 089/131] Fix that the code does not compile --- .../java/org/jgrapht/intervalgraph/IntervalGraphTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java index e995dc0bcdf..f3f219599d2 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java @@ -5,6 +5,7 @@ import org.jgrapht.graph.DefaultEdge; import org.jgrapht.intervalgraph.interval.Interval; import org.jgrapht.intervalgraph.interval.IntervalVertex; +import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; import org.junit.Before; import org.junit.Test; @@ -16,13 +17,13 @@ */ public class IntervalGraphTest { - private IntervalGraph intervalGraph; + private IntervalGraph, DefaultEdge, Integer, Integer> intervalGraph; @Before public void setUp() { - EdgeFactory edgeFactory = new ClassBasedEdgeFactory<>(DefaultEdge.class); + EdgeFactory, DefaultEdge> edgeFactory = new ClassBasedEdgeFactory<>(DefaultEdge.class); intervalGraph = new IntervalGraph<>( - edgeFactory, false, false, false, false + edgeFactory, false ); } From e6ce44f1ca857edd46be1feda41649b1635459bc Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 20:35:34 +0200 Subject: [PATCH 090/131] Fix failing tests --- .../alg/intervalgraph/IntervalGraphRecognizer.java | 3 ++- .../intervalgraph/CenteredIntervalTreeStructureTest.java | 4 ++-- .../jgrapht/intervalgraph/CenteredIntervalTreeTest.java | 4 ++-- .../java/org/jgrapht/intervalgraph/IntervalGraphTest.java | 2 +- .../jgrapht/intervalgraph/RedBlackComparatorTreeTest.java | 8 +++++++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 2f860d2746d..048b0d7e1fd 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -2,6 +2,7 @@ import static org.jgrapht.alg.intervalgraph.LexBreadthFirstSearch.*; +import java.lang.reflect.Array; import java.util.*; import org.jgrapht.*; @@ -123,7 +124,7 @@ private boolean isIntervalGraph(Graph graph) neighborIndex.put(vertex, maxNeighbor); } - Interval[] intervals = (Interval[])new Object[graph.vertexSet().size()]; + Interval[] intervals = (Interval[])Array.newInstance(Interval.class, graph.vertexSet().size()); this.intervalsSortedByStartingPoint = new ArrayList<>(graph.vertexSet().size()); diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java index 12a2f6db49f..3c040a062ae 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeStructureTest.java @@ -17,10 +17,10 @@ public class CenteredIntervalTreeStructureTest { @Test public void testCompareToPoint() { IntegerInterval interval = new IntegerInterval(0, 1); - assertEquals(-1, interval.compareToPoint(-1)); + assertEquals(1, interval.compareToPoint(-1)); assertEquals(0, interval.compareToPoint(0)); assertEquals(0, interval.compareToPoint(1)); - assertEquals(1, interval.compareToPoint(2)); + assertEquals(-1, interval.compareToPoint(2)); } @Test diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java index 1a813030206..986d5c75393 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/CenteredIntervalTreeTest.java @@ -17,10 +17,10 @@ public class CenteredIntervalTreeTest { @Test public void testCompareToPoint() { IntegerInterval interval = new IntegerInterval(0, 1); - assertEquals(-1, interval.compareToPoint(-1)); + assertEquals(1, interval.compareToPoint(-1)); assertEquals(0, interval.compareToPoint(0)); assertEquals(0, interval.compareToPoint(1)); - assertEquals(1, interval.compareToPoint(2)); + assertEquals(-1, interval.compareToPoint(2)); } @Test diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java index f3f219599d2..5778b8f466d 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java @@ -218,7 +218,7 @@ public void edgeSet() { IntervalVertex vertex2 = IntervalVertex.of(1, interval2); intervalGraph.addVertex(vertex2); - assertEquals(intervalGraph.edgeSet().size(), 2); + assertEquals(1, intervalGraph.edgeSet().size()); } diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java index 5d9d4dcde78..6e3f447775d 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java @@ -22,9 +22,15 @@ public void setUp() throws Exception { @Test public void isOrdered() { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 5; i++) { assertEquals(i, (int) tree.inorderValues().get(i)); } + for (int i = 6; i < 73; i++) { + assertEquals(i, (int) tree.inorderValues().get(i - 1)); + } + for (int i = 74; i < 100; i++) { + assertEquals(i, (int) tree.inorderValues().get(i - 2)); + } } @Test From a211849d3613ee21c8296d1abb725c197dda60e7 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Mon, 7 May 2018 20:45:10 +0200 Subject: [PATCH 091/131] Use interval as vertex added first test method, which tests that the result is a nice tree decomposition if it is a tree decomposition --- .../IntervalgraphDecomposition.java | 49 +++++++++-------- .../IntervalgraphDecompositionTest.java | 55 ++++++++++++++++++- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index 3e283b13f88..17e4ef1fdff 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -7,13 +7,13 @@ import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; -public class IntervalgraphDecomposition> +public class IntervalgraphDecomposition> { - private Graph>, DefaultEdge> treeDecomposition = null; - private Set> currentVertex = null; - private List> startSort, endSort; + private Graph>, DefaultEdge> treeDecomposition = null; + private Set> currentVertex, root = null; + private List> startSort, endSort; - public IntervalgraphDecomposition(Graph graph) + public IntervalgraphDecomposition(Graph graph) { throw new UnsupportedOperationException("Not yet implemented"); //TODO @@ -25,7 +25,7 @@ public IntervalgraphDecomposition(IntervalGraphInterface graph) //TODO } - public IntervalgraphDecomposition(List> intervals) + public IntervalgraphDecomposition(List> intervals) { startSort = new ArrayList<>(intervals); endSort = new ArrayList<>(intervals); @@ -41,9 +41,9 @@ private void computeTreeDecomposition() initTreeDecomposition(); int endIndex=0; - for(IntervalVertex iv: startSort) { - while(endSort.get(endIndex).getInterval().getEnd().compareTo( - iv.getInterval().getStart()) < 0) + for(Interval iv: startSort) { + while(endSort.get(endIndex).getEnd().compareTo( + iv.getStart()) < 0) { addForget(endSort.get(endIndex)); endIndex++; @@ -54,24 +54,24 @@ private void computeTreeDecomposition() private void initTreeDecomposition() { - treeDecomposition = new DefaultUndirectedGraph>,DefaultEdge>(DefaultEdge.class); - Set> root = new HashSet>(0); + treeDecomposition = new DefaultDirectedGraph>,DefaultEdge>(DefaultEdge.class); + root = new HashSet>(0); treeDecomposition.addVertex(root); currentVertex = root; } - private void addIntroduce(IntervalVertex vertex) + private void addIntroduce(Interval vertex) { - Set> nextVertex = new HashSet>(currentVertex); + Set> nextVertex = new HashSet>(currentVertex); nextVertex.add(vertex); treeDecomposition.addVertex(nextVertex); treeDecomposition.addEdge(currentVertex, nextVertex); currentVertex = nextVertex; } - private void addForget(IntervalVertex vertex) + private void addForget(Interval vertex) { - Set> nextVertex = new HashSet>(currentVertex); + Set> nextVertex = new HashSet>(currentVertex); nextVertex.remove(vertex); treeDecomposition.addVertex(nextVertex); treeDecomposition.addEdge(currentVertex, nextVertex); @@ -79,15 +79,21 @@ private void addForget(IntervalVertex vertex) } - public Graph>,DefaultEdge> getTreeDecomposition() + public Graph>,DefaultEdge> getTreeDecomposition() { - computeTreeDecomposition(); + if(treeDecomposition == null) computeTreeDecomposition(); return treeDecomposition; } + public Set> getRoot() + { + if(root == null) computeTreeDecomposition(); + return root; + } - private class IntervalVertexComparator implements Comparator> { + + private class IntervalVertexComparator implements Comparator> { private boolean start = true;; @@ -96,13 +102,12 @@ public IntervalVertexComparator(boolean startKey) { } @Override - public int compare(IntervalVertex o1, IntervalVertex o2) + public int compare(Interval o1, Interval o2) { if(start) - return o1.getInterval().getStart().compareTo(o2.getInterval().getStart()); + return o1.getStart().compareTo(o2.getStart()); else - return o1.getInterval().getEnd().compareTo(o2.getInterval().getEnd()); + return o1.getEnd().compareTo(o2.getEnd()); } - } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index d14e24e8830..9d26cfaf6bc 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -15,6 +15,46 @@ public class IntervalgraphDecompositionTest { + public boolean isNiceTreeDecomposition(Graph,E> graph, Set root){ + if(root.size() != 0) return false; + Queue> queue = new LinkedList>(); + queue.add(root); + while(!queue.isEmpty()) + { + Set current = queue.poll(); + List> neighbors = Graphs.neighborListOf(graph, current); + if(neighbors.size() == 0 && current.size() == 0) continue; //leaf node + if(neighbors.size() == 1) //forget or introduce + { + Set next = neighbors.get(0); + queue.add(next); + Set union = new HashSet(current); + union.addAll(next); + if(union.size() == next.size() || union.size() == current.size()) + { + if(current.size() == next.size()+1) continue; //introduce + else if(current.size()+1 == next.size()) continue; //forget + } + } + if(neighbors.size() == 2) //join + { + Set first = neighbors.get(0); + Set second = neighbors.get(1); + queue.add(first); + queue.add(second); + Set union = new HashSet(current); + union.addAll(first); + union.addAll(second); + if(union.size() == current.size() + && union.size() == first.size() + && union.size() == second.size()) + continue; //join node! + } + return false; //no valid node! + } + return true; + } + @Test public void testIntervalgraphDecompositionForRegularGraphs() { @@ -37,10 +77,21 @@ public void testIntervalgraphDecompositionForIntervalGraphs() @Test public void testIntervalgraphDecompositionForIntervalLists() { - List> list = new ArrayList>(); - for(int i = 0; i<1; i++) + List> list = new ArrayList>(); + //just path + for(int i = 0; i<10; i++) + { + list.add(new Interval(i,i+1)); + } + //and to spice it up, a clique + for(int i = 0; i<5; i++) { + list.add(new Interval(10,10+i)); } + IntervalgraphDecomposition decompalg = new IntervalgraphDecomposition<>(list); + Graph>,DefaultEdge> decomp = decompalg.getTreeDecomposition(); + Set> root = decompalg.getRoot(); + assertTrue(isNiceTreeDecomposition(decomp,root)); } @Test From 12fbc769e7e1b308fe407baea3a638f93cf3eb2a Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Mon, 7 May 2018 21:02:48 +0200 Subject: [PATCH 092/131] changed some issues with pointer und Hash stuff --- .../IntervalgraphDecomposition.java | 9 ++++-- .../IntervalgraphDecompositionTest.java | 28 ++++++++++--------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index 17e4ef1fdff..d2059c20087 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -50,19 +50,22 @@ private void computeTreeDecomposition() } addIntroduce(iv); } + while(endIndex < endSort.size()-1) { + addForget(endSort.get(endIndex++)); + } } private void initTreeDecomposition() { treeDecomposition = new DefaultDirectedGraph>,DefaultEdge>(DefaultEdge.class); - root = new HashSet>(0); + root = new TreeSet>(); treeDecomposition.addVertex(root); currentVertex = root; } private void addIntroduce(Interval vertex) { - Set> nextVertex = new HashSet>(currentVertex); + Set> nextVertex = new TreeSet>(currentVertex); nextVertex.add(vertex); treeDecomposition.addVertex(nextVertex); treeDecomposition.addEdge(currentVertex, nextVertex); @@ -71,7 +74,7 @@ private void addIntroduce(Interval vertex) private void addForget(Interval vertex) { - Set> nextVertex = new HashSet>(currentVertex); + Set> nextVertex = new TreeSet>(currentVertex); nextVertex.remove(vertex); treeDecomposition.addVertex(nextVertex); treeDecomposition.addEdge(currentVertex, nextVertex); diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index 9d26cfaf6bc..6beacedc528 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -15,18 +15,19 @@ public class IntervalgraphDecompositionTest { - public boolean isNiceTreeDecomposition(Graph,E> graph, Set root){ - if(root.size() != 0) return false; + private void isNiceTreeDecomposition(Graph,E> graph, Set root){ + if(root.size() != 0) assertFalse(root+" is no valid root", true); Queue> queue = new LinkedList>(); queue.add(root); while(!queue.isEmpty()) { Set current = queue.poll(); - List> neighbors = Graphs.neighborListOf(graph, current); - if(neighbors.size() == 0 && current.size() == 0) continue; //leaf node - if(neighbors.size() == 1) //forget or introduce + List> successor = Graphs.successorListOf(graph, current); + System.out.println("DEBUG: current:"+current+", neighbor:"+successor); + if(successor.size() == 0 && current.size() <= 1) continue; //leaf node + if(successor.size() == 1) //forget or introduce { - Set next = neighbors.get(0); + Set next = successor.get(0); queue.add(next); Set union = new HashSet(current); union.addAll(next); @@ -36,10 +37,10 @@ public boolean isNiceTreeDecomposition(Graph,E> graph, Set root) else if(current.size()+1 == next.size()) continue; //forget } } - if(neighbors.size() == 2) //join + if(successor.size() == 2) //join { - Set first = neighbors.get(0); - Set second = neighbors.get(1); + Set first = successor.get(0); + Set second = successor.get(1); queue.add(first); queue.add(second); Set union = new HashSet(current); @@ -50,9 +51,9 @@ public boolean isNiceTreeDecomposition(Graph,E> graph, Set root) && union.size() == second.size()) continue; //join node! } - return false; //no valid node! + assertFalse("Vertex Set "+current+" is no valid nice tree node in tree "+graph, true); //no valid node! } - return true; + assertTrue(true); } @Test @@ -63,7 +64,7 @@ public void testIntervalgraphDecompositionForRegularGraphs() //IntervalgraphDecomposition> decompositionAlg = new IntervalgraphDecomposition<>(g); //Graph,DefaultEdge> decomp = decompositionAlg.getTreeDecomposition(); //TODO: test here - //assertNotEquals(decomp,decomp); + assertTrue(false); } @Test @@ -72,6 +73,7 @@ public void testIntervalgraphDecompositionForIntervalGraphs() IntervalGraphInterface ig = new CenteredIntervalTree<>(); //TODO: change ig //IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(ig); + assertTrue(false); } @Test @@ -91,7 +93,7 @@ public void testIntervalgraphDecompositionForIntervalLists() IntervalgraphDecomposition decompalg = new IntervalgraphDecomposition<>(list); Graph>,DefaultEdge> decomp = decompalg.getTreeDecomposition(); Set> root = decompalg.getRoot(); - assertTrue(isNiceTreeDecomposition(decomp,root)); + isNiceTreeDecomposition(decomp,root); } @Test From 8de6bffa03c5fd5fdaacf8ad5d2e9fcaf02e82d3 Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 21:42:47 +0200 Subject: [PATCH 093/131] Fix all style violations --- .../IntervalGraphRecognizer.java | 10 ++-- .../intervalgraph/LexBreadthFirstSearch.java | 19 ++++-- .../graph/specifics/IntervalSpecifics.java | 11 +++- .../intervalgraph/CenteredIntervalTree.java | 6 +- .../jgrapht/intervalgraph/IntervalGraph.java | 7 +++ .../intervalgraph/IntervalGraphInterface.java | 21 ++++++- .../IntervalGraphVertexContainer.java | 4 ++ ...IntervalGraphVertexContainerInterface.java | 4 ++ .../intervalgraph/IntervalTreeInterface.java | 4 +- .../intervalgraph/IntervalTreeNodeKey.java | 5 ++ .../intervalgraph/IntervalTreeNodeValue.java | 7 ++- .../intervalgraph/IntervalTreeStructure.java | 7 +++ .../org/jgrapht/intervalgraph/RBNode.java | 2 +- .../intervalgraph/RedBlackComparatorTree.java | 2 +- .../RedBlackIntervalComparatorTree.java | 2 +- .../intervalgraph/RedBlackIntervalTree.java | 2 +- .../jgrapht/intervalgraph/RedBlackTree.java | 2 +- .../interval/IntegerInterval.java | 17 ++++++ .../intervalgraph/interval/Interval.java | 60 ++++++++++++++++--- .../intervalgraph/interval/package-info.java | 4 ++ .../jgrapht/intervalgraph/package-info.java | 4 ++ .../traverse/LexBreadthFirstIterator.java | 8 +++ 22 files changed, 179 insertions(+), 29 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/package-info.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 048b0d7e1fd..50c07ede64b 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -10,19 +10,19 @@ /** * A recognizer for interval graphs. - *

+ * * An interval graph is a intersection graph of a set of intervals on the line, i.e. they contain a * vertex for each interval and two vertices are connected if the corresponding intervals have a * nonempty intersection. - *

+ * * The recognizer uses the algorithm described in - * (The LBFS Structure + * (The LBFS Structure * and Recognition of Interval Graphs. SIAM J. Discrete Math.. 23. 1905-1953. * 10.1137/S0895480100373455.) by Derek Corneil, Stephan Olariu and Lorna Stewart based on * multiple lexicographical breadth-first search (LBFS) sweeps. - *

+ * * For this recognizer to work correctly the graph must not be modified during iteration. - *

+ * * * @param the graph vertex type. * @param the graph edge type. diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java index efd2e1a599a..3d1f5257f3e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/LexBreadthFirstSearch.java @@ -5,17 +5,23 @@ import java.util.*; -public class LexBreadthFirstSearch +/** A class that is used to perform the BFS algorithms used to detect interval graphs. + * @param The vertex type + * @param The edge type + */ +class LexBreadthFirstSearch { /** * Performs a lexicographical BFS starting at {@code startingVertex}. * + * @param The vertex type + * @param The edge type * @param graph the graph we want to perform LBFS on * @param startingVertex the starting vertex of the LBFS * @return an array of vertices representing the order in which the vertices were found */ - public static HashMap lexBreadthFirstSearch(Graph graph, V startingVertex) + static HashMap lexBreadthFirstSearch(Graph graph, V startingVertex) { HashMap result = new HashMap<>(graph.vertexSet().size()); LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, startingVertex); @@ -31,12 +37,13 @@ public static HashMap lexBreadthFirstSearch(Graph graph * Performs LBFS+ starting at {@code startingVertex} using the previous ordering {@code prevOrdering}. * * @param graph the graph we want to perform LBFS on - * @param startingVertex the starting vertex of the LBFS * @param priority the priority of vertices for tiebreaking + * @param The vertex type + * @param The edge type * @return an array of vertices representing the order in which the vertices were found */ - public static HashMap lexBreadthFirstSearchPlus(Graph graph, HashMap priority) + static HashMap lexBreadthFirstSearchPlus(Graph graph, HashMap priority) { HashMap result = new HashMap<>(graph.vertexSet().size()); LexBreadthFirstIterator lbfIterator = new LexBreadthFirstIterator<>(graph, priority); @@ -54,10 +61,12 @@ public static HashMap lexBreadthFirstSearchPlus(Graph g * @param graph the graph we want to perform LBFS on * @param priorityA the first priority of vertices for tiebreaking * @param priorityB the second priority of vertices for tiebreaking + * @param The vertex type + * @param The edge type * @return an array of vertices representing the order in which the vertices were found */ - public static HashMap lexBreadthFirstSearchStar(Graph graph, HashMap priorityA, HashMap priorityB) + static HashMap lexBreadthFirstSearchStar(Graph graph, HashMap priorityA, HashMap priorityB) { HashMap neighborIndexA = new HashMap<>(); HashMap neighborIndexB = new HashMap<>(); diff --git a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java index 38892329c05..2c69f6e20a8 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java +++ b/jgrapht-core/src/main/java/org/jgrapht/graph/specifics/IntervalSpecifics.java @@ -16,8 +16,10 @@ * Implementation of IntervalSpecifics. * This class implements necessary methods for IntervalGraph. * - * @param the vertex type + * @param the interval vertex type * @param the edge type + * @param the internal vertex type + * @param The underlying type for intervals * * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 @@ -45,6 +47,7 @@ public IntervalSpecifics(IntervalGraph intervalGraph) { * Constructs new interval specifics. * * @param intervalGraph the graph for which these specifics are for + * @param vertices The vertices of the graph */ public IntervalSpecifics(IntervalGraph intervalGraph, ArrayList vertices) { @@ -69,14 +72,20 @@ public void addVertex(V vertex) } /** + * Gets the overlapping vertices for a given vertex * + * @param vertex The input vertex + * + * @return A list of vertices that overlap the input vertex */ public List getOverlappingIntervalVertices(V vertex) { return intervalGraphVertexContainerInterface.getOverlappingIntervalVertices(vertex); } /** + * Removes a vertex * + * @param v The vertex that should be removed */ public void removeVertex(V v) { intervalGraphVertexContainerInterface.remove(v); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java index cd7cfc62975..e0dc0cc15e9 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/CenteredIntervalTree.java @@ -6,7 +6,11 @@ import org.jgrapht.Graph; import org.jgrapht.intervalgraph.interval.Interval; -public class CenteredIntervalTree> implements IntervalGraphInterface { +/** + * A centered interval tree that is used to efficiently store interval graphs + * @param The type of intervals stored + */ +class CenteredIntervalTree> implements IntervalGraphInterface { private T centerPoint; private CenteredIntervalTree leftTree; // contains all the intervals *completely* to the left of the center point private CenteredIntervalTree rightTree; // contains all the intervals *completely* to the right of the center point diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 42d96f467a2..1fbe74790d4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -20,6 +20,8 @@ * * @param the vertex type * @param the edge type + * @param the internal vertex type + * @param The underlying type for intervals * * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 @@ -183,6 +185,10 @@ private boolean addExistingIntervalEdges(V sourceVertex, V targetVertex, E edge) * returns interval graph representation if one exists, otherwise null * * @param graph the graph to check + * @param the vertex type + * @param the edge type + * @param the internal vertex type + * @param The underlying type for intervals * @return interval graph representation if one exists, otherwise null */ public static , E, VertexType, T extends Comparable> @@ -585,6 +591,7 @@ protected IntervalSpecifics createSpecifics(boolean directe * * @param directed if true the specifics should adjust the behavior to a directed graph * otherwise undirected + * @param vertices The set of vertices * @return the specifics used by this graph */ protected IntervalSpecifics createSpecifics(boolean directed, ArrayList vertices) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java index 930a139af15..1b021201a3b 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphInterface.java @@ -5,10 +5,29 @@ import java.util.Collection; +/** + * An interface for interval graph containers + * @param The underlying type for the intervals + */ public interface IntervalGraphInterface> { - Collection> intersections(T queryInterval); + /** + * Returns a collection of intersecting intervals + * @param queryPoint The query point + * @return A collection of intersecting intervals + */ + Collection> intersections(T queryPoint); + + /** + * Returns a collection of intersecting intervals + * @param queryInterval The query interval + * @return A collection of intersecting intervals + */ Collection> intersections(Interval queryInterval); + /** + * Returns a graph of the stored intervals + * @return A graph of the stored intervals + */ Graph asGraph(); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java index 74b76c2bb34..4a23df7b3e5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainer.java @@ -12,6 +12,7 @@ * * @param the vertex type * @param the edge type + * @param the internal vertex type * @param the type of the interval * * @author Christoph Grüne (christophgruene) @@ -45,6 +46,9 @@ public IntervalGraphVertexContainer() { /** * Constructs a vertex container for an interval graph with all necessary objects. + * + * @param vertices The set of vertices + * @param undirectedEdgeContainers The set of undirected edge containers */ public IntervalGraphVertexContainer(ArrayList vertices, ArrayList> undirectedEdgeContainers) { this.vertexMap = new LinkedHashMap<>(); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java index 6b339a33231..ead1bcb12ab 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraphVertexContainerInterface.java @@ -28,6 +28,8 @@ public interface IntervalGraphVertexContainerInterfacev * * @param v the vertex with interval + * + * @return A list of overlapping intervals */ List getOverlappingIntervalVertices(V v); @@ -44,6 +46,8 @@ public interface IntervalGraphVertexContainerInterface put(V vertex, UndirectedEdgeContainer ec); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java index 059df78ae90..abb28650788 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeInterface.java @@ -10,7 +10,9 @@ * included points in O(log n + k), where n is the number of intervals and k the output size, * i.e. the number of output intervals. * - * @param the type of the interval + * @param The type of the interval + * @param The key for the search tree + * @param The node value type * * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java index fab2133f0c9..77b266e3414 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeKey.java @@ -130,4 +130,9 @@ else if (!(obj instanceof IntervalTreeNodeKey)) @SuppressWarnings("unchecked") IntervalTreeNodeKey other = (IntervalTreeNodeKey) obj; return Objects.equals(key, other.key) && Objects.equals(comparator, other.comparator); } + + @Override + public int hashCode() { + return Objects.hash(key, comparator); + } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java index 2935009e236..3104a7b8299 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeNodeValue.java @@ -9,7 +9,8 @@ * Implementation of IntervalTreeNodeValue * This is a container class to store the necessary data for the (augmented) interval tree in the nodes of the tree. * - * @param the type of the interval + * @param the type of the interval + * @param The underlying type for the intervals * * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 @@ -58,6 +59,10 @@ public T getHighValue() return highValue; } + /** + * Sets the high value + * @param highValue The high value + */ public void setHighValue(T highValue) { this.highValue = highValue; } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index 42f8be9539f..a0369d25d0f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -23,10 +23,17 @@ public class IntervalTreeStructure> implements IntervalS private IntervalTreeInterface>, IntervalTreeNodeValue, T>> tree; + /** + * Initializes a new instance of the class + */ public IntervalTreeStructure() { this.tree = new RedBlackIntervalTree<>(); } + /** + * Initializes a new instance of the class + * @param intervals The set of contained intervals + */ public IntervalTreeStructure(ArrayList> intervals) { ArrayList>> keys = new ArrayList<>(intervals.size()); ArrayList, T>> values = new ArrayList<>(intervals.size()); diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java index 7a629b1acd3..ccf1aeb1e61 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RBNode.java @@ -11,7 +11,7 @@ * @author Daniel Mock (danielmock) * @since Apr 26, 2018 */ -public class RBNode implements Serializable { +class RBNode implements Serializable { private static final long serialVersionUID = 5674337686253743843L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java index d9541c33534..3456a0ee78d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java @@ -15,7 +15,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class RedBlackComparatorTree implements Serializable { +class RedBlackComparatorTree implements Serializable { private static final long serialVersionUID = 1199228564356373435L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java index 94d6f5ef783..bb594489ac1 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java @@ -6,7 +6,7 @@ import java.util.LinkedList; import java.util.List; -public class RedBlackIntervalComparatorTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackComparatorTree { +class RedBlackIntervalComparatorTree, NodeValue extends IntervalTreeNodeValue, T>> extends RedBlackComparatorTree { public RedBlackIntervalComparatorTree(Comparator> comparator) { super((o1, o2) -> comparator.compare(o1.getInterval(), o2.getInterval())); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java index 714e443c111..5128ee4cc78 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalTree.java @@ -20,7 +20,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 26, 2018 */ -public class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>, T extends Comparable> extends RedBlackTree implements IntervalTreeInterface, Serializable { +class RedBlackIntervalTree, NodeValue extends IntervalTreeNodeValue, T>, T extends Comparable> extends RedBlackTree implements IntervalTreeInterface, Serializable { private static final long serialVersionUID = 4353687394654923429L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java index 1742c6cadee..efaedb82998 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackTree.java @@ -13,7 +13,7 @@ * @author Christoph Grüne (christophgruene) * @since Apr 18, 2018 */ -public class RedBlackTree, V> implements BinarySearchTree, Serializable { +class RedBlackTree, V> implements BinarySearchTree, Serializable { private static final long serialVersionUID = 1199228564356373435L; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java index 81131e8a52a..a62dfa54ecb 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/IntegerInterval.java @@ -1,14 +1,31 @@ package org.jgrapht.intervalgraph.interval; +/** + * An implementation of integer intervals + */ public class IntegerInterval extends Interval { + + /** + * Constructs a new instance of the class + * @param start The start point of the interval + * @param end The end point of the interval + */ public IntegerInterval(int start, int end) { super(start, end); } + /** + * Gets the length of the interval + * @return The length of the interval + */ public int length() { return getEnd() - getStart(); } + /** + * Returns a string representation for the interval + * @return A string representation for the interval + */ @Override public String toString() { return "[" + getStart() + ", " + getEnd() + "]"; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 154def1ea18..e08658d073f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -2,10 +2,19 @@ import java.util.Objects; +/** + * The base class for an interval + * @param The underlying type + */ public class Interval> implements Comparable> { private T start; private T end; + /** + * Creates a new class of the interval class + * @param start The start point + * @param end The end point + */ public Interval(T start, T end) { this.start = start; this.end = end; @@ -14,17 +23,36 @@ public Interval(T start, T end) { throw new IllegalArgumentException(); } + /** + * Gets the start point + * @return The start point + */ public T getStart() { return start; } + + /** + * Gets the end point + * @return The end point + */ public T getEnd() { return end; } + /** + * Checks whether or not the other interval intersects this interval + * @param other The other interval + * @return true, if the other interval intersects this, otherwise false + */ public boolean isIntersecting(Interval other) { return this.contains(other.getStart()) || this.contains(other.getEnd()) || other.contains(this.getStart()); } + /** + * Checks whether or not the point is contained in this interval + * @param point The point + * @return true, if the point is contained in this, otherwise false + */ public boolean contains(T point) { if (point == null) { throw new IllegalArgumentException(); @@ -35,14 +63,19 @@ public boolean contains(T point) { return result; } - - public int compareToPoint(T o) { - if (o == null) { + /** + * Compares the point to this interval + * @param point The point + * @return A value < 0 if the interval is left of the point, 0 if the point is contained in the interval, + * otherwise a value > 0 + */ + public int compareToPoint(T point) { + if (point == null) { throw new IllegalArgumentException(); } - int relativeStart = getStart().compareTo(o); - int relativeEnd = getEnd().compareTo(o); + int relativeStart = getStart().compareTo(point); + int relativeEnd = getEnd().compareTo(point); if (relativeStart <= 0 && relativeEnd >= 0) { return 0; @@ -51,11 +84,16 @@ public int compareToPoint(T o) { } } - + /** + * Compares this interval to the other interval + * @param other The other interval + * @return A value < 0 if the this interval is completely left of the other interval, 0 if the intervals intersect, + * otherwise a value > 0 + */ @Override - public int compareTo(Interval o) { - int isLeft = getEnd().compareTo(o.getStart()); // < 0 if this ends before other starts - int isRight = getStart().compareTo(o.getEnd()); // > 0 if this starts before other ends + public int compareTo(Interval other) { + int isLeft = getEnd().compareTo(other.getStart()); // < 0 if this ends before other starts + int isRight = getStart().compareTo(other.getEnd()); // > 0 if this starts before other ends if (isLeft >= 0 && isRight <= 0) { return 0; @@ -66,6 +104,10 @@ public int compareTo(Interval o) { } } + /** + * Checks whether or not the current interval is valid + * @return true, if the end point is at least as big as the start point, otherwise false + */ public boolean isValid() { return getStart().compareTo(getEnd()) <= 0; } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/package-info.java new file mode 100644 index 00000000000..0ec015480e2 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/package-info.java @@ -0,0 +1,4 @@ +/** + * Data structures for interval graphs. + */ +package org.jgrapht.intervalgraph.interval; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/package-info.java new file mode 100644 index 00000000000..62c5c251494 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/package-info.java @@ -0,0 +1,4 @@ +/** + * Data structures for interval graphs. + */ +package org.jgrapht.intervalgraph; diff --git a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java index 21ad472b5ed..0a88d064074 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java +++ b/jgrapht-core/src/main/java/org/jgrapht/traverse/LexBreadthFirstIterator.java @@ -111,7 +111,15 @@ public LexBreadthFirstIterator(Graph graph, HashMap priority) /** * Creates new lexicographical breadth-first iterator with a static priority list for {@code graph}. * + * This is used for the LBFS* variant top detect interval graphs + * * @param graph the graph to be iterated. + * @param priorityA The A priority list + * @param priorityB The B priority list + * @param neighborIndexA The A neighboring list + * @param neighborIndexB The B neighboring list + * @param ASets The A sets + * @param BSets The B sets */ public LexBreadthFirstIterator(Graph graph, HashMap priorityA, From 97ac52f18ae68718260d7dea9ba8a9ec0731176f Mon Sep 17 00:00:00 2001 From: Dennis Fischer Date: Mon, 7 May 2018 21:53:52 +0200 Subject: [PATCH 094/131] Fix invalid html in javadocs --- .../alg/intervalgraph/IntervalGraphRecognizer.java | 2 +- .../jgrapht/intervalgraph/IntervalStructureInterface.java | 1 - .../org/jgrapht/intervalgraph/IntervalTreeStructure.java | 1 - .../java/org/jgrapht/intervalgraph/interval/Interval.java | 8 ++++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 50c07ede64b..b2544b530ba 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -16,7 +16,7 @@ * nonempty intersection. * * The recognizer uses the algorithm described in - * (The LBFS Structure + * https://webdocs.cs.ualberta.ca/~stewart/Pubs/IntervalSIAM.pdf (The LBFS Structure * and Recognition of Interval Graphs. SIAM J. Discrete Math.. 23. 1905-1953. * 10.1137/S0895480100373455.) by Derek Corneil, Stephan Olariu and Lorna Stewart based on * multiple lexicographical breadth-first search (LBFS) sweeps. diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java index 63b065b292f..cbfadc40632 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalStructureInterface.java @@ -42,7 +42,6 @@ public interface IntervalStructureInterface> { * removes an interval from the tree * * @param interval the interval - * @return */ void remove(Interval interval); } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java index a0369d25d0f..aeabaf44593 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalTreeStructure.java @@ -77,7 +77,6 @@ public void add(Interval interval) { * removes an interval from the tree * * @param interval the interval - * @return */ @Override public void remove(Interval interval) { diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index e08658d073f..65fa6aa4469 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -66,8 +66,8 @@ public boolean contains(T point) { /** * Compares the point to this interval * @param point The point - * @return A value < 0 if the interval is left of the point, 0 if the point is contained in the interval, - * otherwise a value > 0 + * @return A value < 0 if the interval is left of the point, 0 if the point is contained in the interval, + * otherwise a value > 0 */ public int compareToPoint(T point) { if (point == null) { @@ -87,8 +87,8 @@ public int compareToPoint(T point) { /** * Compares this interval to the other interval * @param other The other interval - * @return A value < 0 if the this interval is completely left of the other interval, 0 if the intervals intersect, - * otherwise a value > 0 + * @return A value < 0 if the this interval is completely left of the other interval, 0 if the intervals intersect, + * otherwise a value > 0 */ @Override public int compareTo(Interval other) { From f166ae0dd334d778b4b0f25fae64d66699167722 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2018 22:11:30 +0200 Subject: [PATCH 095/131] fixed generic shit in asIntervalGraph() --- .../IntervalGraphRecognizer.java | 4 ++-- .../jgrapht/intervalgraph/IntervalGraph.java | 23 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 562edb87de5..e2696b37bd0 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -42,7 +42,7 @@ public final class IntervalGraphRecognizer */ private ArrayList> intervalsSortedByStartingPoint; private Map, V> intervalToVertexMap; - private Map> vertexToIntervalMap; + private Map> vertexToIntervalMap; /** * Creates (and runs) a new interval graph recognizer for the given graph. @@ -269,7 +269,7 @@ public Map, V> getIntervalToVertexMap() * * @return A mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. */ - public Map> getVertexToIntervalMap() + public Map> getVertexToIntervalMap() { return this.vertexToIntervalMap; } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index 42d96f467a2..1e8c45b564d 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -4,6 +4,7 @@ import org.jgrapht.Graph; import org.jgrapht.GraphType; import org.jgrapht.Graphs; +import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; import org.jgrapht.alg.util.Pair; import org.jgrapht.graph.*; import org.jgrapht.graph.specifics.IntervalSpecifics; @@ -185,28 +186,28 @@ private boolean addExistingIntervalEdges(V sourceVertex, V targetVertex, E edge) * @param graph the graph to check * @return interval graph representation if one exists, otherwise null */ - public static , E, VertexType, T extends Comparable> - IntervalGraph asIntervalGraph(Graph graph) { -/* - IntervalGraphRecognizer intervalGraphRecognizer = new IntervalGraphRecongnizer(Graph + IntervalGraph, E, VertexType, Integer> asIntervalGraph(Graph graph) { + + IntervalGraphRecognizer intervalGraphRecognizer = new IntervalGraphRecognizer<>(graph); if(!intervalGraphRecognizer.isIntervalGraph()) { return null; } - ArrayList> sortedIntervalList = intervalGraphRecognizer.getIntervalsSortedByStartingPoint(); - Map, VertexType> intervalVertexMap = intervalGraphRecognizer.getIntervalVertexMap(); - Map vertexIntervalMap = intervalGraphRecognizer.getVertexIntervalMap(); + ArrayList> sortedIntervalList = intervalGraphRecognizer.getIntervalsSortedByStartingPoint(); + Map, VertexType> intervalVertexMap = intervalGraphRecognizer.getIntervalToVertexMap(); + Map> vertexIntervalMap = intervalGraphRecognizer.getVertexToIntervalMap(); - ArrayList vertices = new ArrayList<>(sortedIntervalList.size()); + ArrayList> vertices = new ArrayList<>(sortedIntervalList.size()); for(int i = 0; i < sortedIntervalList.size(); ++i) { vertices.add(i, vertexIntervalMap.get(intervalVertexMap.get(sortedIntervalList.get(i)))); } - Map, E> edges = new LinkedHashMap<>(); + Map, IntervalVertexInterface>, E> edges = new LinkedHashMap<>(); - for(V vertex : vertices) { + for(IntervalVertexInterface vertex : vertices) { for(Iterator it = graph.outgoingEdgesOf(vertex.getVertex()).iterator(); it.hasNext();) { E edge = it.next(); edges.put(Pair.of(vertex, vertexIntervalMap.get(graph.getEdgeTarget(edge))), edge); @@ -217,8 +218,6 @@ IntervalGraph asIntervalGraph(Graph graph) { return new IntervalGraph<>(vertices, edges, (sourceVertex, targetVertex) -> graph.getEdgeFactory().createEdge(sourceVertex.getVertex(), targetVertex.getVertex()), graph.getType().isDirected(), graph.getType().isAllowingMultipleEdges(), graph.getType().isAllowingSelfLoops(), graph.getType().isWeighted()); - */ - return null; } From 3c0c94dd8ebbfdf375b69aea0a2aca19da642e33 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2018 23:04:36 +0200 Subject: [PATCH 096/131] fixed javaDoc --- .../src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java index d9506ad6053..ead7fe71845 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/IntervalGraph.java @@ -186,10 +186,8 @@ private boolean addExistingIntervalEdges(V sourceVertex, V targetVertex, E edge) * returns interval graph representation if one exists, otherwise null * * @param graph the graph to check - * @param the vertex type * @param the edge type * @param the internal vertex type - * @param The underlying type for intervals * @return interval graph representation if one exists, otherwise null */ public static From ae8cd0233b7dc9e9b36606643d6b287effb7414d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 May 2018 23:12:04 +0200 Subject: [PATCH 097/131] deleted unnecessary classes --- .../intervalgraph/RedBlackComparatorTree.java | 497 ------------------ .../RedBlackIntervalComparatorTree.java | 164 ------ .../RedBlackComparatorTreeTest.java | 108 ---- .../RedBlackIntervalComparatorTreeTest.java | 40 -- 4 files changed, 809 deletions(-) delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java delete mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java delete mode 100644 jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java deleted file mode 100644 index 868d5d9e90a..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackComparatorTree.java +++ /dev/null @@ -1,497 +0,0 @@ -package org.jgrapht.intervalgraph; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Implementation of red-black comparator tree - * - * @param the value - * - * @author Daniel Mock (danielmock) - * @author Christoph Grüne (christophgruene) - * @since Apr 18, 2018 - */ -class RedBlackComparatorTree implements Serializable { - - private static final long serialVersionUID = 1199228564356373435L; - - protected RBNode root; - - public final Comparator comparator; - public final Comparator> nodeComparator; - - public RedBlackComparatorTree(Comparator comparator) { - this.comparator = comparator; - this.nodeComparator = (o1, o2) -> comparator.compare(o1.getVal(), o2.getVal()); - } - - public RBNode getRoot() { - return root; - } - - private boolean isRed(RBNode node){ - return node != null && node.isRed(); - } - - /** - * Returns whether a key is contained in the tree - * - * @return true if tree contains key, false otherwise - * @throws IllegalArgumentException if key is null - */ - public boolean contains(V val) { - if (val == null) { - throw new IllegalArgumentException("Val is null"); - } - - return searchNode(val) != null; - } - - /** - * Inserts the given (key, value) pair into the tree. If the tree contains already a symbol with the given key - * it overwrites the old value with the new. - * - * @param val the value - * @throws IllegalArgumentException if key is null - */ - public void insert(V val) { - if (val == null) { - throw new IllegalArgumentException("Value is null"); - } - - root = insert(root, val); - root.setBlack(); - } - - protected RBNode insert(RBNode current, V val) { - if (current == null){ - return new RBNode<>(val, true, 1); - } - - if (val.equals(current.getVal())) { - current.setVal(val); - } else if (comparator.compare(val, current.getVal()) < 0) { - current.setLeftChild(insert(current.getLeftChild(), val)); - } else { - current.setRightChild(insert(current.getRightChild(), val)); - } - - // Fixup - - if (isRed(current.getRightChild()) && !isRed(current.getLeftChild())) { - current = rotateLeft(current); - } - if (isRed(current.getLeftChild()) && isRed(current.getLeftChild().getLeftChild())) { - current = rotateRight(current); - } - if (isRed(current.getLeftChild()) && isRed(current.getRightChild())) { - changeColor(current); - } - current.setSize(getSize(current.getLeftChild()) + getSize(current.getRightChild()) + 1); - - return current; - } - - /** - * Removes the specified key and its associated value from this tree - * - * @throws IllegalArgumentException if key is null - */ - public void delete(V val) { - if (val == null) { - throw new IllegalArgumentException("Key is null"); - } - if (!contains(val)) { - return; - } - - if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { - root.setRed(); - } - - root = delete(root, val); - if (!isEmpty()) { - root.setBlack(); - } - } - - private boolean isEmpty() { - return root == null; - } - - protected RBNode delete(RBNode current, V val) { - if (comparator.compare(val, current.getVal()) < 0) { - if (!isRed(current.getLeftChild()) && !isRed(current.getLeftChild().getLeftChild())) { - current = moveRedLeft(current); - } - current.setLeftChild(delete(current.getLeftChild(), val)); - } else { - if (isRed(current.getLeftChild())) { - current = rotateRight(current); - } - if (comparator.compare(val, current.getVal()) == 0 && current.getRightChild() == null) { - return null; - } - if (!isRed(current.getRightChild()) && !isRed(current.getRightChild().getLeftChild())) { - current = moveRedRight(current); - } - if (comparator.compare(val, current.getVal()) == 0) { - RBNode node = getLeftChild(current.getRightChild()); - current.setVal(node.getVal()); - current.setRightChild(deleteMin(current.getRightChild())); - } - else current.setRightChild(delete(current.getRightChild(), val)); - } - - return balance(current); - } - - protected RBNode balance(RBNode node) { - if (isRed(node.getRightChild())) { - node = rotateLeft(node); - } - if (isRed(node.getLeftChild()) && isRed(node.getLeftChild().getLeftChild())) { - node = rotateRight(node); - } - if (isRed(node.getLeftChild()) && isRed(node.getRightChild())) { - changeColor(node); - } - - node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild() ) + 1); - return node; - } - - /** - * Removes the smallest key and associated value from the tree. - * - * @throws NoSuchElementException if the tree is empty - */ - public void deleteMin() { - if (isEmpty()) { - throw new NoSuchElementException("empty tree"); - } - - if (!isRed(root.getLeftChild()) && !isRed(root.getRightChild())) { - root.setRed(); - } - - root = deleteMin(root); - if (!isEmpty()) { - root.setBlack(); - } - } - - private RBNode deleteMin(RBNode node) { - if (node.getLeftChild() == null) { - return null; - } - - if (!isRed(node.getLeftChild()) && !isRed(node.getLeftChild().getLeftChild())) { - root = moveRedLeft(node); - } - - node.setLeftChild(deleteMin(node.getLeftChild())); - return balance(node); - } - - /** - * Removes the largest key and associated value from the tree. - * - * @throws NoSuchElementException if the tree is empty - */ - public void deleteMax() { - if (isEmpty()) { - throw new NoSuchElementException(); - } - - if (!isRed(root.getRightChild()) && !isRed(root.getRightChild())) { - root.setRed(); - } - - root = deleteMax(root); - if (!isEmpty()) { - root.setBlack(); - } - } - - private RBNode deleteMax(RBNode node) { - if (isRed(node.getLeftChild())) { - node = rotateRight(node); - } - if (node.getRightChild() == null) { - return null; - } - if (!isRed(node.getRightChild()) && !isRed(node.getRightChild().getLeftChild())) { - node = moveRedRight(node); - } - - node.setRightChild(deleteMax(node.getRightChild())); - - return balance(node); - } - - /** - * Returns the height of the BST. - * - * @return the height of the BST (a tree with 1 node has height 0) - */ - public int height() { - return height(root); - } - - private int height(RBNode node) { - if (node == null) { - return -1; - } - - return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild())); - } - - /** - * Returns the smallest key in the tree. - * - * @return the smallest key in the tree - * @throws NoSuchElementException if the tree is empty - */ - public V min() { - if (isEmpty()) { - throw new NoSuchElementException("empty tree"); - } - - return getLeftChild(root).getVal(); - } - - private RBNode getLeftChild(RBNode node) { - return node.getLeftChild() == null ? node : getLeftChild(node.getLeftChild()); - } - - /** - * Returns the largest key in the tree. - * - * @return the largest key in the tree - * @throws NoSuchElementException if the tree is empty - */ - public V max() { - if (isEmpty()) { - throw new NoSuchElementException("empty tree"); - } - - return getRightChild(root).getVal(); - } - - private RBNode getRightChild(RBNode node) { - return node.getRightChild() == null ? node : getRightChild(node.getRightChild()); - } - - /** - * Returns the largest key in the tree less than or equal to key. - * - * @return the largest key in the tree less than or equal to key - * @throws NoSuchElementException if there is no such key - * @throws IllegalArgumentException if key is null - */ - public V floor(V val) { - return null; - } - - /** - * Returns the smallest key in the tree greater than or equal to key. - * - * @return the smallest key in the tree greater than or equal to key - * @throws NoSuchElementException if there is no such key - * @throws IllegalArgumentException if key is null - */ - public V ceiling(V val) { - return null; - } - - /** - * Return the key in the tree whose rank is k. - * This is the (k+1)st smallest key in the tree. - * - * @param k the position - * @return the key in the tree of rank k - * @throws IllegalArgumentException if k not in {0, ..., n-1} - */ - public V select(int k) { - return null; - } - - /** - * Return the number of keys in the tree strictly less than key. - * - * @param val the value - * @return the number of keys in the tree strictly less than key - * @throws IllegalArgumentException if key is null - */ - public int rank(V val) { - return 0; - } - - /** - * Returns all keys in the symbol table as an Iterable. - * To iterate over all of the keys in the symbol table named st, - * use the foreach notation: for (Key key : st.keys()). - * - * @return all keys in the symbol table as an Iterable - */ - public Iterable keys() { - return null; - } - - /** - * Returns all keys in the symbol table in the given range, - * as an Iterable. - * - * @param min minimum endpoint - * @param max maximum endpoint - * @return all keys in the sybol table between min - * (inclusive) and max (inclusive) as an Iterable - * @throws IllegalArgumentException if either min or max - * is null - */ - public Iterable keys(V min, V max) { - return null; - } - - /** - * Returns the number of keys in the symbol table in the given range. - * - * @param min minimum endpoint - * @param max maximum endpoint - * @return the number of keys in the sybol table between min - * (inclusive) and max (inclusive) - * @throws IllegalArgumentException if either min or max - * is null - */ - public int size(V min, V max) { - return 0; - } - - public int getSize(RBNode node) { - return node == null ? 0 : node.getSize(); - } - - /******************************************************************************************************************* - * HELPER METHODS * - ******************************************************************************************************************/ - - protected RBNode rotateLeft(RBNode node) { - RBNode rightChild = node.getRightChild(); - node.setRightChild(rightChild.getLeftChild()); - rightChild.setLeftChild(node); - rightChild.setRed(isRed(rightChild.getLeftChild())); - rightChild.getLeftChild().setRed(true); - rightChild.setSize(getSize(node)); - node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); - return rightChild; - } - - protected RBNode rotateRight(RBNode node) { - RBNode leftChild = node.getLeftChild(); - node.setLeftChild(leftChild.getRightChild()); - leftChild.setRightChild(node); - leftChild.setRed(isRed(leftChild.getRightChild())); - leftChild.getRightChild().setRed(true); - leftChild.setSize(getSize(node)); - node.setSize(getSize(node.getLeftChild()) + getSize(node.getRightChild()) + 1); - return leftChild; - } - - private void changeColor(RBNode node) { - node.setRed(!isRed(node)); - node.getRightChild().setRed(!isRed(node.getRightChild())); - node.getLeftChild().setRed(!isRed(node.getLeftChild())); - } - - private RBNode searchNode(V val) { - RBNode current = root; - while (current != null) { - if (current.getVal().equals(val)) { - return current; - } else if (comparator.compare(current.getVal(), val) < 0) { - current = current.getRightChild(); - } else { - current = current.getLeftChild(); - } - } - - return null; - } - - private RBNode moveRedRight(RBNode node) { - changeColor(node); - if (isRed(node.getLeftChild().getLeftChild())) { - node = rotateRight(node); - changeColor(node); - } - - return node; - } - - private RBNode moveRedLeft(RBNode node) { - changeColor(node); - if (isRed(node.getRightChild().getLeftChild())) { - node.setRightChild(rotateRight(node.getRightChild())); - node = rotateLeft(node); - changeColor(node); - } - - return node; - } - - // returns the nodes inorder - private List> inorder() { - if (root == null) { - return new ArrayList<>(); - } - - List> result = new ArrayList<>(getSize(root)); - inorder(root, result); - return result; - } - - private void inorder(RBNode current, List> result) { - if (current == null) { - return; - } - - inorder(current.getLeftChild(), result); - result.add(current); - inorder(current.getRightChild(), result); - } - - public List inorderValues(){ - List> inorder = inorder(); - List result = new ArrayList<>(inorder.size()); - for (RBNode node: inorder) { - result.add(node.getVal()); - } - return result; - } - - private List> preorder() { - if (root == null) { - return new ArrayList<>(); - } - - List> result = new ArrayList<>(getSize(root)); - preorder(root, result); - return result; - } - - private void preorder(RBNode current, List> result) { - if (current == null) { - return; - } - - result.add(current); - inorder(current.getLeftChild(), result); - inorder(current.getRightChild(), result); - } - -} diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java deleted file mode 100644 index 6e6addd2e78..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTree.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.jgrapht.intervalgraph; - -import org.jgrapht.intervalgraph.interval.Interval; - -import java.util.Comparator; -import java.util.LinkedList; -import java.util.List; - - -/** - * Implementation of red-black comparator tree with support for interval tree - * - * @param - * @param - */ -public class RedBlackIntervalComparatorTree, NodeValue extends IntervalTreeNodeValue, T>> - extends RedBlackComparatorTree { - - public RedBlackIntervalComparatorTree(Comparator> comparator) { - super((o1, o2) -> comparator.compare(o1.getInterval(), o2.getInterval())); - } - - /** - * Constructs a new instance. The comparator compares the start value of both intervals. - * In a tie, it compares the end values. - */ - public RedBlackIntervalComparatorTree() { - this((o1, o2) -> { - int startCompare = o1.getStart().compareTo(o2.getStart()); - if (startCompare != 0) { - return startCompare; - } else { - return o1.getEnd().compareTo(o2.getEnd()); - } - }); - } - - private static final long serialVersionUID = 4353687394654923429L; - - public List> overlapsWith(Interval interval) { - List> result = new LinkedList<>(); - overlapsWith(this.getRoot(), interval, result); - return result; - } - - public List> overlapsWith(T point) { - List> result = new LinkedList<>(); - overlapsWithPoint(this.getRoot(), point, result); - return result; - } - - protected RBNode rotateRight(RBNode node) { - // Perform rotation as usual - RBNode result = super.rotateRight(node); - - // update hi vals - result.getVal().setHighValue(node.getVal().getHighValue()); - updateHi(node); - - return result; - } - - protected RBNode rotateLeft(RBNode node) { - // Perform rotation as usual - RBNode result = super.rotateLeft(node); - - // update hi vals - result.getVal().setHighValue(node.getVal().getHighValue()); - updateHi(node); - - return result; - } - - @Override - protected RBNode delete(RBNode current, NodeValue val) { - RBNode result = super.delete(current, val); - updateHi(result); - return result; - } - - protected RBNode insert(RBNode current, NodeValue val) { - RBNode result = super.insert(current, val); - updateHi(result); - return result; - } - - protected RBNode balance(RBNode node) { - RBNode result = super.balance(node); - updateHi(result); - return result; - } - - // sets the hi attribute of the given node to the max of the subtree or itself - private void updateHi(RBNode node) { - if (node == null) { - return; - } - - T result = node.getVal().getInterval().getEnd(); - if (node.getRightChild() != null) { - result = max(result, node.getRightChild().getVal().getHighValue()); - } - - if (node.getLeftChild() != null) { - result = max(result, node.getLeftChild().getVal().getHighValue()); - } - - node.getVal().setHighValue(result); - } - - public T max(T t1, T t2) { - if (t1 == null || t2 == null) { - throw new IllegalArgumentException("Parameter cannot be null."); - } - return t1.compareTo(t2) > 0 ? t1 : t2; - } - - private void overlapsWith(RBNode node, Interval interval, List> result) { - if (node == null) { - return; - } - - // query starts strictly after any interval in the subtree - if (interval.getStart().compareTo(node.getVal().getHighValue()) > 0) { - return; - } - - // node and query overlap - if (node.getVal().getInterval().isIntersecting(interval)) { - result.add(node.getVal().getInterval()); - } - - // if the node starts before the query ends, check right children - if (node.getVal().getInterval().getStart().compareTo(interval.getEnd()) <= 0) { - overlapsWith(node.getRightChild(), interval, result); - } - - overlapsWith(node.getLeftChild(), interval, result); - } - - private void overlapsWithPoint(RBNode node, T point, List> result) { - if (node == null) { - return; - } - - // point is bigger than the endpoint of any interval in the subtree - if (point.compareTo(node.getVal().getHighValue()) > 0) { - return; - } - - // check left subtrees - overlapsWithPoint(node.getLeftChild(), point, result); - - // add node interval if it contains the query point - if (node.getVal().getInterval().contains(point)) { - result.add(node.getVal().getInterval()); - } - - // check right subtree if their start values are smaller (equal) than query point - if (point.compareTo(node.getVal().getInterval().getStart()) >= 0) { - overlapsWithPoint(node.getRightChild(), point, result); - } - } -} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java deleted file mode 100644 index b4d427d8e08..00000000000 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackComparatorTreeTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.jgrapht.intervalgraph; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -public class RedBlackComparatorTreeTest { - - private RedBlackComparatorTree redBlackComparatorTree = new RedBlackComparatorTree<>(Integer::compareTo); - - @Before - public void setUp() { - for (int i = 0; i < 100; i++) { - redBlackComparatorTree.insert(i); - } - } - - @Test - public void testOrdered() { - for (int i = 0; i < 100; i++) { - assertEquals(i, (int) redBlackComparatorTree.inorderValues().get(i)); - } - for (int i = 6; i < 73; i++) { - assertEquals(i, (int) redBlackComparatorTree.inorderValues().get(i - 1)); - } - for (int i = 74; i < 100; i++) { - assertEquals(i, (int) redBlackComparatorTree.inorderValues().get(i - 2)); - } - } - - @Test - public void testContains() { - assertTrue(redBlackComparatorTree.contains(0)); - assertTrue(redBlackComparatorTree.contains(4)); - } - - @Test - public void testContainsNegative() { - redBlackComparatorTree.delete(5); - redBlackComparatorTree.delete(73); - redBlackComparatorTree.delete(200); - - assertFalse(redBlackComparatorTree.contains(5)); - assertFalse(redBlackComparatorTree.contains(73)); - assertFalse(redBlackComparatorTree.contains(200)); - } - - @Test - public void testDelete() { - redBlackComparatorTree.delete(25); - redBlackComparatorTree.delete(25); - } - - // Test important properties of red-black tree - - /** - * The root is black - */ - @Test - public void testBlackRoot() { - assertFalse(redBlackComparatorTree.getRoot().isRed()); - } - - /** - * If a node is red, then both its children are black - */ - @Test - public void testBlackChildren() { - testBlackChildren(redBlackComparatorTree.getRoot()); - } - - private void testBlackChildren(RBNode currentNode) { - RBNode leftChild = currentNode.getLeftChild(); - if (leftChild != null) { - if (currentNode.isRed()) { - assertFalse(leftChild.isRed()); - } - testBlackChildren(leftChild); - } - - RBNode rightChild = currentNode.getRightChild(); - if (rightChild != null) { - if (currentNode.isRed()) { - assertFalse(rightChild.isRed()); - } - testBlackChildren(rightChild); - } - } - - /** - * Every path from a given node to any of its descendant leaves contains the same number of black nodes - */ - @Test - public void testBlackNodeNumber() { - assertEquals(countLeftChildren(redBlackComparatorTree.getRoot(), 0), countRightChildren(redBlackComparatorTree.getRoot(), 0)); - } - - private int countLeftChildren(RBNode node, int currentBlackNumber) { - currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; - return node.getLeftChild() == null ? currentBlackNumber : countLeftChildren(node.getLeftChild(), currentBlackNumber); - } - - private int countRightChildren(RBNode node, int currentBlackNumber) { - currentBlackNumber = node.isRed() ? currentBlackNumber : currentBlackNumber + 1; - return node.getRightChild() == null ? currentBlackNumber : countRightChildren(node.getRightChild(), currentBlackNumber); - } -} diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java deleted file mode 100644 index 406fdf80d22..00000000000 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/RedBlackIntervalComparatorTreeTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.jgrapht.intervalgraph; - -import org.jgrapht.intervalgraph.interval.IntegerInterval; -import org.jgrapht.intervalgraph.interval.Interval; -import org.junit.Before; -import org.junit.Test; - -import java.util.LinkedList; -import java.util.List; - -import static org.junit.Assert.*; - -public class RedBlackIntervalComparatorTreeTest { - - private List sorted = new LinkedList<>(); - private RedBlackIntervalComparatorTree, Integer>> tree = new RedBlackIntervalComparatorTree<>(); - - @Before - public void setUp() { - for (int i = 0; i < 20; i++) { - IntegerInterval interval = new IntegerInterval(i, i+3); - tree.insert(new IntervalTreeNodeValue<>(interval)); - sorted.add(interval); - } - } - - @Test - public void testInorder() { - List, Integer>> result = tree.inorderValues(); - for (int i1 = 0, resultSize = result.size(); i1 < resultSize; i1++) { - Interval i = result.get(i1).getInterval(); - assertEquals("fault at " + i1,i, sorted.get(i1)); - } - - assertTrue(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); - tree.delete(new IntervalTreeNodeValue<>(new IntegerInterval(5,8))); - assertFalse(tree.contains(new IntervalTreeNodeValue<>(new IntegerInterval(5,8)))); - assertEquals(Integer.valueOf(19 + 3), tree.getRoot().getVal().getHighValue()); - } -} From d380a50ebe0dc06b7da67310d0ae0f2072193106 Mon Sep 17 00:00:00 2001 From: Abdallah Date: Tue, 8 May 2018 16:25:25 +0200 Subject: [PATCH 098/131] Tests for IntervalGraph Added Tests for weighted Graph --- .../intervalgraph/IntervalGraphTest.java | 215 +++++++++++++++++- 1 file changed, 210 insertions(+), 5 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java index 5778b8f466d..15b58498fa8 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java @@ -9,6 +9,8 @@ import org.junit.Before; import org.junit.Test; +import java.util.Set; + import static org.junit.Assert.*; /** @@ -18,13 +20,15 @@ public class IntervalGraphTest { private IntervalGraph, DefaultEdge, Integer, Integer> intervalGraph; + private IntervalGraph, DefaultEdge, Integer, Integer> weightedIntervalGraph; @Before public void setUp() { EdgeFactory, DefaultEdge> edgeFactory = new ClassBasedEdgeFactory<>(DefaultEdge.class); - intervalGraph = new IntervalGraph<>( - edgeFactory, false - ); + + intervalGraph = new IntervalGraph<>(edgeFactory, false); + + weightedIntervalGraph = new IntervalGraph<>(edgeFactory, true); } @Test(expected = IllegalArgumentException.class) @@ -58,18 +62,22 @@ public void containsEdge() { Interval interval1 = new Interval<>(5, 19); IntervalVertex vertex1 = IntervalVertex.of(1, interval1); intervalGraph.addVertex(vertex1); + weightedIntervalGraph.addVertex(vertex1); Interval interval2 = new Interval<>(9, 100); IntervalVertex vertex2 = IntervalVertex.of(2, interval2); intervalGraph.addVertex(vertex2); + weightedIntervalGraph.addVertex(vertex2); Interval interval3 = new Interval<>(6, 11); IntervalVertex vertex3 = IntervalVertex.of(3, interval3); intervalGraph.addVertex(vertex3); + weightedIntervalGraph.addVertex(vertex3); Interval interval4 = new Interval<>(1000, 1001); IntervalVertex vertex4 = IntervalVertex.of(4, interval4); intervalGraph.addVertex(vertex4); + weightedIntervalGraph.addVertex(vertex4); assertTrue(intervalGraph.containsEdge(vertex2, vertex1)); assertTrue(intervalGraph.containsEdge(vertex1, vertex2)); @@ -81,12 +89,62 @@ public void containsEdge() { assertFalse(intervalGraph.containsEdge(vertex2, vertex4)); assertFalse(intervalGraph.containsEdge(vertex3, vertex4)); - /* assertFalse(intervalGraph.containsEdge(vertex1, vertex1)); assertFalse(intervalGraph.containsEdge(vertex2, vertex2)); assertFalse(intervalGraph.containsEdge(vertex3, vertex3)); assertFalse(intervalGraph.containsEdge(vertex4, vertex4)); - */ + + assertTrue(weightedIntervalGraph.containsEdge(vertex2, vertex1)); + assertTrue(weightedIntervalGraph.containsEdge(vertex1, vertex2)); + assertTrue(weightedIntervalGraph.containsEdge(vertex1, vertex3)); + assertTrue(weightedIntervalGraph.containsEdge(vertex3, vertex1)); + assertTrue(weightedIntervalGraph.containsEdge(vertex2, vertex3)); + assertTrue(weightedIntervalGraph.containsEdge(vertex3, vertex2)); + assertFalse(weightedIntervalGraph.containsEdge(vertex1, vertex4)); + assertFalse(weightedIntervalGraph.containsEdge(vertex2, vertex4)); + assertFalse(weightedIntervalGraph.containsEdge(vertex3, vertex4)); + + assertFalse(weightedIntervalGraph.containsEdge(vertex1, vertex1)); + assertFalse(weightedIntervalGraph.containsEdge(vertex2, vertex2)); + assertFalse(weightedIntervalGraph.containsEdge(vertex3, vertex3)); + assertFalse(weightedIntervalGraph.containsEdge(vertex4, vertex4)); + } + + @Test + public void getAllEdges() { + Interval interval1 = new Interval<>(5, 19); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + weightedIntervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(9, 100); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + weightedIntervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(6, 11); + IntervalVertex vertex3 = IntervalVertex.of(3, interval3); + intervalGraph.addVertex(vertex3); + weightedIntervalGraph.addVertex(vertex3); + + Interval interval4 = new Interval<>(1000, 1001); + IntervalVertex vertex4 = IntervalVertex.of(4, interval4); + intervalGraph.addVertex(vertex4); + weightedIntervalGraph.addVertex(vertex4); + + Set edgeSet = intervalGraph.getAllEdges(vertex1, vertex2); + assertTrue(edgeSet.contains(intervalGraph.getEdge(vertex1, vertex2))); + assertEquals(edgeSet.size(), 1); + + edgeSet = intervalGraph.getAllEdges(vertex1, vertex4); + assertTrue(edgeSet.isEmpty()); + + Set weightedEdgeSet = weightedIntervalGraph.getAllEdges(vertex1, vertex2); + assertTrue(edgeSet.contains(weightedIntervalGraph.getEdge(vertex1, vertex2))); + assertEquals(weightedEdgeSet.size(), 1); + + weightedEdgeSet = weightedIntervalGraph.getAllEdges(vertex1, vertex4); + assertTrue(weightedEdgeSet.isEmpty()); } @Test @@ -94,26 +152,37 @@ public void addVertex() { Interval interval1 = new Interval<>(1, 2); IntervalVertex vertex1 = IntervalVertex.of(1, interval1); intervalGraph.addVertex(vertex1); + weightedIntervalGraph.addVertex(vertex1); IntervalVertex vertex2 = IntervalVertex.of(1, interval1); intervalGraph.addVertex(vertex2); + weightedIntervalGraph.addVertex(vertex2); assertTrue(intervalGraph.vertexSet().contains(vertex1)); assertTrue(intervalGraph.vertexSet().contains(vertex2)); assertEquals(intervalGraph.vertexSet().size(), 1); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex1)); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex2)); + assertEquals(weightedIntervalGraph.vertexSet().size(), 1); IntervalVertex vertex3 = IntervalVertex.of(2, interval1); intervalGraph.addVertex(vertex3); + weightedIntervalGraph.addVertex(vertex3); assertTrue(intervalGraph.vertexSet().contains(vertex3)); assertEquals(intervalGraph.vertexSet().size(), 2); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex3)); + assertEquals(weightedIntervalGraph.vertexSet().size(), 2); Interval interval2 = new Interval<>(2, 10); IntervalVertex vertex4 = IntervalVertex.of(2, interval2); intervalGraph.addVertex(vertex4); + weightedIntervalGraph.addVertex(vertex4); assertTrue(intervalGraph.vertexSet().contains(vertex4)); assertEquals(intervalGraph.vertexSet().size(), 3); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex4)); + assertEquals(weightedIntervalGraph.vertexSet().size(), 3); } @Test @@ -121,27 +190,39 @@ public void removeVertex() { Interval interval1 = new Interval<>(3, 20); IntervalVertex vertex1 = IntervalVertex.of(1, interval1); intervalGraph.addVertex(vertex1); + weightedIntervalGraph.addVertex(vertex1); Interval interval2 = new Interval<>(4, 100); IntervalVertex vertex2 = IntervalVertex.of(2, interval2); intervalGraph.addVertex(vertex2); + weightedIntervalGraph.addVertex(vertex2); assertTrue(intervalGraph.vertexSet().contains(vertex1)); assertTrue(intervalGraph.vertexSet().contains(vertex2)); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex1)); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex2)); intervalGraph.removeVertex(vertex1); + weightedIntervalGraph.removeVertex(vertex1); assertTrue(intervalGraph.vertexSet().contains(vertex2)); assertFalse(intervalGraph.vertexSet().contains(vertex1)); + assertTrue(weightedIntervalGraph.vertexSet().contains(vertex2)); + assertFalse(weightedIntervalGraph.vertexSet().contains(vertex1)); assertEquals(intervalGraph.vertexSet().size(), 1); + assertEquals(weightedIntervalGraph.vertexSet().size(), 1); intervalGraph.removeVertex(vertex2); + weightedIntervalGraph.removeVertex(vertex2); assertFalse(intervalGraph.vertexSet().contains(vertex1)); assertFalse(intervalGraph.vertexSet().contains(vertex2)); + assertFalse(weightedIntervalGraph.vertexSet().contains(vertex1)); + assertFalse(weightedIntervalGraph.vertexSet().contains(vertex2)); assertEquals(intervalGraph.vertexSet().size(), 0); + assertEquals(weightedIntervalGraph.vertexSet().size(), 0); } @Test @@ -149,20 +230,29 @@ public void containsVertex() { Interval interval1 = new Interval<>(8, 9); IntervalVertex vertex1 = IntervalVertex.of(1, interval1); intervalGraph.addVertex(vertex1); + weightedIntervalGraph.addVertex(vertex1); Interval interval2 = new Interval<>(27, 56); IntervalVertex vertex2 = IntervalVertex.of(2, interval2); intervalGraph.addVertex(vertex2); + weightedIntervalGraph.addVertex(vertex2); assertTrue(intervalGraph.containsVertex(vertex1)); assertTrue(intervalGraph.containsVertex(vertex2)); assertEquals(intervalGraph.vertexSet().size(), 2); + assertTrue(weightedIntervalGraph.containsVertex(vertex1)); + assertTrue(weightedIntervalGraph.containsVertex(vertex2)); + assertEquals(weightedIntervalGraph.vertexSet().size(), 2); intervalGraph.removeVertex(vertex1); + weightedIntervalGraph.removeVertex(vertex1); assertFalse(intervalGraph.containsVertex(vertex1)); assertTrue(intervalGraph.containsVertex(vertex2)); assertEquals(intervalGraph.vertexSet().size(), 1); + assertFalse(weightedIntervalGraph.containsVertex(vertex1)); + assertTrue(weightedIntervalGraph.containsVertex(vertex2)); + assertEquals(weightedIntervalGraph.vertexSet().size(), 1); } @Test @@ -236,6 +326,7 @@ public void vertexSet() { assertTrue(intervalGraph.vertexSet().contains(vertex1)); assertTrue(intervalGraph.vertexSet().contains(vertex2)); + assertEquals(intervalGraph.vertexSet().size(), 2); Interval interval3 = new Interval<>(100, 293); IntervalVertex vertex3 = IntervalVertex.of(1, interval3); @@ -244,6 +335,7 @@ public void vertexSet() { assertTrue(intervalGraph.vertexSet().contains(vertex1)); assertTrue(intervalGraph.vertexSet().contains(vertex2)); assertTrue(intervalGraph.vertexSet().contains(vertex3)); + assertEquals(intervalGraph.vertexSet().size(), 3); intervalGraph.removeVertex(vertex2); intervalGraph.removeVertex(vertex3); @@ -251,6 +343,11 @@ public void vertexSet() { assertTrue(intervalGraph.vertexSet().contains(vertex1)); assertFalse(intervalGraph.vertexSet().contains(vertex2)); assertFalse(intervalGraph.vertexSet().contains(vertex3)); + assertEquals(intervalGraph.vertexSet().size(), 1); + + intervalGraph.removeVertex(vertex1); + + assertTrue(intervalGraph.vertexSet().isEmpty()); } @Test @@ -273,4 +370,112 @@ public void getEdgeWeight() { assertEquals(intervalGraph.getEdgeWeight(edge), 1, 0); assertEquals(intervalGraph.getEdgeWeight(edge1), 1, 0); } + + @Test + public void cloneIntervalGraph() { + IntervalGraph, DefaultEdge, Integer, Integer> clonedIntervalGraph = + (IntervalGraph, DefaultEdge, Integer, Integer>) intervalGraph.clone(); + + assertEquals(clonedIntervalGraph.vertexSet(), intervalGraph.vertexSet()); + assertEquals(clonedIntervalGraph.edgeSet(), intervalGraph.edgeSet()); + assertEquals(clonedIntervalGraph.getEdgeFactory(), intervalGraph.getEdgeFactory()); + assertEquals(clonedIntervalGraph.isWeighted(), intervalGraph.isWeighted()); + assertTrue(clonedIntervalGraph.equals(intervalGraph)); + } + + @Test + public void degreeOf() { + Interval interval1 = new Interval<>(-3, 1); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(0, 4); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(2, 29); + IntervalVertex vertex3 = IntervalVertex.of(3, interval3); + intervalGraph.addVertex(vertex3); + + Interval interval4 = new Interval<>(348, 2394); + IntervalVertex vertex4 = IntervalVertex.of(4, interval4); + intervalGraph.addVertex(vertex4); + + assertEquals(intervalGraph.degreeOf(vertex2), 2); + assertEquals(intervalGraph.degreeOf(vertex1), 1); + assertEquals(intervalGraph.degreeOf(vertex3), 1); + assertEquals(intervalGraph.degreeOf(vertex4), 0); + } + + @Test + public void edgesOf() { + Interval interval1 = new Interval<>(-10, 19); + IntervalVertex vertex1 = IntervalVertex.of(1, interval1); + intervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(9, 100); + IntervalVertex vertex2 = IntervalVertex.of(2, interval2); + intervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(12, 39); + IntervalVertex vertex3 = IntervalVertex.of(3, interval3); + intervalGraph.addVertex(vertex3); + + Interval interval4 = new Interval<>(1000, 1001); + IntervalVertex vertex4 = IntervalVertex.of(4, interval4); + intervalGraph.addVertex(vertex4); + + Set edgesOfVertex1 = intervalGraph.edgesOf(vertex1); + assertTrue(edgesOfVertex1.contains(intervalGraph.getEdge(vertex1, vertex2))); + assertTrue(edgesOfVertex1.contains(intervalGraph.getEdge(vertex2, vertex1))); + assertTrue(edgesOfVertex1.contains(intervalGraph.getEdge(vertex1, vertex3))); + assertEquals(edgesOfVertex1.size(), 2); + + Set edgesOfVertex2 = intervalGraph.edgesOf(vertex2); + assertTrue(edgesOfVertex2.contains(intervalGraph.getEdge(vertex1, vertex2))); + assertTrue(edgesOfVertex2.contains(intervalGraph.getEdge(vertex2, vertex1))); + assertTrue(edgesOfVertex2.contains(intervalGraph.getEdge(vertex2, vertex3))); + assertEquals(edgesOfVertex1.size(), 2); + + Set edgesOfVertex3 = intervalGraph.edgesOf(vertex3); + assertTrue(edgesOfVertex3.contains(intervalGraph.getEdge(vertex2, vertex3))); + assertTrue(edgesOfVertex3.contains(intervalGraph.getEdge(vertex3, vertex2))); + assertTrue(edgesOfVertex3.contains(intervalGraph.getEdge(vertex1, vertex3))); + assertEquals(edgesOfVertex1.size(), 2); + + Set edgesOfVertex4 = intervalGraph.edgesOf(vertex4); + assertTrue(edgesOfVertex4.isEmpty()); + } + + @Test + public void isWeighted() { + assertFalse(intervalGraph.isWeighted()); + assertTrue(weightedIntervalGraph.isWeighted()); + } + + @Test + public void setEdgeWeight() { + Interval interval1 = new Interval<>(2, 19); + IntervalVertex vertex1 = IntervalVertex.of(2, interval1); + weightedIntervalGraph.addVertex(vertex1); + + Interval interval2 = new Interval<>(-4, 8); + IntervalVertex vertex2 = IntervalVertex.of(1, interval2); + weightedIntervalGraph.addVertex(vertex2); + + Interval interval3 = new Interval<>(11, 198); + IntervalVertex vertex3 = IntervalVertex.of(3, interval3); + weightedIntervalGraph.addVertex(vertex3); + + DefaultEdge edge1 = weightedIntervalGraph.getEdge(vertex1, vertex2); + DefaultEdge edge2 = weightedIntervalGraph.getEdge(vertex1, vertex3); + + intervalGraph.setEdgeWeight(edge1, 3); + intervalGraph.setEdgeWeight(edge2, 93); + + assertEquals(intervalGraph.getEdgeWeight(edge1), 3); + assertEquals(intervalGraph.getEdgeWeight(edge2), 93); + + } + } From 2e57f7bb36a3b486b56c1dea42051da0be7ca82c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 May 2018 21:14:39 +0200 Subject: [PATCH 099/131] fixed tests --- .../intervalgraph/IntervalGraphTest.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java index 15b58498fa8..e60ddac48d9 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/IntervalGraphTest.java @@ -3,6 +3,7 @@ import org.jgrapht.EdgeFactory; import org.jgrapht.graph.ClassBasedEdgeFactory; import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.DefaultWeightedEdge; import org.jgrapht.intervalgraph.interval.Interval; import org.jgrapht.intervalgraph.interval.IntervalVertex; import org.jgrapht.intervalgraph.interval.IntervalVertexInterface; @@ -20,15 +21,16 @@ public class IntervalGraphTest { private IntervalGraph, DefaultEdge, Integer, Integer> intervalGraph; - private IntervalGraph, DefaultEdge, Integer, Integer> weightedIntervalGraph; + private IntervalGraph, DefaultWeightedEdge, Integer, Integer> weightedIntervalGraph; @Before public void setUp() { - EdgeFactory, DefaultEdge> edgeFactory = new ClassBasedEdgeFactory<>(DefaultEdge.class); + EdgeFactory, DefaultEdge> edgeFactory1 = new ClassBasedEdgeFactory<>(DefaultEdge.class); + EdgeFactory, DefaultWeightedEdge> edgeFactory2 = new ClassBasedEdgeFactory<>(DefaultWeightedEdge.class); - intervalGraph = new IntervalGraph<>(edgeFactory, false); + intervalGraph = new IntervalGraph<>(edgeFactory1, false); - weightedIntervalGraph = new IntervalGraph<>(edgeFactory, true); + weightedIntervalGraph = new IntervalGraph<>(edgeFactory2, true); } @Test(expected = IllegalArgumentException.class) @@ -140,7 +142,7 @@ public void getAllEdges() { assertTrue(edgeSet.isEmpty()); Set weightedEdgeSet = weightedIntervalGraph.getAllEdges(vertex1, vertex2); - assertTrue(edgeSet.contains(weightedIntervalGraph.getEdge(vertex1, vertex2))); + assertTrue(weightedEdgeSet.contains(weightedIntervalGraph.getEdge(vertex1, vertex2))); assertEquals(weightedEdgeSet.size(), 1); weightedEdgeSet = weightedIntervalGraph.getAllEdges(vertex1, vertex4); @@ -467,14 +469,14 @@ public void setEdgeWeight() { IntervalVertex vertex3 = IntervalVertex.of(3, interval3); weightedIntervalGraph.addVertex(vertex3); - DefaultEdge edge1 = weightedIntervalGraph.getEdge(vertex1, vertex2); - DefaultEdge edge2 = weightedIntervalGraph.getEdge(vertex1, vertex3); + DefaultWeightedEdge edge1 = weightedIntervalGraph.getEdge(vertex1, vertex2); + DefaultWeightedEdge edge2 = weightedIntervalGraph.getEdge(vertex1, vertex3); - intervalGraph.setEdgeWeight(edge1, 3); - intervalGraph.setEdgeWeight(edge2, 93); + weightedIntervalGraph.setEdgeWeight(edge1, 3.0); + weightedIntervalGraph.setEdgeWeight(edge2, 93.0); - assertEquals(intervalGraph.getEdgeWeight(edge1), 3); - assertEquals(intervalGraph.getEdgeWeight(edge2), 93); + assertEquals(3.0, weightedIntervalGraph.getEdgeWeight(edge1), 0.001); + assertEquals(93.0, weightedIntervalGraph.getEdgeWeight(edge2),0.001); } From 79855990f5515f2878e0f1ac17ef22f2bb776684 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Sat, 12 May 2018 16:35:23 +0200 Subject: [PATCH 100/131] Finally fixed decomposition algo --- .../IntervalgraphDecomposition.java | 85 +++++++++++----- .../IntervalgraphDecompositionTest.java | 98 +++++++++++++------ 2 files changed, 127 insertions(+), 56 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index d2059c20087..02ddd2d59a7 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -9,8 +9,11 @@ public class IntervalgraphDecomposition> { - private Graph>, DefaultEdge> treeDecomposition = null; - private Set> currentVertex, root = null; + private Graph decomposition = null; + private Map>> decompositionMap = null; + private Integer currentVertex = null; + private Set roots = null; + private Set> currentIntervalSet = null; private List> startSort, endSort; public IntervalgraphDecomposition(Graph graph) @@ -35,20 +38,31 @@ public IntervalgraphDecomposition(List> intervals) private void computeTreeDecomposition() { - if(treeDecomposition != null) + if(decomposition != null) return; initTreeDecomposition(); int endIndex=0; - for(Interval iv: startSort) { + Interval last = null; + for(Interval current : startSort) + { while(endSort.get(endIndex).getEnd().compareTo( - iv.getStart()) < 0) + current.getStart()) < 0) { addForget(endSort.get(endIndex)); endIndex++; } - addIntroduce(iv); + // root or leaf node AND last one had no successor (i.e. end of last is before start of current) + if(currentIntervalSet.size() != 0 || last == null) + addIntroduce(current); + else if(last.getEnd().compareTo( + current.getStart()) < 0) + { + addNewRoot(); + addIntroduce(current); + } + last = current; } while(endIndex < endSort.size()-1) { addForget(endSort.get(endIndex++)); @@ -57,41 +71,64 @@ private void computeTreeDecomposition() private void initTreeDecomposition() { - treeDecomposition = new DefaultDirectedGraph>,DefaultEdge>(DefaultEdge.class); - root = new TreeSet>(); - treeDecomposition.addVertex(root); - currentVertex = root; + decomposition = new DefaultDirectedGraph(DefaultEdge.class); + decompositionMap = new HashMap>>(); + roots = new HashSet(); + currentVertex = 0; + roots.add(currentVertex); + currentIntervalSet = new HashSet>(); + decompositionMap.put(currentVertex,currentIntervalSet); + decomposition.addVertex(currentVertex); + } + + private void addNewRoot() + { + Set> nextVertex = new HashSet>(); + currentIntervalSet = nextVertex; + decomposition.addVertex(currentVertex+1); + roots.add(currentVertex+1); + decompositionMap.put(currentVertex+1, nextVertex); + currentVertex++; } private void addIntroduce(Interval vertex) { - Set> nextVertex = new TreeSet>(currentVertex); + Set> nextVertex = new HashSet>(currentIntervalSet); nextVertex.add(vertex); - treeDecomposition.addVertex(nextVertex); - treeDecomposition.addEdge(currentVertex, nextVertex); - currentVertex = nextVertex; + currentIntervalSet = nextVertex; + decomposition.addVertex(currentVertex+1); + decomposition.addEdge(currentVertex, currentVertex+1); + decompositionMap.put(currentVertex+1, nextVertex); + currentVertex++; } private void addForget(Interval vertex) { - Set> nextVertex = new TreeSet>(currentVertex); + Set> nextVertex = new HashSet>(currentIntervalSet); nextVertex.remove(vertex); - treeDecomposition.addVertex(nextVertex); - treeDecomposition.addEdge(currentVertex, nextVertex); - currentVertex = nextVertex; + currentIntervalSet = nextVertex; + decomposition.addVertex(currentVertex+1); + decomposition.addEdge(currentVertex, currentVertex+1); + decompositionMap.put(currentVertex+1, nextVertex); + currentVertex++; } - public Graph>,DefaultEdge> getTreeDecomposition() + public Graph getTreeDecomposition() { - if(treeDecomposition == null) computeTreeDecomposition(); - return treeDecomposition; + if(decomposition == null) computeTreeDecomposition(); + return decomposition; + } + + public Map>> getMap(){ + if(decompositionMap == null) computeTreeDecomposition(); + return decompositionMap; } - public Set> getRoot() + public Set getRoot() { - if(root == null) computeTreeDecomposition(); - return root; + if(roots == null) computeTreeDecomposition(); + return roots; } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index 6beacedc528..cf83e1e7a31 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -3,8 +3,10 @@ import static org.junit.Assert.*; import java.util.*; +import java.util.Map.Entry; import org.jgrapht.*; +import org.jgrapht.alg.connectivity.ConnectivityInspector; import org.jgrapht.alg.treedecomposition.*; import org.jgrapht.event.*; import org.jgrapht.graph.*; @@ -15,47 +17,80 @@ public class IntervalgraphDecompositionTest { - private void isNiceTreeDecomposition(Graph,E> graph, Set root){ - if(root.size() != 0) assertFalse(root+" is no valid root", true); - Queue> queue = new LinkedList>(); + private void isNiceDecomposition(Graph decomposition, Map> map, V root){ + if(map.get(root).size() != 0) assertFalse(root+" is no valid root", true); + Queue queue = new LinkedList(); queue.add(root); while(!queue.isEmpty()) { - Set current = queue.poll(); - List> successor = Graphs.successorListOf(graph, current); - System.out.println("DEBUG: current:"+current+", neighbor:"+successor); - if(successor.size() == 0 && current.size() <= 1) continue; //leaf node + V current = queue.poll(); + List successor = Graphs.successorListOf(decomposition, current); + if(successor.size() == 0 && map.get(current).size() <= 1) continue; //leaf node if(successor.size() == 1) //forget or introduce { - Set next = successor.get(0); + V next = successor.get(0); queue.add(next); - Set union = new HashSet(current); - union.addAll(next); - if(union.size() == next.size() || union.size() == current.size()) + Set union = new HashSet(map.get(current)); + union.addAll(map.get(next)); + if(union.size() == map.get(next).size() || union.size() == map.get(current).size()) { - if(current.size() == next.size()+1) continue; //introduce - else if(current.size()+1 == next.size()) continue; //forget + if(map.get(current).size() == map.get(next).size()-1) continue; //introduce + else if(map.get(current).size()-1 == map.get(next).size()) continue; //forget } } if(successor.size() == 2) //join { - Set first = successor.get(0); - Set second = successor.get(1); + V first = successor.get(0); + V second = successor.get(1); queue.add(first); queue.add(second); - Set union = new HashSet(current); - union.addAll(first); - union.addAll(second); - if(union.size() == current.size() - && union.size() == first.size() - && union.size() == second.size()) + Set union = new HashSet(map.get(current)); + union.addAll(map.get(first)); + union.addAll(map.get(second)); + if(union.size() == map.get(current).size() + && union.size() == map.get(first).size() + && union.size() == map.get(second).size()) continue; //join node! } - assertFalse("Vertex Set "+current+" is no valid nice tree node in tree "+graph, true); //no valid node! + assertFalse("Vertex Set "+current+" is not a valid node for a nice decomposition\n in tree "+decomposition+"\n with map "+map, true); //no valid node! } assertTrue(true); } + private void isDecomposition(Graph oldGraph, Graph decomposition, Map> map){ + Set edgeSet = oldGraph.edgeSet(); + Set vertexSet = decomposition.vertexSet(); + //Every edge is represented + for(F e : edgeSet) + { + boolean hasVertex = false; + for(V v : vertexSet) + { + if(map.get(v).contains(oldGraph.getEdgeSource(e)) && map.get(v).contains(oldGraph.getEdgeTarget(e))) { + hasVertex = true; + continue; + } + } + if(!hasVertex) assertFalse("Edge "+e+" is not found\n in graph "+decomposition+"\n with map "+map, true); + } + //every vertex has non-empty connected set of vertex sets + Set oldVertexSet = oldGraph.vertexSet(); + for(W w : oldVertexSet) + { + Set keySet = new HashSet(); + for(Entry> entry : map.entrySet()) + { + if(entry.getValue().contains(w)) + keySet.add(entry.getKey()); + } + //not empty + assertFalse("Vertex "+w+" is not represented\n in decomposition "+decomposition+"\n and map "+map, keySet.isEmpty()); + //connected + Graph subgraph = new AsSubgraph(decomposition,keySet); + assertTrue("Vertex "+w+" is not connected\n in decomposition "+decomposition+"\n and map "+map,GraphTests.isConnected(subgraph)); + } + } + @Test public void testIntervalgraphDecompositionForRegularGraphs() { @@ -80,26 +115,25 @@ public void testIntervalgraphDecompositionForIntervalGraphs() public void testIntervalgraphDecompositionForIntervalLists() { List> list = new ArrayList>(); + //unconnected + list.add(new Interval(-2,-1)); //just path for(int i = 0; i<10; i++) { list.add(new Interval(i,i+1)); } //and to spice it up, a clique - for(int i = 0; i<5; i++) + for(int i = 0; i<10; i++) { list.add(new Interval(10,10+i)); } IntervalgraphDecomposition decompalg = new IntervalgraphDecomposition<>(list); - Graph>,DefaultEdge> decomp = decompalg.getTreeDecomposition(); - Set> root = decompalg.getRoot(); - isNiceTreeDecomposition(decomp,root); - } - - @Test - public void testGetTreeDecomposition() - { - fail("Not yet implemented"); + Graph decomp = decompalg.getTreeDecomposition(); + Map>> map = decompalg.getMap(); + Set roots = decompalg.getRoot(); + for(Integer root : roots) + isNiceDecomposition(decomp,map,root); + } } From e3332c45539600ad6dff27e8062e0cfdc1d731b5 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Sat, 12 May 2018 18:30:49 +0200 Subject: [PATCH 101/131] added Comparator to Intervals added radixSort to the Recognizer for Ending Point sorted list --- .../IntervalGraphRecognizer.java | 83 ++++++++++++++++++- .../IntervalgraphDecomposition.java | 24 +----- .../intervalgraph/interval/Interval.java | 37 +++++++++ .../IntervalgraphDecompositionTest.java | 4 +- 4 files changed, 124 insertions(+), 24 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 34e43e0ed3c..372bbfe9bc4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -41,7 +41,7 @@ public final class IntervalGraphRecognizer * Stores the computed interval graph representation (or null if no such representation * exists) of the graph. */ - private ArrayList> intervalsSortedByStartingPoint; + private ArrayList> intervalsSortedByStartingPoint, intervalsSortedByEndingPoint; private Map, V> intervalToVertexMap; private Map> vertexToIntervalMap; @@ -249,6 +249,87 @@ public ArrayList> getIntervalsSortedByStartingPoint() { return this.intervalsSortedByStartingPoint; } + + private static ArrayList> radixSortInteger(List> list){ + ArrayList> positiveList = new ArrayList>(list.size()); + ArrayList> negativeList = new ArrayList>(list.size()); + for(Interval interval : list) { + if(interval.getEnd() < 0) negativeList.add(interval); + else positiveList.add(interval); + } + + positiveList = radixSortNatural(positiveList); + negativeList = radixSortNatural(negativeList); + ArrayList> negativeListReverse = new ArrayList>(negativeList.size()); + + for(int i = 0; i < negativeList.size(); i++) { + negativeListReverse.add(negativeList.get(i)); + } + negativeListReverse.addAll(positiveList); + return negativeListReverse; + } + + private static ArrayList> radixSortNatural(List> list) + { + ArrayList> intervals = new ArrayList>(list); + ArrayList> intervalsTmp = new ArrayList>(intervals.size()); + + //init + for(int i = 0; i max = Collections.max(intervals,Interval.getEndingComparator()); + Integer power = 1; + //every digit + while(max.getEnd()/(power) > 0) + { + int[] buckets = new int[10]; + + //count all numbers with digit at position exponent + for(int i = 0; i < intervals.size(); i++) + { + int digit = Math.abs( (intervals.get(i).getEnd() / power ) % 10); + System.out.println(digit); + buckets[digit]++; + } + + //compute position of digits + for(int i = 1; i < 10; i++) + { + buckets[i] += buckets[i-1]; + } + + //sort after digit in intervalsTmp + for(int i = intervals.size()-1; i >= 0; i--) + { + int digit = Math.abs( ( intervals.get(i).getEnd() / power ) % 10 ); + int position = buckets[digit]-1; + buckets[digit] = position; + System.out.println(position +":"+ i+":"+intervals.size()+":"+intervalsTmp.size()); + intervalsTmp.set(position,intervals.get(i)); + } + + //swap both + ArrayList> tmp = intervals; + intervals = intervalsTmp; + intervalsTmp = tmp; + + power*=10; + } + return intervals; + } + + /** + * Returns the list of all intervals sorted by ending point, or null, if the graph was not an interval graph. + * + * @return The list of all intervals sorted by ending point, or null, if the graph was not an interval graph. + */ + public ArrayList> getIntervalsSortedByEndingPoint() + { + if(this.intervalsSortedByEndingPoint == null) + this.intervalsSortedByEndingPoint = radixSortInteger(this.intervalsSortedByStartingPoint); + return this.intervalsSortedByEndingPoint; + } /** * Returns a mapping of the constructed intervals to the vertices of the original graph, or null, if the graph was not an interval graph. diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index 02ddd2d59a7..8dd1c3a02aa 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -32,8 +32,8 @@ public IntervalgraphDecomposition(List> intervals) { startSort = new ArrayList<>(intervals); endSort = new ArrayList<>(intervals); - startSort.sort(new IntervalVertexComparator(true)); - endSort.sort(new IntervalVertexComparator(false)); + startSort.sort(Interval.getStartingComparator()); + endSort.sort(Interval.getEndingComparator()); } private void computeTreeDecomposition() @@ -130,24 +130,4 @@ public Set getRoot() if(roots == null) computeTreeDecomposition(); return roots; } - - - - private class IntervalVertexComparator implements Comparator> { - - private boolean start = true;; - - public IntervalVertexComparator(boolean startKey) { - start = startKey; - } - - @Override - public int compare(Interval o1, Interval o2) - { - if(start) - return o1.getStart().compareTo(o2.getStart()); - else - return o1.getEnd().compareTo(o2.getEnd()); - } - } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 3a46597e65e..5894cd99f2f 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -1,5 +1,6 @@ package org.jgrapht.intervalgraph.interval; +import java.util.Comparator; import java.util.Objects; /** @@ -135,4 +136,40 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(start, end); } + + + /** + * getter for a Comparator, which only compares the starting points + * @return a starting point comparator + */ + public static > StartingComparator getStartingComparator() { + return new StartingComparator(); + } + + /** + * getter for a Comparator, which only compares the ending points + * @return a ending point comparator + */ + public static > EndingComparator getEndingComparator() { + return new EndingComparator(); + } + + private static class StartingComparator> implements Comparator>{ + + @Override + public int compare(Interval o1, Interval o2) { + return o1.getStart().compareTo(o2.getStart()); + } + + } + + private static class EndingComparator> implements Comparator>{ + + @Override + public int compare(Interval o1, Interval o2) { + return o1.getEnd().compareTo(o2.getEnd()); + } + + + } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index cf83e1e7a31..5e372ffa960 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -7,6 +7,7 @@ import org.jgrapht.*; import org.jgrapht.alg.connectivity.ConnectivityInspector; +import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; import org.jgrapht.alg.treedecomposition.*; import org.jgrapht.event.*; import org.jgrapht.graph.*; @@ -105,7 +106,7 @@ public void testIntervalgraphDecompositionForRegularGraphs() @Test public void testIntervalgraphDecompositionForIntervalGraphs() { - IntervalGraphInterface ig = new CenteredIntervalTree<>(); + //IntervalGraphInterface ig = new CenteredIntervalTree<>(); //TODO: change ig //IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(ig); assertTrue(false); @@ -116,6 +117,7 @@ public void testIntervalgraphDecompositionForIntervalLists() { List> list = new ArrayList>(); //unconnected + list.add(new Interval(-4,-3)); list.add(new Interval(-2,-1)); //just path for(int i = 0; i<10; i++) From 1d77dbb413c1f0918a360ddb3e0e9a070518a630 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Mon, 14 May 2018 20:42:37 +0200 Subject: [PATCH 102/131] fixes and changes in the structure --- .../IntervalgraphDecomposition.java | 262 +++++++++++++++--- .../IntervalgraphDecompositionTest.java | 95 +++++-- 2 files changed, 295 insertions(+), 62 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index 8dd1c3a02aa..f0e020a9598 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -1,52 +1,173 @@ package org.jgrapht.alg.treedecomposition; import java.util.*; +import java.util.Map.*; import org.jgrapht.*; +import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; import org.jgrapht.graph.*; import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; -public class IntervalgraphDecomposition> +/** + * Class for calculating the nice Tree Decomposition for interval graphs + * + * @param the value of the intervals of the interval graph + * + * @author Ira Justus Fesefeldt (PhoenixIra) + * @since Mai 14, 2018 + */ +public class IntervalgraphDecomposition,V> { + //resulting forest of the decomposition private Graph decomposition = null; - private Map>> decompositionMap = null; - private Integer currentVertex = null; + + //map from decomposition nodes to the interval sets + private Map> decompositionIntervalMap = null; + + //the roots of the forest private Set roots = null; - private Set> currentIntervalSet = null; + + //input to the algorithm, list of sorted intervals private List> startSort, endSort; + private Map,V> intervalToVertexMap; + private Map> vertexToIntervalMap; - public IntervalgraphDecomposition(Graph graph) + //helper attributes + private Integer currentVertex = null; + private Set currentSet = null; + + /** + * Private constructor for the factory methods, which changes the inputs + * + * @param sortedByStartPoint the intervals sorted after the starting points + * @param sortedByEndPoint the intervals sorted after the ending points + * @param intervalToVertexMap maps intervals to the vertices of the graph (may be the same) + */ + private IntervalgraphDecomposition(List> sortedByStartPoint, + List> sortedByEndPoint, + Map,V> intervalToVertexMap, + Map> vertexToIntervalMap) { - throw new UnsupportedOperationException("Not yet implemented"); - //TODO + this.startSort = sortedByStartPoint; + this.endSort = sortedByEndPoint; + this.intervalToVertexMap = intervalToVertexMap; + this.vertexToIntervalMap = vertexToIntervalMap; } - public IntervalgraphDecomposition(IntervalGraphInterface graph) + /** + * Factory method for creating a nice tree decomposition for interval graphs. + * This factory method uses general graphs and the IntervalGraphRecognizer to generate a list of intervals + * sorted by starting and ending points. + * The complexity of this method depends on the sorting algorithm in IntervalGraphRecognizer (probably quasi linear in the number of intervals) + * + * @param graph the graph which should transformed to an interval graph and then into a corresponding nice tree decomposition + * @return the algorithm for the computation of the nice tree decomposition, returns null if graph was no interval graph + * @see IntervalGraphRecognizer + */ + public static IntervalgraphDecomposition create(Graph graph){ + IntervalGraphRecognizer recog = new IntervalGraphRecognizer<>(graph); + HashMap> vertexToIntegerMap = new HashMap<>(recog.getVertexToIntervalMap().size()); + for(Entry> entry : recog.getVertexToIntervalMap().entrySet()) + vertexToIntegerMap.put(entry.getKey(), entry.getValue().getInterval()); + if(recog.isIntervalGraph()) + return new IntervalgraphDecomposition + (recog.getIntervalsSortedByStartingPoint(), + recog.getIntervalsSortedByStartingPoint(), + recog.getIntervalToVertexMap(), + vertexToIntegerMap); + else + return null; + } + + /** + * Factory method for creating a nice tree decomposition for interval graphs. + * This factory method extracts the intervals from the interval graph and uses them as an input for the computation. + * The complexity of this method depends on the sorting algorithm of ArrayList (probably O(|V| log(|V|)) + * + * @param intervalGraph the input for which a nice tree decomposition should be computed + * @return the algorithm for the computation of the nice tree decomposition + * @see ArrayList#sort(Comparator) + */ + public static , E, VertexType, T extends Comparable> + IntervalgraphDecomposition create(IntervalGraph intervalGraph) { - throw new UnsupportedOperationException("Not yet implemented"); - //TODO + Set vertexSet = intervalGraph.vertexSet(); + List> intervals = new ArrayList>(vertexSet.size()); + Map,V> intervalToVertexMap = new HashMap<>(vertexSet.size()); + Map> vertexToIntervalMap = new HashMap<>(vertexSet.size()); + for(V iv : vertexSet) { + intervals.add(iv.getInterval()); + intervalToVertexMap.put(iv.getInterval(), iv); + vertexToIntervalMap.put(iv, iv.getInterval()); + } + ArrayList> startSort = new ArrayList<>(intervals); + ArrayList> endSort = new ArrayList<>(intervals); + startSort.sort(Interval.getStartingComparator()); + endSort.sort(Interval.getEndingComparator()); + return new IntervalgraphDecomposition(startSort, endSort,intervalToVertexMap, vertexToIntervalMap); } - public IntervalgraphDecomposition(List> intervals) + /** + * Factory method for creating a nice tree decomposition for interval graphs. + * This factory method needs to lists of intervals, the first sorted after starting points, the second after ending points + * The complexity of this method is linear in the number of intervals + * + * @param sortedByStartPoint a list of all intervals sorted by the starting point + * @param sortedByEndPoint a list of all intervals sorted by the ending point + * @return the algorithm for the computation of the nice tree decomposition + */ + public static > IntervalgraphDecomposition> create(List> sortedByStartPoint, + List> sortedByEndPoint) { - startSort = new ArrayList<>(intervals); - endSort = new ArrayList<>(intervals); + HashMap,Interval> identity = new HashMap<>(sortedByStartPoint.size()); + for(Interval interval : sortedByStartPoint) + identity.put(interval, interval); + return new IntervalgraphDecomposition>(new ArrayList>(sortedByStartPoint), + new ArrayList>(sortedByEndPoint), + identity, identity); + } + + /** + * Factory method for creating a nice tree decomposition for interval graphs. + * This factory method needs to lists of intervals, which then is sorted by ArrayList.sort(). + * The complexity of this method depends on the sorting Algorithm of ArrayList (probably O(|List| log(|List|)) + * + * @param intervals the (unsorted) list of all intervals + * @return the algorithm for the computation of the nice tree decomposition + * @see ArrayList#sort(Comparator) + */ + public static > IntervalgraphDecomposition> create(List> intervals) + { + ArrayList> startSort = new ArrayList<>(intervals); + ArrayList> endSort = new ArrayList<>(intervals); startSort.sort(Interval.getStartingComparator()); endSort.sort(Interval.getEndingComparator()); + HashMap,Interval> identity = new HashMap<>(startSort.size()); + for(Interval interval : startSort) + identity.put(interval, interval); + return new IntervalgraphDecomposition>(startSort, endSort,identity,identity); } - private void computeTreeDecomposition() + /** + * Main method for computing the nice tree decomposition + */ + private void computeNiceDecomposition() { + //already computed if(decomposition != null) return; - initTreeDecomposition(); + //create all objects and set new root + initDecomposition(); int endIndex=0; Interval last = null; + + //as long as intervals remain for(Interval current : startSort) { + //first forget until you need to introduce new nodes while(endSort.get(endIndex).getEnd().compareTo( current.getStart()) < 0) { @@ -54,80 +175,141 @@ private void computeTreeDecomposition() endIndex++; } // root or leaf node AND last one had no successor (i.e. end of last is before start of current) - if(currentIntervalSet.size() != 0 || last == null) + if(currentSet.size() != 0 || last == null) + { + //no root node, so introduce addIntroduce(current); + } else if(last.getEnd().compareTo( current.getStart()) < 0) { + //root node! addNewRoot(); addIntroduce(current); } + //save last node for root detection last = current; } + //add the last forget nodes while(endIndex < endSort.size()-1) { addForget(endSort.get(endIndex++)); } } - private void initTreeDecomposition() + /** + * Method for initializing the decomposition + */ + private void initDecomposition() { + //creating objects decomposition = new DefaultDirectedGraph(DefaultEdge.class); - decompositionMap = new HashMap>>(); + decompositionIntervalMap = new HashMap>(); roots = new HashSet(); + + //create root currentVertex = 0; roots.add(currentVertex); - currentIntervalSet = new HashSet>(); - decompositionMap.put(currentVertex,currentIntervalSet); + currentSet = new HashSet<>(); + decompositionIntervalMap.put(currentVertex,currentSet); decomposition.addVertex(currentVertex); } + /** + * Method for adding a new root + */ private void addNewRoot() { - Set> nextVertex = new HashSet>(); - currentIntervalSet = nextVertex; + Set nextVertex = new HashSet<>(); + currentSet = nextVertex; decomposition.addVertex(currentVertex+1); roots.add(currentVertex+1); - decompositionMap.put(currentVertex+1, nextVertex); + decompositionIntervalMap.put(currentVertex+1, nextVertex); + + //new integer for next vertex currentVertex++; } - private void addIntroduce(Interval vertex) + /** + * Method for adding introducing nodes + * @param vertex the vertex, which is introduced + */ + private void addIntroduce(Interval interval) { - Set> nextVertex = new HashSet>(currentIntervalSet); - nextVertex.add(vertex); - currentIntervalSet = nextVertex; + Set nextVertex = new HashSet<>(currentSet); + nextVertex.add(intervalToVertexMap.get(interval)); + currentSet = nextVertex; decomposition.addVertex(currentVertex+1); decomposition.addEdge(currentVertex, currentVertex+1); - decompositionMap.put(currentVertex+1, nextVertex); + decompositionIntervalMap.put(currentVertex+1, nextVertex); + + //new integer for next vertex currentVertex++; } - private void addForget(Interval vertex) + /** + * method for adding forget nodes + * @param vertex the vertex, which is introduced + */ + private void addForget(Interval interval) { - Set> nextVertex = new HashSet>(currentIntervalSet); - nextVertex.remove(vertex); - currentIntervalSet = nextVertex; + Set nextVertex = new HashSet<>(currentSet); + nextVertex.remove(intervalToVertexMap.get(interval)); + currentSet = nextVertex; decomposition.addVertex(currentVertex+1); decomposition.addEdge(currentVertex, currentVertex+1); - decompositionMap.put(currentVertex+1, nextVertex); + decompositionIntervalMap.put(currentVertex+1, nextVertex); + + //new integer for next vertex currentVertex++; } - - public Graph getTreeDecomposition() + /** + * getter for the decomposition as an directed graph + * + * @return the computed decomposition + */ + public Graph getDecomposition() { - if(decomposition == null) computeTreeDecomposition(); + if(decomposition == null) computeNiceDecomposition(); return decomposition; } - public Map>> getMap(){ - if(decompositionMap == null) computeTreeDecomposition(); - return decompositionMap; + /** + * getter for the map from integer nodes of the decomposition to the intervals of the interval graph + * + * @return a nodes to interval map + */ + public Map> getMap(){ + if(decompositionIntervalMap == null) computeNiceDecomposition(); + return decompositionIntervalMap; } + /** + * getter for all roots of the decomposition + * + * @return a set of roots + */ public Set getRoot() { - if(roots == null) computeTreeDecomposition(); + if(roots == null) computeNiceDecomposition(); return roots; } + + /** + * getter for interval to vertex Map + * + * @return a map that maps intervals to vertices + */ + public Map,V> getIntervalToVertexMap(){ + return intervalToVertexMap; + } + + /** + * getter for vertex to interval map + * + * @return a map that maps vertices to intervals + */ + public Map> getVertexToIntervalMap(){ + return vertexToIntervalMap; + } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index 5e372ffa960..2a1d1e5a926 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -6,10 +6,7 @@ import java.util.Map.Entry; import org.jgrapht.*; -import org.jgrapht.alg.connectivity.ConnectivityInspector; -import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; import org.jgrapht.alg.treedecomposition.*; -import org.jgrapht.event.*; import org.jgrapht.graph.*; import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; @@ -18,10 +15,18 @@ public class IntervalgraphDecompositionTest { - private void isNiceDecomposition(Graph decomposition, Map> map, V root){ - if(map.get(root).size() != 0) assertFalse(root+" is no valid root", true); + private void testNiceDecomposition(Graph decomposition, Map> map, Set root){ + Queue queue = new LinkedList(); - queue.add(root); + + //test and add all roots + for(V v: root) { + assertTrue(v+" is no valid root" + + "\n in decomposition "+decomposition + + "\n and map"+map, map.get(v).size() == 0); + queue.add(v); + } + while(!queue.isEmpty()) { V current = queue.poll(); @@ -53,12 +58,14 @@ private void isNiceDecomposition(Graph decomposition, Map> && union.size() == map.get(second).size()) continue; //join node! } - assertFalse("Vertex Set "+current+" is not a valid node for a nice decomposition\n in tree "+decomposition+"\n with map "+map, true); //no valid node! + assertFalse("Vertex Set "+current+" is not a valid node for a nice decomposition" + + "\nin decomposition "+decomposition + + "\nwith map "+map, true); //no valid node! } assertTrue(true); } - private void isDecomposition(Graph oldGraph, Graph decomposition, Map> map){ + private void testDecomposition(Graph oldGraph, Graph decomposition, Map> map){ Set edgeSet = oldGraph.edgeSet(); Set vertexSet = decomposition.vertexSet(); //Every edge is represented @@ -72,7 +79,9 @@ private void isDecomposition(Graph oldGraph, Graph decomposi continue; } } - if(!hasVertex) assertFalse("Edge "+e+" is not found\n in graph "+decomposition+"\n with map "+map, true); + assertTrue("Edge "+e+" is not found" + + "\nin graph "+decomposition + + "\nwith map "+map, hasVertex); } //every vertex has non-empty connected set of vertex sets Set oldVertexSet = oldGraph.vertexSet(); @@ -92,26 +101,69 @@ private void isDecomposition(Graph oldGraph, Graph decomposi } } + /** + * Interval Graph representation of the graph to test: + * _ ___________ ___________ + * ____________ ___________ + * _____________ ___________ + * ... + */ @Test public void testIntervalgraphDecompositionForRegularGraphs() { + //graph Graph g = new DefaultUndirectedGraph<>(DefaultEdge.class); - //TODO: change g - //IntervalgraphDecomposition> decompositionAlg = new IntervalgraphDecomposition<>(g); - //Graph,DefaultEdge> decomp = decompositionAlg.getTreeDecomposition(); - //TODO: test here - assertTrue(false); + g.addVertex(-1); + for(int i = 0; i<10; i++) + g.addVertex(i); + + for(int i = 0; i<10; i++) { + for(int j = i+1; j<10; j++) { + if((i%2)==0 && (j%2)==0) + g.addEdge(i, j); + + if((i%2)==1 && (j%2)==0 && i decomp = IntervalgraphDecomposition.create(g); + assertNotNull("graph was detected as not an interval graph", decomp); + + //test for nice decomposition + testNiceDecomposition(decomp.getDecomposition(), decomp.getMap(), decomp.getRoot()); + testDecomposition(g, decomp.getDecomposition(), decomp.getMap()); } @Test public void testIntervalgraphDecompositionForIntervalGraphs() { - //IntervalGraphInterface ig = new CenteredIntervalTree<>(); - //TODO: change ig - //IntervalgraphDecomposition decompositionAlg = new IntervalgraphDecomposition<>(ig); - assertTrue(false); + //TODO + } + + @Test + public void testIntervalgraphDecompositionForSortedIntervalLists() + { + //TODO } + /** + * Test for the create method of lists of intervals + * Representation: + * + * __ __ __ + * __ + * __ + * ... + * __ + * ___ + * ____ + * ... + */ @Test public void testIntervalgraphDecompositionForIntervalLists() { @@ -129,12 +181,11 @@ public void testIntervalgraphDecompositionForIntervalLists() { list.add(new Interval(10,10+i)); } - IntervalgraphDecomposition decompalg = new IntervalgraphDecomposition<>(list); - Graph decomp = decompalg.getTreeDecomposition(); + IntervalgraphDecomposition> decompalg = IntervalgraphDecomposition.create(list); + Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); Set roots = decompalg.getRoot(); - for(Integer root : roots) - isNiceDecomposition(decomp,map,root); + testNiceDecomposition(decomp,map,roots); } From 74b247a60ffe76124f04d97ab08c7379282f795f Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Mon, 14 May 2018 20:50:08 +0200 Subject: [PATCH 103/131] added doc --- .../intervalgraph/IntervalGraphRecognizer.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 372bbfe9bc4..edf570781bb 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -250,7 +250,13 @@ public ArrayList> getIntervalsSortedByStartingPoint() return this.intervalsSortedByStartingPoint; } - private static ArrayList> radixSortInteger(List> list){ + /** + * Implementation of radix Sort for integers on Intervals after the ending point + * + * @param list list of intervals to sort + * @return a new sorted list of the intervals sorted after the ending point + */ + private ArrayList> radixSortInteger(List> list){ ArrayList> positiveList = new ArrayList>(list.size()); ArrayList> negativeList = new ArrayList>(list.size()); for(Interval interval : list) { @@ -269,7 +275,13 @@ private static ArrayList> radixSortInteger(List> radixSortNatural(List> list) + /** + * Implementation of radix Sort for natural numbers on Intervals after the ending point + * + * @param list list of intervals to sort + * @return a new sorted list of the intervals sorted after the ending point + */ + private ArrayList> radixSortNatural(List> list) { ArrayList> intervals = new ArrayList>(list); ArrayList> intervalsTmp = new ArrayList>(intervals.size()); From ca56ef095f6814691198f4bfe290f3ab5f8bd67b Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Mon, 14 May 2018 20:53:18 +0200 Subject: [PATCH 104/131] oops - removed debug output --- .../org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index edf570781bb..684e48c0279 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -301,7 +301,6 @@ private ArrayList> radixSortNatural(List> li for(int i = 0; i < intervals.size(); i++) { int digit = Math.abs( (intervals.get(i).getEnd() / power ) % 10); - System.out.println(digit); buckets[digit]++; } @@ -317,7 +316,6 @@ private ArrayList> radixSortNatural(List> li int digit = Math.abs( ( intervals.get(i).getEnd() / power ) % 10 ); int position = buckets[digit]-1; buckets[digit] = position; - System.out.println(position +":"+ i+":"+intervals.size()+":"+intervalsTmp.size()); intervalsTmp.set(position,intervals.get(i)); } From dca3484ca99688b258d1229e8e85a335d47d5dcd Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Mon, 14 May 2018 21:10:20 +0200 Subject: [PATCH 105/131] changed according to check style --- .../IntervalGraphRecognizer.java | 214 ++++++------ .../IntervalgraphDecomposition.java | 324 ++++++++++-------- .../alg/treedecomposition/package-info.java | 6 + .../intervalgraph/interval/Interval.java | 140 +++++--- 4 files changed, 385 insertions(+), 299 deletions(-) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 684e48c0279..4aaf74ede75 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -15,9 +15,9 @@ * vertex for each interval and two vertices are connected if the corresponding intervals have a * nonempty intersection. * - * The recognizer uses the algorithm described in - * https://webdocs.cs.ualberta.ca/~stewart/Pubs/IntervalSIAM.pdf (The LBFS Structure - * and Recognition of Interval Graphs. SIAM J. Discrete Math.. 23. 1905-1953. + * The recognizer uses the algorithm described in https://webdocs.cs.ualberta.ca/~stewart/Pubs/IntervalSIAM.pdf + * (The LBFS Structure and Recognition of Interval Graphs. SIAM J. Discrete Math.. 23. 1905-1953. * 10.1137/S0895480100373455.) by Derek Corneil, Stephan Olariu and Lorna Stewart based on * multiple lexicographical breadth-first search (LBFS) sweeps. * @@ -41,7 +41,8 @@ public final class IntervalGraphRecognizer * Stores the computed interval graph representation (or null if no such representation * exists) of the graph. */ - private ArrayList> intervalsSortedByStartingPoint, intervalsSortedByEndingPoint; + private ArrayList> intervalsSortedByStartingPoint, + intervalsSortedByEndingPoint; private Map, V> intervalToVertexMap; private Map> vertexToIntervalMap; @@ -50,7 +51,7 @@ public final class IntervalGraphRecognizer * * @param graph the graph to be tested. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({ "unchecked" }) public IntervalGraphRecognizer(Graph graph) { this.isIntervalGraph = isIntervalGraph(graph); @@ -102,8 +103,7 @@ private boolean isIntervalGraph(Graph graph) // Step 6 - LBFS* with the resulting sweeps // Input - the result of sweep gamma and sweep epsilon // Output - the result of current sweep zeta - HashMap sweepZeta = - lexBreadthFirstSearchStar(graph, sweepDelta, sweepEpsilon); + HashMap sweepZeta = lexBreadthFirstSearchStar(graph, sweepDelta, sweepEpsilon); // if sweepZeta is umbrella-free, then the graph is interval. // otherwise, the graph is not interval @@ -124,15 +124,19 @@ private boolean isIntervalGraph(Graph graph) neighborIndex.put(vertex, maxNeighbor); } - Interval[] intervals = (Interval[])Array.newInstance(Interval.class, graph.vertexSet().size()); - this.intervalsSortedByStartingPoint = - new ArrayList<>(graph.vertexSet().size()); + Interval[] intervals = + (Interval[]) Array.newInstance(Interval.class, graph.vertexSet().size()); + this.intervalsSortedByStartingPoint = new ArrayList<>(graph.vertexSet().size()); - // Initialize the vertex map. Because we know the number of vertices we can make sure the hashmap does not - // need to rehash by setting the capacity to the number of vertices divided by the default load factor + // Initialize the vertex map. Because we know the number of vertices we can make sure + // the hashmap does not + // need to rehash by setting the capacity to the number of vertices divided by the + // default load factor // of 0.75. - this.intervalToVertexMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); - this.vertexToIntervalMap = new HashMap<>((int)Math.ceil(graph.vertexSet().size() / 0.75)); + this.intervalToVertexMap = + new HashMap<>((int) Math.ceil(graph.vertexSet().size() / 0.75)); + this.vertexToIntervalMap = + new HashMap<>((int) Math.ceil(graph.vertexSet().size() / 0.75)); // Compute intervals and store them associated by their starting point ... for (V vertex : graph.vertexSet()) { @@ -156,7 +160,7 @@ private boolean isIntervalGraph(Graph graph) return false; } } - + /** * Calculates if the given sweep is an I-Ordering (according to the Graph graph) in linear time. * @@ -166,11 +170,11 @@ private boolean isIntervalGraph(Graph graph) * @param graph the graph we want to check if its an I-Order * @return true, if sweep is an I-Order according to graph */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({ "unchecked" }) private static boolean isIOrdering(HashMap sweep, Graph graph) { // Compute inverse sweep map to quickly find vertices at given indices - V[] inverseSweep = (V[])new Object[graph.vertexSet().size()]; + V[] inverseSweep = (V[]) new Object[graph.vertexSet().size()]; for (V vertex : graph.vertexSet()) { int index = sweep.get(vertex); @@ -179,12 +183,12 @@ private static boolean isIOrdering(HashMap sweep, Graph // Compute maximal neighbors w.r.t. sweep ordering for every vertex HashMap maxNeighbors = new HashMap<>(graph.vertexSet().size()); - for(V vertex : graph.vertexSet()) { + for (V vertex : graph.vertexSet()) { List neighbors = Graphs.neighborListOf(graph, vertex); V maxNeighbor = vertex; - for(V neighbor : neighbors) { - if(sweep.get(neighbor) > sweep.get(maxNeighbor)) { + for (V neighbor : neighbors) { + if (sweep.get(neighbor) > sweep.get(maxNeighbor)) { maxNeighbor = neighbor; } } @@ -192,13 +196,14 @@ private static boolean isIOrdering(HashMap sweep, Graph maxNeighbors.put(vertex, maxNeighbor); } - // Check if every vertex is connected to all vertices between itself and its maximal neighbor - for(V vertex : graph.vertexSet()) { + // Check if every vertex is connected to all vertices between itself and its maximal + // neighbor + for (V vertex : graph.vertexSet()) { int index = sweep.get(vertex); int maxIndex = sweep.get(maxNeighbors.get(vertex)); - for(int i = index; i < maxIndex; i++) { - if(vertex != inverseSweep[i] && !graph.containsEdge(vertex, inverseSweep[i])) { + for (int i = index; i < maxIndex; i++) { + if (vertex != inverseSweep[i] && !graph.containsEdge(vertex, inverseSweep[i])) { // Found missing edge return false; } @@ -241,40 +246,46 @@ public boolean isIntervalGraph() } /** - * Returns the list of all intervals sorted by starting point, or null, if the graph was not an interval graph. + * Returns the list of all intervals sorted by starting point, or null, if the graph was not an + * interval graph. * - * @return The list of all intervals sorted by starting point, or null, if the graph was not an interval graph. + * @return The list of all intervals sorted by starting point, or null, if the graph was not an + * interval graph. */ public ArrayList> getIntervalsSortedByStartingPoint() { return this.intervalsSortedByStartingPoint; } - + /** * Implementation of radix Sort for integers on Intervals after the ending point * * @param list list of intervals to sort * @return a new sorted list of the intervals sorted after the ending point */ - private ArrayList> radixSortInteger(List> list){ - ArrayList> positiveList = new ArrayList>(list.size()); - ArrayList> negativeList = new ArrayList>(list.size()); - for(Interval interval : list) { - if(interval.getEnd() < 0) negativeList.add(interval); - else positiveList.add(interval); - } - - positiveList = radixSortNatural(positiveList); - negativeList = radixSortNatural(negativeList); - ArrayList> negativeListReverse = new ArrayList>(negativeList.size()); - - for(int i = 0; i < negativeList.size(); i++) { - negativeListReverse.add(negativeList.get(i)); - } - negativeListReverse.addAll(positiveList); - return negativeListReverse; + private ArrayList> radixSortInteger(List> list) + { + ArrayList> positiveList = new ArrayList>(list.size()); + ArrayList> negativeList = new ArrayList>(list.size()); + for (Interval interval : list) { + if (interval.getEnd() < 0) + negativeList.add(interval); + else + positiveList.add(interval); + } + + positiveList = radixSortNatural(positiveList); + negativeList = radixSortNatural(negativeList); + ArrayList> negativeListReverse = + new ArrayList>(negativeList.size()); + + for (int i = 0; i < negativeList.size(); i++) { + negativeListReverse.add(negativeList.get(i)); + } + negativeListReverse.addAll(positiveList); + return negativeListReverse; } - + /** * Implementation of radix Sort for natural numbers on Intervals after the ending point * @@ -283,68 +294,71 @@ private ArrayList> radixSortInteger(List> li */ private ArrayList> radixSortNatural(List> list) { - ArrayList> intervals = new ArrayList>(list); - ArrayList> intervalsTmp = new ArrayList>(intervals.size()); - - //init - for(int i = 0; i max = Collections.max(intervals,Interval.getEndingComparator()); - Integer power = 1; - //every digit - while(max.getEnd()/(power) > 0) - { - int[] buckets = new int[10]; - - //count all numbers with digit at position exponent - for(int i = 0; i < intervals.size(); i++) - { - int digit = Math.abs( (intervals.get(i).getEnd() / power ) % 10); - buckets[digit]++; - } - - //compute position of digits - for(int i = 1; i < 10; i++) - { - buckets[i] += buckets[i-1]; - } - - //sort after digit in intervalsTmp - for(int i = intervals.size()-1; i >= 0; i--) - { - int digit = Math.abs( ( intervals.get(i).getEnd() / power ) % 10 ); - int position = buckets[digit]-1; - buckets[digit] = position; - intervalsTmp.set(position,intervals.get(i)); - } - - //swap both - ArrayList> tmp = intervals; - intervals = intervalsTmp; - intervalsTmp = tmp; - - power*=10; - } - return intervals; + ArrayList> intervals = new ArrayList>(list); + ArrayList> intervalsTmp = + new ArrayList>(intervals.size()); + + // init + for (int i = 0; i < intervals.size(); i++) + intervalsTmp.add(null); + + Interval max = + Collections.max(intervals, Interval. getEndingComparator()); + Integer power = 1; + // every digit + while (max.getEnd() / (power) > 0) { + int[] buckets = new int[10]; + + // count all numbers with digit at position exponent + for (int i = 0; i < intervals.size(); i++) { + int digit = Math.abs((intervals.get(i).getEnd() / power) % 10); + buckets[digit]++; + } + + // compute position of digits + for (int i = 1; i < 10; i++) { + buckets[i] += buckets[i - 1]; + } + + // sort after digit in intervalsTmp + for (int i = intervals.size() - 1; i >= 0; i--) { + int digit = Math.abs((intervals.get(i).getEnd() / power) % 10); + int position = buckets[digit] - 1; + buckets[digit] = position; + intervalsTmp.set(position, intervals.get(i)); + } + + // swap both + ArrayList> tmp = intervals; + intervals = intervalsTmp; + intervalsTmp = tmp; + + power *= 10; + } + return intervals; } - + /** - * Returns the list of all intervals sorted by ending point, or null, if the graph was not an interval graph. + * Returns the list of all intervals sorted by ending point, or null, if the graph was not an + * interval graph. * - * @return The list of all intervals sorted by ending point, or null, if the graph was not an interval graph. + * @return The list of all intervals sorted by ending point, or null, if the graph was not an + * interval graph. */ public ArrayList> getIntervalsSortedByEndingPoint() { - if(this.intervalsSortedByEndingPoint == null) - this.intervalsSortedByEndingPoint = radixSortInteger(this.intervalsSortedByStartingPoint); - return this.intervalsSortedByEndingPoint; + if (this.intervalsSortedByEndingPoint == null) + this.intervalsSortedByEndingPoint = + radixSortInteger(this.intervalsSortedByStartingPoint); + return this.intervalsSortedByEndingPoint; } /** - * Returns a mapping of the constructed intervals to the vertices of the original graph, or null, if the graph was not an interval graph. + * Returns a mapping of the constructed intervals to the vertices of the original graph, or + * null, if the graph was not an interval graph. * - * @return A mapping of the constructed intervals to the vertices of the original graph, or null, if the graph was not an interval graph. + * @return A mapping of the constructed intervals to the vertices of the original graph, or + * null, if the graph was not an interval graph. */ public Map, V> getIntervalToVertexMap() { @@ -352,9 +366,11 @@ public Map, V> getIntervalToVertexMap() } /** - * Returns a mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. + * Returns a mapping of the vertices of the original graph to the constructed intervals, or + * null, if the graph was not an interval graph. * - * @return A mapping of the vertices of the original graph to the constructed intervals, or null, if the graph was not an interval graph. + * @return A mapping of the vertices of the original graph to the constructed intervals, or + * null, if the graph was not an interval graph. */ public Map> getVertexToIntervalMap() { diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index f0e020a9598..33095f48a2c 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -12,31 +12,32 @@ /** * Class for calculating the nice Tree Decomposition for interval graphs * - * @param the value of the intervals of the interval graph + * @param the value type of the intervals of the interval graph + * @param the type of the nodes of the input graph * * @author Ira Justus Fesefeldt (PhoenixIra) * @since Mai 14, 2018 */ -public class IntervalgraphDecomposition,V> +public class IntervalgraphDecomposition, V> { - //resulting forest of the decomposition + // resulting forest of the decomposition private Graph decomposition = null; - - //map from decomposition nodes to the interval sets + + // map from decomposition nodes to the interval sets private Map> decompositionIntervalMap = null; - - //the roots of the forest + + // the roots of the forest private Set roots = null; - - //input to the algorithm, list of sorted intervals + + // input to the algorithm, list of sorted intervals private List> startSort, endSort; - private Map,V> intervalToVertexMap; - private Map> vertexToIntervalMap; - - //helper attributes + private Map, V> intervalToVertexMap; + private Map> vertexToIntervalMap; + + // helper attributes private Integer currentVertex = null; private Set currentSet = null; - + /** * Private constructor for the factory methods, which changes the inputs * @@ -44,210 +45,222 @@ public class IntervalgraphDecomposition,V> * @param sortedByEndPoint the intervals sorted after the ending points * @param intervalToVertexMap maps intervals to the vertices of the graph (may be the same) */ - private IntervalgraphDecomposition(List> sortedByStartPoint, - List> sortedByEndPoint, - Map,V> intervalToVertexMap, - Map> vertexToIntervalMap) + private IntervalgraphDecomposition( + List> sortedByStartPoint, List> sortedByEndPoint, + Map, V> intervalToVertexMap, Map> vertexToIntervalMap) { - this.startSort = sortedByStartPoint; - this.endSort = sortedByEndPoint; - this.intervalToVertexMap = intervalToVertexMap; - this.vertexToIntervalMap = vertexToIntervalMap; + this.startSort = sortedByStartPoint; + this.endSort = sortedByEndPoint; + this.intervalToVertexMap = intervalToVertexMap; + this.vertexToIntervalMap = vertexToIntervalMap; } - + /** - * Factory method for creating a nice tree decomposition for interval graphs. - * This factory method uses general graphs and the IntervalGraphRecognizer to generate a list of intervals - * sorted by starting and ending points. - * The complexity of this method depends on the sorting algorithm in IntervalGraphRecognizer (probably quasi linear in the number of intervals) + * Factory method for creating a nice tree decomposition for interval graphs. This factory + * method uses general graphs and the IntervalGraphRecognizer to generate a list of intervals + * sorted by starting and ending points. The complexity of this method depends on the sorting + * algorithm in IntervalGraphRecognizer (probably quasi linear in the number of intervals) * - * @param graph the graph which should transformed to an interval graph and then into a corresponding nice tree decomposition - * @return the algorithm for the computation of the nice tree decomposition, returns null if graph was no interval graph + * @param graph the graph which should transformed to an interval graph and then into a + * corresponding nice tree decomposition + * @param the vertex type of the graph + * @param the edge type of the graph + * @return the algorithm for the computation of the nice tree decomposition, returns null if + * graph was no interval graph * @see IntervalGraphRecognizer */ - public static IntervalgraphDecomposition create(Graph graph){ - IntervalGraphRecognizer recog = new IntervalGraphRecognizer<>(graph); - HashMap> vertexToIntegerMap = new HashMap<>(recog.getVertexToIntervalMap().size()); - for(Entry> entry : recog.getVertexToIntervalMap().entrySet()) - vertexToIntegerMap.put(entry.getKey(), entry.getValue().getInterval()); - if(recog.isIntervalGraph()) - return new IntervalgraphDecomposition - (recog.getIntervalsSortedByStartingPoint(), - recog.getIntervalsSortedByStartingPoint(), - recog.getIntervalToVertexMap(), - vertexToIntegerMap); - else - return null; + public static IntervalgraphDecomposition create(Graph graph) + { + IntervalGraphRecognizer recog = new IntervalGraphRecognizer<>(graph); + HashMap> vertexToIntegerMap = + new HashMap<>(recog.getVertexToIntervalMap().size()); + for (Entry> entry : recog + .getVertexToIntervalMap().entrySet()) + vertexToIntegerMap.put(entry.getKey(), entry.getValue().getInterval()); + if (recog.isIntervalGraph()) + return new IntervalgraphDecomposition( + recog.getIntervalsSortedByStartingPoint(), + recog.getIntervalsSortedByStartingPoint(), recog.getIntervalToVertexMap(), + vertexToIntegerMap); + else + return null; } - + /** - * Factory method for creating a nice tree decomposition for interval graphs. - * This factory method extracts the intervals from the interval graph and uses them as an input for the computation. - * The complexity of this method depends on the sorting algorithm of ArrayList (probably O(|V| log(|V|)) + * Factory method for creating a nice tree decomposition for interval graphs. This factory + * method extracts the intervals from the interval graph and uses them as an input for the + * computation. The complexity of this method depends on the sorting algorithm of ArrayList + * (probably O(|V| log(|V|)) * * @param intervalGraph the input for which a nice tree decomposition should be computed + * @param the IntervalVertex Type of the interval graph + * @param the edge type of the interval graph + * @param the vertex type of the graph + * @param the value of the intervals * @return the algorithm for the computation of the nice tree decomposition * @see ArrayList#sort(Comparator) */ - public static , E, VertexType, T extends Comparable> - IntervalgraphDecomposition create(IntervalGraph intervalGraph) + public static , E, VertexType, + T extends Comparable> IntervalgraphDecomposition create( + IntervalGraph intervalGraph) { Set vertexSet = intervalGraph.vertexSet(); List> intervals = new ArrayList>(vertexSet.size()); - Map,V> intervalToVertexMap = new HashMap<>(vertexSet.size()); - Map> vertexToIntervalMap = new HashMap<>(vertexSet.size()); - for(V iv : vertexSet) { - intervals.add(iv.getInterval()); - intervalToVertexMap.put(iv.getInterval(), iv); - vertexToIntervalMap.put(iv, iv.getInterval()); + Map, V> intervalToVertexMap = new HashMap<>(vertexSet.size()); + Map> vertexToIntervalMap = new HashMap<>(vertexSet.size()); + for (V iv : vertexSet) { + intervals.add(iv.getInterval()); + intervalToVertexMap.put(iv.getInterval(), iv); + vertexToIntervalMap.put(iv, iv.getInterval()); } ArrayList> startSort = new ArrayList<>(intervals); ArrayList> endSort = new ArrayList<>(intervals); - startSort.sort(Interval.getStartingComparator()); - endSort.sort(Interval.getEndingComparator()); - return new IntervalgraphDecomposition(startSort, endSort,intervalToVertexMap, vertexToIntervalMap); + startSort.sort(Interval. getStartingComparator()); + endSort.sort(Interval. getEndingComparator()); + return new IntervalgraphDecomposition( + startSort, endSort, intervalToVertexMap, vertexToIntervalMap); } - + /** - * Factory method for creating a nice tree decomposition for interval graphs. - * This factory method needs to lists of intervals, the first sorted after starting points, the second after ending points - * The complexity of this method is linear in the number of intervals + * Factory method for creating a nice tree decomposition for interval graphs. This factory + * method needs to lists of intervals, the first sorted after starting points, the second after + * ending points The complexity of this method is linear in the number of intervals * * @param sortedByStartPoint a list of all intervals sorted by the starting point * @param sortedByEndPoint a list of all intervals sorted by the ending point + * @param the value of the intervals * @return the algorithm for the computation of the nice tree decomposition */ - public static > IntervalgraphDecomposition> create(List> sortedByStartPoint, - List> sortedByEndPoint) + public static > IntervalgraphDecomposition> create( + List> sortedByStartPoint, List> sortedByEndPoint) { - HashMap,Interval> identity = new HashMap<>(sortedByStartPoint.size()); - for(Interval interval : sortedByStartPoint) + HashMap, Interval> identity = new HashMap<>(sortedByStartPoint.size()); + for (Interval interval : sortedByStartPoint) identity.put(interval, interval); - return new IntervalgraphDecomposition>(new ArrayList>(sortedByStartPoint), - new ArrayList>(sortedByEndPoint), - identity, identity); + return new IntervalgraphDecomposition>( + new ArrayList>(sortedByStartPoint), + new ArrayList>(sortedByEndPoint), identity, identity); } - + /** - * Factory method for creating a nice tree decomposition for interval graphs. - * This factory method needs to lists of intervals, which then is sorted by ArrayList.sort(). - * The complexity of this method depends on the sorting Algorithm of ArrayList (probably O(|List| log(|List|)) + * Factory method for creating a nice tree decomposition for interval graphs. This factory + * method needs to lists of intervals, which then is sorted by ArrayList.sort(). The complexity + * of this method depends on the sorting Algorithm of ArrayList (probably O(|List| log(|List|)) * * @param intervals the (unsorted) list of all intervals + * @param the values of the intervals * @return the algorithm for the computation of the nice tree decomposition * @see ArrayList#sort(Comparator) */ - public static > IntervalgraphDecomposition> create(List> intervals) + public static > IntervalgraphDecomposition> create( + List> intervals) { ArrayList> startSort = new ArrayList<>(intervals); ArrayList> endSort = new ArrayList<>(intervals); - startSort.sort(Interval.getStartingComparator()); - endSort.sort(Interval.getEndingComparator()); - HashMap,Interval> identity = new HashMap<>(startSort.size()); - for(Interval interval : startSort) + startSort.sort(Interval. getStartingComparator()); + endSort.sort(Interval. getEndingComparator()); + HashMap, Interval> identity = new HashMap<>(startSort.size()); + for (Interval interval : startSort) identity.put(interval, interval); - return new IntervalgraphDecomposition>(startSort, endSort,identity,identity); + return new IntervalgraphDecomposition>( + startSort, endSort, identity, identity); } - + /** * Main method for computing the nice tree decomposition */ - private void computeNiceDecomposition() + private void computeNiceDecomposition() { - //already computed - if(decomposition != null) + // already computed + if (decomposition != null) return; - - //create all objects and set new root + + // create all objects and set new root initDecomposition(); - - int endIndex=0; + + int endIndex = 0; Interval last = null; - - //as long as intervals remain - for(Interval current : startSort) - { - //first forget until you need to introduce new nodes - while(endSort.get(endIndex).getEnd().compareTo( - current.getStart()) < 0) - { + + // as long as intervals remain + for (Interval current : startSort) { + // first forget until you need to introduce new nodes + while (endSort.get(endIndex).getEnd().compareTo(current.getStart()) < 0) { addForget(endSort.get(endIndex)); endIndex++; } - // root or leaf node AND last one had no successor (i.e. end of last is before start of current) - if(currentSet.size() != 0 || last == null) - { - //no root node, so introduce - addIntroduce(current); - } - else if(last.getEnd().compareTo( - current.getStart()) < 0) - { - //root node! - addNewRoot(); - addIntroduce(current); + // root or leaf node AND last one had no successor (i.e. end of last is before start of + // current) + if (currentSet.size() != 0 || last == null) { + // no root node, so introduce + addIntroduce(current); + } else if (last.getEnd().compareTo(current.getStart()) < 0) { + // root node! + addNewRoot(); + addIntroduce(current); } - //save last node for root detection + // save last node for root detection last = current; } - //add the last forget nodes - while(endIndex < endSort.size()-1) { + // add the last forget nodes + while (endIndex < endSort.size() - 1) { addForget(endSort.get(endIndex++)); } } - + /** * Method for initializing the decomposition */ - private void initDecomposition() + private void initDecomposition() { - //creating objects - decomposition = new DefaultDirectedGraph(DefaultEdge.class); - decompositionIntervalMap = new HashMap>(); + // creating objects + decomposition = new DefaultDirectedGraph(DefaultEdge.class); + decompositionIntervalMap = new HashMap>(); roots = new HashSet(); - - //create root + + // create root currentVertex = 0; roots.add(currentVertex); currentSet = new HashSet<>(); - decompositionIntervalMap.put(currentVertex,currentSet); + decompositionIntervalMap.put(currentVertex, currentSet); decomposition.addVertex(currentVertex); } - + /** * Method for adding a new root */ private void addNewRoot() { - Set nextVertex = new HashSet<>(); - currentSet = nextVertex; - decomposition.addVertex(currentVertex+1); - roots.add(currentVertex+1); - decompositionIntervalMap.put(currentVertex+1, nextVertex); - - //new integer for next vertex - currentVertex++; + Set nextVertex = new HashSet<>(); + currentSet = nextVertex; + decomposition.addVertex(currentVertex + 1); + roots.add(currentVertex + 1); + decompositionIntervalMap.put(currentVertex + 1, nextVertex); + + // new integer for next vertex + currentVertex++; } - + /** * Method for adding introducing nodes + * * @param vertex the vertex, which is introduced */ - private void addIntroduce(Interval interval) + private void addIntroduce(Interval interval) { Set nextVertex = new HashSet<>(currentSet); nextVertex.add(intervalToVertexMap.get(interval)); currentSet = nextVertex; - decomposition.addVertex(currentVertex+1); - decomposition.addEdge(currentVertex, currentVertex+1); - decompositionIntervalMap.put(currentVertex+1, nextVertex); - - //new integer for next vertex + decomposition.addVertex(currentVertex + 1); + decomposition.addEdge(currentVertex, currentVertex + 1); + decompositionIntervalMap.put(currentVertex + 1, nextVertex); + + // new integer for next vertex currentVertex++; } - + /** * method for adding forget nodes + * * @param vertex the vertex, which is introduced */ private void addForget(Interval interval) @@ -255,11 +268,11 @@ private void addForget(Interval interval) Set nextVertex = new HashSet<>(currentSet); nextVertex.remove(intervalToVertexMap.get(interval)); currentSet = nextVertex; - decomposition.addVertex(currentVertex+1); - decomposition.addEdge(currentVertex, currentVertex+1); - decompositionIntervalMap.put(currentVertex+1, nextVertex); - - //new integer for next vertex + decomposition.addVertex(currentVertex + 1); + decomposition.addEdge(currentVertex, currentVertex + 1); + decompositionIntervalMap.put(currentVertex + 1, nextVertex); + + // new integer for next vertex currentVertex++; } @@ -268,22 +281,26 @@ private void addForget(Interval interval) * * @return the computed decomposition */ - public Graph getDecomposition() + public Graph getDecomposition() { - if(decomposition == null) computeNiceDecomposition(); + if (decomposition == null) + computeNiceDecomposition(); return decomposition; } - + /** - * getter for the map from integer nodes of the decomposition to the intervals of the interval graph + * getter for the map from integer nodes of the decomposition to the intervals of the interval + * graph * * @return a nodes to interval map */ - public Map> getMap(){ - if(decompositionIntervalMap == null) computeNiceDecomposition(); - return decompositionIntervalMap; + public Map> getMap() + { + if (decompositionIntervalMap == null) + computeNiceDecomposition(); + return decompositionIntervalMap; } - + /** * getter for all roots of the decomposition * @@ -291,25 +308,28 @@ public Map> getMap(){ */ public Set getRoot() { - if(roots == null) computeNiceDecomposition(); + if (roots == null) + computeNiceDecomposition(); return roots; } - + /** * getter for interval to vertex Map * * @return a map that maps intervals to vertices */ - public Map,V> getIntervalToVertexMap(){ + public Map, V> getIntervalToVertexMap() + { return intervalToVertexMap; } - + /** * getter for vertex to interval map * * @return a map that maps vertices to intervals */ - public Map> getVertexToIntervalMap(){ + public Map> getVertexToIntervalMap() + { return vertexToIntervalMap; } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java new file mode 100644 index 00000000000..efe9ce81a6a --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java @@ -0,0 +1,6 @@ + +/** + * Tree Decomposition related algorithms + * + */ +package org.jgrapht.alg.treedecomposition; diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index 5894cd99f2f..f8d5a9a8e90 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -8,7 +8,10 @@ * * @param the type of the interval */ -public class Interval> implements Comparable> { +public class Interval> + implements + Comparable> +{ protected T start; protected T end; @@ -17,15 +20,18 @@ public class Interval> implements Comparable * Constructs an interval * * @param start interval start - * @param end interval end - * @throws IllegalArgumentException if interval start or end is null, or if interval start is greater than interval end + * @param end interval end + * @throws IllegalArgumentException if interval start or end is null, or if interval start is + * greater than interval end */ - public Interval(T start, T end) { + public Interval(T start, T end) + { if (start == null || end == null) { throw new IllegalArgumentException("Interval start or end cannot be null."); } if (start.compareTo(end) > 0) { - throw new IllegalArgumentException("Interval start must be smaller than or equal to interval end."); + throw new IllegalArgumentException( + "Interval start must be smaller than or equal to interval end."); } this.start = start; @@ -37,7 +43,8 @@ public Interval(T start, T end) { * * @return the start point of the interval */ - public T getStart() { + public T getStart() + { return start; } @@ -46,7 +53,8 @@ public T getStart() { * * @return the end point of the interval */ - public T getEnd() { + public T getEnd() + { return end; } @@ -56,8 +64,10 @@ public T getEnd() { * @param other The other interval * @return true if the other interval intersects this, false otherwise */ - public boolean isIntersecting(Interval other) { - return this.contains(other.getStart()) || this.contains(other.getEnd()) || other.contains(this.getStart()); + public boolean isIntersecting(Interval other) + { + return this.contains(other.getStart()) || this.contains(other.getEnd()) + || other.contains(this.getStart()); } /** @@ -66,7 +76,8 @@ public boolean isIntersecting(Interval other) { * @param point the point to be tested * @return true if current interval contains the given point, false otherwise */ - public boolean contains(T point) { + public boolean contains(T point) + { if (point == null) { throw new IllegalArgumentException("Point to be tested cannot be null."); } @@ -80,9 +91,11 @@ public boolean contains(T point) { * Compare current interval with the given point * * @param point the point to be tested - * @return 0 if current interval contains the given point, comparison result with the interval start otherwise + * @return 0 if current interval contains the given point, comparison result with the interval + * start otherwise */ - public int compareToPoint(T point) { + public int compareToPoint(T point) + { if (point == null) { throw new IllegalArgumentException("Point to be tested cannot be null."); } @@ -101,11 +114,12 @@ public int compareToPoint(T point) { * Compares this interval to the other interval * * @param o The other interval - * @return A value < 0 if the this interval is completely left of the other interval, 0 if the intervals intersect, - * otherwise a value > 0 + * @return A value < 0 if the this interval is completely left of the other interval, 0 if + * the intervals intersect, otherwise a value > 0 */ @Override - public int compareTo(Interval o) { + public int compareTo(Interval o) + { int isLeft = end.compareTo(o.getStart()); // < 0 if this ends before other starts int isRight = start.compareTo(o.getEnd()); // > 0 if this starts before other ends @@ -119,57 +133,87 @@ public int compareTo(Interval o) { } @Override - public String toString() { + public String toString() + { return "Interval[" + start + ", " + end + "]"; } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Interval interval = (Interval) o; - return Objects.equals(start, interval.start) && - Objects.equals(end, interval.end); + return Objects.equals(start, interval.start) && Objects.equals(end, interval.end); } @Override - public int hashCode() { + public int hashCode() + { return Objects.hash(start, end); } - - + /** * getter for a Comparator, which only compares the starting points + * + * @param the value of the interval * @return a starting point comparator */ - public static > StartingComparator getStartingComparator() { - return new StartingComparator(); + public static > StartingComparator getStartingComparator() + { + return new StartingComparator(); } - + /** * getter for a Comparator, which only compares the ending points + * + * @param the value of the interval * @return a ending point comparator */ - public static > EndingComparator getEndingComparator() { - return new EndingComparator(); + public static > EndingComparator getEndingComparator() + { + return new EndingComparator(); + } + + /** + * private class for comparing the starting points of the interval + * + * @author Ira Justus Fesefeldt (PhoenixIra) + * + * @param the value of the interval + */ + private static class StartingComparator> + implements + Comparator> + { + + @Override + public int compare(Interval o1, Interval o2) + { + return o1.getStart().compareTo(o2.getStart()); + } + + } + + /** + * private class for comparing the ending points of the interval + * + * @author Ira Justus Fesefeldt (PhoenixIra) + * + * @param the value of the interval + */ + private static class EndingComparator> + implements + Comparator> + { + + @Override + public int compare(Interval o1, Interval o2) + { + return o1.getEnd().compareTo(o2.getEnd()); + } + } - - private static class StartingComparator> implements Comparator>{ - - @Override - public int compare(Interval o1, Interval o2) { - return o1.getStart().compareTo(o2.getStart()); - } - - } - - private static class EndingComparator> implements Comparator>{ - - @Override - public int compare(Interval o1, Interval o2) { - return o1.getEnd().compareTo(o2.getEnd()); - } - - - } } From 622e086d398312998d0974aa6ef777a4e7feec01 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Tue, 15 May 2018 19:34:18 +0200 Subject: [PATCH 106/131] changed Set of Roots to Join Node Construction of Root --- .../IntervalGraphRecognizer.java | 9 ++--- .../IntervalgraphDecomposition.java | 36 ++++++++++++------- .../IntervalgraphDecompositionTest.java | 17 ++++----- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 4aaf74ede75..f6b4280bb43 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -129,10 +129,8 @@ private boolean isIntervalGraph(Graph graph) this.intervalsSortedByStartingPoint = new ArrayList<>(graph.vertexSet().size()); // Initialize the vertex map. Because we know the number of vertices we can make sure - // the hashmap does not - // need to rehash by setting the capacity to the number of vertices divided by the - // default load factor - // of 0.75. + // the hashmap does not need to rehash by setting the capacity to the number of vertices + // divided by the default load factor of 0.75. this.intervalToVertexMap = new HashMap<>((int) Math.ceil(graph.vertexSet().size() / 0.75)); this.vertexToIntervalMap = @@ -196,8 +194,7 @@ private static boolean isIOrdering(HashMap sweep, Graph maxNeighbors.put(vertex, maxNeighbor); } - // Check if every vertex is connected to all vertices between itself and its maximal - // neighbor + // Check if every vertex is connected to all vertices between itself and its maximal neighbor for (V vertex : graph.vertexSet()) { int index = sweep.get(vertex); int maxIndex = sweep.get(maxNeighbors.get(vertex)); diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java index 33095f48a2c..f57b47187d9 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java @@ -26,8 +26,8 @@ public class IntervalgraphDecomposition, V> // map from decomposition nodes to the interval sets private Map> decompositionIntervalMap = null; - // the roots of the forest - private Set roots = null; + // the root of the tree + private Integer root = null; // input to the algorithm, list of sorted intervals private List> startSort, endSort; @@ -215,28 +215,40 @@ private void initDecomposition() // creating objects decomposition = new DefaultDirectedGraph(DefaultEdge.class); decompositionIntervalMap = new HashMap>(); - roots = new HashSet(); // create root currentVertex = 0; - roots.add(currentVertex); + root = 0; currentSet = new HashSet<>(); decompositionIntervalMap.put(currentVertex, currentSet); decomposition.addVertex(currentVertex); } /** - * Method for adding a new root + * Method for adding a new root as a joint node */ private void addNewRoot() { Set nextVertex = new HashSet<>(); currentSet = nextVertex; + + // new root decomposition.addVertex(currentVertex + 1); - roots.add(currentVertex + 1); decompositionIntervalMap.put(currentVertex + 1, nextVertex); + + // set current Vertex + currentVertex++; + + // new current root + decomposition.addVertex(currentVertex + 1); + decompositionIntervalMap.put(currentVertex + 1, nextVertex); + + // make joint edges + decomposition.addEdge(currentVertex, currentVertex+1); + decomposition.addEdge(currentVertex, root); + root = currentVertex; - // new integer for next vertex + // set current Vertex currentVertex++; } @@ -254,7 +266,7 @@ private void addIntroduce(Interval interval) decomposition.addEdge(currentVertex, currentVertex + 1); decompositionIntervalMap.put(currentVertex + 1, nextVertex); - // new integer for next vertex + // set current Vertex currentVertex++; } @@ -272,7 +284,7 @@ private void addForget(Interval interval) decomposition.addEdge(currentVertex, currentVertex + 1); decompositionIntervalMap.put(currentVertex + 1, nextVertex); - // new integer for next vertex + // set current Vertex currentVertex++; } @@ -306,11 +318,11 @@ public Map> getMap() * * @return a set of roots */ - public Set getRoot() + public Integer getRoot() { - if (roots == null) + if (root == null) computeNiceDecomposition(); - return roots; + return root; } /** diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java index 2a1d1e5a926..f2f9ead00d6 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java @@ -8,24 +8,21 @@ import org.jgrapht.*; import org.jgrapht.alg.treedecomposition.*; import org.jgrapht.graph.*; -import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; import org.junit.*; public class IntervalgraphDecompositionTest { - private void testNiceDecomposition(Graph decomposition, Map> map, Set root){ + private void testNiceDecomposition(Graph decomposition, Map> map, V root){ Queue queue = new LinkedList(); - //test and add all roots - for(V v: root) { - assertTrue(v+" is no valid root" + //test and add root + assertTrue(root+" is no valid root" + "\n in decomposition "+decomposition - + "\n and map"+map, map.get(v).size() == 0); - queue.add(v); - } + + "\n and map"+map, map.get(root).size() == 0); + queue.add(root); while(!queue.isEmpty()) { @@ -184,8 +181,8 @@ public void testIntervalgraphDecompositionForIntervalLists() IntervalgraphDecomposition> decompalg = IntervalgraphDecomposition.create(list); Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); - Set roots = decompalg.getRoot(); - testNiceDecomposition(decomp,map,roots); + Integer root = decompalg.getRoot(); + testNiceDecomposition(decomp,map,root); } From ead492372540c11af75fc5b6877da1db1789a2e8 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Tue, 15 May 2018 19:55:56 +0200 Subject: [PATCH 107/131] negative list did not need to be reversed in radixSortInteger (abs magic) --- .../IntervalGraphRecognizer.java | 10 ++-------- .../interval/IntervalGraphRecognizerTest.java | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index f6b4280bb43..076316b86f1 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -273,14 +273,8 @@ private ArrayList> radixSortInteger(List> li positiveList = radixSortNatural(positiveList); negativeList = radixSortNatural(negativeList); - ArrayList> negativeListReverse = - new ArrayList>(negativeList.size()); - - for (int i = 0; i < negativeList.size(); i++) { - negativeListReverse.add(negativeList.get(i)); - } - negativeListReverse.addAll(positiveList); - return negativeListReverse; + negativeList.addAll(positiveList); + return negativeList; } /** diff --git a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java index 27dee98b15d..dcce418daea 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/intervalgraph/interval/IntervalGraphRecognizerTest.java @@ -13,6 +13,8 @@ import static org.junit.Assert.*; +import java.util.*; + public class IntervalGraphRecognizerTest { /** @@ -176,6 +178,12 @@ public void isCompleteAnIntervalGraph(int n) { //Every complete Graph is an interval graph IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(cg); assertTrue(recognizer.isIntervalGraph()); + + //also test the sorting algorithm for intervals + ArrayList> intervalsStartSort = recognizer.getIntervalsSortedByStartingPoint(); + ArrayList> intervalsEndSort = recognizer.getIntervalsSortedByEndingPoint(); + intervalsStartSort.sort(Interval.getEndingComparator()); + assertEquals(intervalsStartSort, intervalsEndSort); } /* @@ -201,6 +209,12 @@ public void isUnconnectedAnIntervalGraph(int n) { //Every complete Graph is an interval graph IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); assertTrue(recognizer.isIntervalGraph()); + + //also test the sorting algorithm for intervals + ArrayList> intervalsStartSort = recognizer.getIntervalsSortedByStartingPoint(); + ArrayList> intervalsEndSort = recognizer.getIntervalsSortedByEndingPoint(); + intervalsStartSort.sort(Interval.getEndingComparator()); + assertEquals(intervalsStartSort, intervalsEndSort); } /* @@ -226,6 +240,12 @@ public void isLinearAnIntervalGraph(int n) { //Every complete Graph is an interval graph IntervalGraphRecognizer recognizer = new IntervalGraphRecognizer<>(builder.build()); assertTrue(recognizer.isIntervalGraph()); + + //also test the sorting algorithm for intervals + ArrayList> intervalsStartSort = recognizer.getIntervalsSortedByStartingPoint(); + ArrayList> intervalsEndSort = recognizer.getIntervalsSortedByEndingPoint(); + intervalsStartSort.sort(Interval.getEndingComparator()); + assertEquals(intervalsStartSort, intervalsEndSort); } /* From 7e538d77b73e04d473907971da3da40f5f029c30 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Tue, 15 May 2018 20:11:51 +0200 Subject: [PATCH 108/131] having fun with edge cases (list.size = 0) --- .../alg/intervalgraph/IntervalGraphRecognizer.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 076316b86f1..620a528fe24 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -67,6 +67,7 @@ private boolean isIntervalGraph(Graph graph) // An empty graph is an interval graph. if (graph.vertexSet().isEmpty()) { + this.intervalsSortedByStartingPoint = new ArrayList<>(); return true; } @@ -262,6 +263,9 @@ public ArrayList> getIntervalsSortedByStartingPoint() */ private ArrayList> radixSortInteger(List> list) { + if(list.size() == 0) + return new ArrayList>(); + ArrayList> positiveList = new ArrayList>(list.size()); ArrayList> negativeList = new ArrayList>(list.size()); for (Interval interval : list) { @@ -285,6 +289,9 @@ private ArrayList> radixSortInteger(List> li */ private ArrayList> radixSortNatural(List> list) { + if(list.size() == 0) + return new ArrayList>(); + ArrayList> intervals = new ArrayList>(list); ArrayList> intervalsTmp = new ArrayList>(intervals.size()); @@ -332,12 +339,17 @@ private ArrayList> radixSortNatural(List> li /** * Returns the list of all intervals sorted by ending point, or null, if the graph was not an * interval graph. + * The List will be created with radix sort from getIntervalsSortedByStartingPoint as soon as + * this method is called. * * @return The list of all intervals sorted by ending point, or null, if the graph was not an * interval graph. */ public ArrayList> getIntervalsSortedByEndingPoint() { + // + if (this.intervalsSortedByStartingPoint == null) + return null; if (this.intervalsSortedByEndingPoint == null) this.intervalsSortedByEndingPoint = radixSortInteger(this.intervalsSortedByStartingPoint); From 655b9b86c1d0556e7b476f24eb429ca1c433f26f Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 23 May 2018 11:26:33 +0200 Subject: [PATCH 109/131] initial commit, optimization and tests needed --- .../alg/color/DecompositionTreeColour.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java new file mode 100644 index 00000000000..19d3bcffd49 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java @@ -0,0 +1,86 @@ +package org.jgrapht.alg.color; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import org.jgrapht.Graph; +import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; + +public class DecompositionTreeColour implements VertexColoringAlgorithm { + + + private Graph, E> graph; + + /** + * Construct a new coloring algorithm. + * + * @param graph the input graph + */ + public DecompositionTreeColour(Graph, E> graph) + { + this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); + } + protected Iterable> getVertexOrdering() + { + return (Iterable>) graph.vertexSet(); + } + + @Override + public Coloring getColoring() { + + + Map asssignedColors = new HashMap<>(); + Set used = new HashSet<>(); + Set free = new HashSet<>(); + + + + for(List outerVertex:getVertexOrdering() ) { + for(V innerVertex : outerVertex ) { + //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour + if(asssignedColors.containsKey(innerVertex)) { + used.add(asssignedColors.get(innerVertex)); + + } + else { + //these are the vertices without any assigned colours + free.add(innerVertex); + } + } + + //here we assign colours to the free vertices + + for(V freeVertex: free) { + int colourCandidate = 0; + while (used.contains(colourCandidate)) { + colourCandidate++; + } + + asssignedColors.put(freeVertex,colourCandidate); + + used.add(colourCandidate); + + + } + used.clear(); + + } + int maxColourAssigned = Collections.max(asssignedColors.values()); + + + return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); + } +} + + + + + + + + + From f909902ab96ed1157108b9aef9fe2b7a94330c61 Mon Sep 17 00:00:00 2001 From: Justus Fesefeldt Date: Fri, 25 May 2018 12:45:10 +0200 Subject: [PATCH 110/131] changes according to PR and changed structure back to path decomposition --- .../IntervalGraphRecognizer.java | 14 ++-- ...n.java => IntervalGraphDecomposition.java} | 64 +++++++------------ .../intervalgraph/interval/Interval.java | 59 ++++++----------- ...va => IntervalGraphDecompositionTest.java} | 8 +-- 4 files changed, 55 insertions(+), 90 deletions(-) rename jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/{IntervalgraphDecomposition.java => IntervalGraphDecomposition.java} (84%) rename jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/{IntervalgraphDecompositionTest.java => IntervalGraphDecompositionTest.java} (94%) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java index 620a528fe24..add26c3a486 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/intervalgraph/IntervalGraphRecognizer.java @@ -263,7 +263,10 @@ public ArrayList> getIntervalsSortedByStartingPoint() */ private ArrayList> radixSortInteger(List> list) { - if(list.size() == 0) + if(list == null) + throw new IllegalArgumentException("List parameter cannot be null."); + + if(list.isEmpty()) return new ArrayList>(); ArrayList> positiveList = new ArrayList>(list.size()); @@ -289,7 +292,10 @@ private ArrayList> radixSortInteger(List> li */ private ArrayList> radixSortNatural(List> list) { - if(list.size() == 0) + if(list == null) + throw new IllegalArgumentException("List parameter cannot be null."); + + if(list.isEmpty()) return new ArrayList>(); ArrayList> intervals = new ArrayList>(list); @@ -302,9 +308,9 @@ private ArrayList> radixSortNatural(List> li Interval max = Collections.max(intervals, Interval. getEndingComparator()); - Integer power = 1; + int power = 1; // every digit - while (max.getEnd() / (power) > 0) { + while (max.getEnd() / power > 0) { int[] buckets = new int[10]; // count all numbers with digit at position exponent diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphDecomposition.java similarity index 84% rename from jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java rename to jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphDecomposition.java index f57b47187d9..e79e5b922d4 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalgraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphDecomposition.java @@ -1,8 +1,6 @@ package org.jgrapht.alg.treedecomposition; import java.util.*; -import java.util.Map.*; - import org.jgrapht.*; import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; import org.jgrapht.graph.*; @@ -18,7 +16,7 @@ * @author Ira Justus Fesefeldt (PhoenixIra) * @since Mai 14, 2018 */ -public class IntervalgraphDecomposition, V> +public class IntervalGraphDecomposition, V> { // resulting forest of the decomposition private Graph decomposition = null; @@ -45,7 +43,7 @@ public class IntervalgraphDecomposition, V> * @param sortedByEndPoint the intervals sorted after the ending points * @param intervalToVertexMap maps intervals to the vertices of the graph (may be the same) */ - private IntervalgraphDecomposition( + private IntervalGraphDecomposition( List> sortedByStartPoint, List> sortedByEndPoint, Map, V> intervalToVertexMap, Map> vertexToIntervalMap) { @@ -53,6 +51,7 @@ private IntervalgraphDecomposition( this.endSort = sortedByEndPoint; this.intervalToVertexMap = intervalToVertexMap; this.vertexToIntervalMap = vertexToIntervalMap; + computeNiceDecomposition(); } /** @@ -69,18 +68,21 @@ private IntervalgraphDecomposition( * graph was no interval graph * @see IntervalGraphRecognizer */ - public static IntervalgraphDecomposition create(Graph graph) + public static IntervalGraphDecomposition create(Graph graph) { IntervalGraphRecognizer recog = new IntervalGraphRecognizer<>(graph); + HashMap> vertexToIntegerMap = new HashMap<>(recog.getVertexToIntervalMap().size()); - for (Entry> entry : recog - .getVertexToIntervalMap().entrySet()) - vertexToIntegerMap.put(entry.getKey(), entry.getValue().getInterval()); + + Map> vertexToIntervalVertexMap = recog.getVertexToIntervalMap(); + for (V key : vertexToIntervalVertexMap.keySet()) + vertexToIntegerMap.put(key, vertexToIntervalVertexMap.get(key).getInterval()); + if (recog.isIntervalGraph()) - return new IntervalgraphDecomposition( + return new IntervalGraphDecomposition( recog.getIntervalsSortedByStartingPoint(), - recog.getIntervalsSortedByStartingPoint(), recog.getIntervalToVertexMap(), + recog.getIntervalsSortedByEndingPoint(), recog.getIntervalToVertexMap(), vertexToIntegerMap); else return null; @@ -101,7 +103,7 @@ public static IntervalgraphDecomposition create(Graph g * @see ArrayList#sort(Comparator) */ public static , E, VertexType, - T extends Comparable> IntervalgraphDecomposition create( + T extends Comparable> IntervalGraphDecomposition create( IntervalGraph intervalGraph) { Set vertexSet = intervalGraph.vertexSet(); @@ -117,7 +119,7 @@ T extends Comparable> IntervalgraphDecomposition create( ArrayList> endSort = new ArrayList<>(intervals); startSort.sort(Interval. getStartingComparator()); endSort.sort(Interval. getEndingComparator()); - return new IntervalgraphDecomposition( + return new IntervalGraphDecomposition( startSort, endSort, intervalToVertexMap, vertexToIntervalMap); } @@ -131,13 +133,13 @@ T extends Comparable> IntervalgraphDecomposition create( * @param the value of the intervals * @return the algorithm for the computation of the nice tree decomposition */ - public static > IntervalgraphDecomposition> create( + public static > IntervalGraphDecomposition> create( List> sortedByStartPoint, List> sortedByEndPoint) { HashMap, Interval> identity = new HashMap<>(sortedByStartPoint.size()); for (Interval interval : sortedByStartPoint) identity.put(interval, interval); - return new IntervalgraphDecomposition>( + return new IntervalGraphDecomposition>( new ArrayList>(sortedByStartPoint), new ArrayList>(sortedByEndPoint), identity, identity); } @@ -152,18 +154,14 @@ public static > IntervalgraphDecomposition> IntervalgraphDecomposition> create( + public static > IntervalGraphDecomposition> create( List> intervals) { ArrayList> startSort = new ArrayList<>(intervals); ArrayList> endSort = new ArrayList<>(intervals); startSort.sort(Interval. getStartingComparator()); endSort.sort(Interval. getEndingComparator()); - HashMap, Interval> identity = new HashMap<>(startSort.size()); - for (Interval interval : startSort) - identity.put(interval, interval); - return new IntervalgraphDecomposition>( - startSort, endSort, identity, identity); + return create(startSort, endSort); } /** @@ -179,7 +177,6 @@ private void computeNiceDecomposition() initDecomposition(); int endIndex = 0; - Interval last = null; // as long as intervals remain for (Interval current : startSort) { @@ -187,22 +184,11 @@ private void computeNiceDecomposition() while (endSort.get(endIndex).getEnd().compareTo(current.getStart()) < 0) { addForget(endSort.get(endIndex)); endIndex++; - } - // root or leaf node AND last one had no successor (i.e. end of last is before start of - // current) - if (currentSet.size() != 0 || last == null) { - // no root node, so introduce - addIntroduce(current); - } else if (last.getEnd().compareTo(current.getStart()) < 0) { - // root node! - addNewRoot(); - addIntroduce(current); - } - // save last node for root detection - last = current; + } + addIntroduce(current); } // add the last forget nodes - while (endIndex < endSort.size() - 1) { + while (endIndex < endSort.size()) { addForget(endSort.get(endIndex++)); } } @@ -226,7 +212,9 @@ private void initDecomposition() /** * Method for adding a new root as a joint node + * Will be used/changed in future */ + @SuppressWarnings("unused") private void addNewRoot() { Set nextVertex = new HashSet<>(); @@ -295,8 +283,6 @@ private void addForget(Interval interval) */ public Graph getDecomposition() { - if (decomposition == null) - computeNiceDecomposition(); return decomposition; } @@ -308,8 +294,6 @@ public Graph getDecomposition() */ public Map> getMap() { - if (decompositionIntervalMap == null) - computeNiceDecomposition(); return decompositionIntervalMap; } @@ -320,8 +304,6 @@ public Map> getMap() */ public Integer getRoot() { - if (root == null) - computeNiceDecomposition(); return root; } diff --git a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java index f8d5a9a8e90..1e9e39a84c5 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java +++ b/jgrapht-core/src/main/java/org/jgrapht/intervalgraph/interval/Interval.java @@ -161,9 +161,16 @@ public int hashCode() * @param the value of the interval * @return a starting point comparator */ - public static > StartingComparator getStartingComparator() + public static > Comparator> getStartingComparator() { - return new StartingComparator(); + return new Comparator>() + { + @Override + public int compare(Interval o1, Interval o2) + { + return o1.getStart().compareTo(o2.getStart()); + } + }; } /** @@ -172,48 +179,18 @@ public static > StartingComparator getStartingCompara * @param the value of the interval * @return a ending point comparator */ - public static > EndingComparator getEndingComparator() - { - return new EndingComparator(); - } - - /** - * private class for comparing the starting points of the interval - * - * @author Ira Justus Fesefeldt (PhoenixIra) - * - * @param the value of the interval - */ - private static class StartingComparator> - implements - Comparator> + public static > Comparator> getEndingComparator() { - - @Override - public int compare(Interval o1, Interval o2) + return new Comparator>() { - return o1.getStart().compareTo(o2.getStart()); - } - } - - /** - * private class for comparing the ending points of the interval - * - * @author Ira Justus Fesefeldt (PhoenixIra) - * - * @param the value of the interval - */ - private static class EndingComparator> - implements - Comparator> - { - - @Override - public int compare(Interval o1, Interval o2) - { - return o1.getEnd().compareTo(o2.getEnd()); - } + @Override + public int compare(Interval o1, Interval o2) + { + return o1.getEnd().compareTo(o2.getEnd()); + } + }; } + } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java similarity index 94% rename from jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java rename to jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java index f2f9ead00d6..fd36bfed3d9 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalgraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java @@ -11,7 +11,7 @@ import org.jgrapht.intervalgraph.interval.*; import org.junit.*; -public class IntervalgraphDecompositionTest +public class IntervalGraphDecompositionTest { private void testNiceDecomposition(Graph decomposition, Map> map, V root){ @@ -28,7 +28,7 @@ private void testNiceDecomposition(Graph decomposition, Map successor = Graphs.successorListOf(decomposition, current); - if(successor.size() == 0 && map.get(current).size() <= 1) continue; //leaf node + if(successor.size() == 0 && map.get(current).isEmpty()) continue; //leaf node if(successor.size() == 1) //forget or introduce { V next = successor.get(0); @@ -128,7 +128,7 @@ public void testIntervalgraphDecompositionForRegularGraphs() } //compute decomposition - IntervalgraphDecomposition decomp = IntervalgraphDecomposition.create(g); + IntervalGraphDecomposition decomp = IntervalGraphDecomposition.create(g); assertNotNull("graph was detected as not an interval graph", decomp); //test for nice decomposition @@ -178,7 +178,7 @@ public void testIntervalgraphDecompositionForIntervalLists() { list.add(new Interval(10,10+i)); } - IntervalgraphDecomposition> decompalg = IntervalgraphDecomposition.create(list); + IntervalGraphDecomposition> decompalg = IntervalGraphDecomposition.create(list); Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); Integer root = decompalg.getRoot(); From 91155262c884fe42f99cf8393b6bd77a4d76dbd7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 26 May 2018 06:31:00 +0200 Subject: [PATCH 111/131] Added comments, need to optimize and include generalisations --- .../alg/color/DecompositionTreeColour.java | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java index 19d3bcffd49..86d60dd0c2e 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java @@ -10,29 +10,50 @@ import org.jgrapht.Graph; import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; -public class DecompositionTreeColour implements VertexColoringAlgorithm { +/** + * Colouring of decomposition trees (currently done for interval graphs). This algorithm iterates over lists of vertices and assigns + * the smallest colour to each of the vertices such that the no vertex in the same list has the same colour. + * + * @author Suchanda Bhattacharyya + * + * @param The type of graph vertex + * @param The type of graph edge + */ +public class DecompositionTreeColour implements VertexColoringAlgorithm { + /** + * The input graph + */ private Graph, E> graph; + /** - * Construct a new coloring algorithm. - * - * @param graph the input graph + * @param graph */ + public DecompositionTreeColour(Graph, E> graph) { this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); } + + + /** + * Getting the ordering for the vertices + * @return the ordering of the vertices + */ protected Iterable> getVertexOrdering() { return (Iterable>) graph.vertexSet(); } + /* (non-Javadoc) + * @see org.jgrapht.alg.interfaces.VertexColoringAlgorithm#getColoring() + */ @Override public Coloring getColoring() { - + Map asssignedColors = new HashMap<>(); Set used = new HashSet<>(); Set free = new HashSet<>(); @@ -40,15 +61,19 @@ public Coloring getColoring() { for(List outerVertex:getVertexOrdering() ) { - for(V innerVertex : outerVertex ) { + //need to sort the inner vertex here or do something so that sorting is not needed + for(V innerVertex : outerVertex ) { //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour if(asssignedColors.containsKey(innerVertex)) { used.add(asssignedColors.get(innerVertex)); + + } else { //these are the vertices without any assigned colours free.add(innerVertex); + } } @@ -62,16 +87,17 @@ public Coloring getColoring() { asssignedColors.put(freeVertex,colourCandidate); + used.add(colourCandidate); } + free.clear(); used.clear(); } int maxColourAssigned = Collections.max(asssignedColors.values()); - - + return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); } } From d43d68180689f98d59fab89240cf28ae267391b2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 26 May 2018 06:35:34 +0200 Subject: [PATCH 112/131] need to add more tests --- .../color/DecompositionTreeColourTest.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java new file mode 100644 index 00000000000..3550cf2cd83 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java @@ -0,0 +1,66 @@ +package org.jgrapht.alg.color; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.jgrapht.Graph; +import org.jgrapht.Graphs; +import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; +import org.jgrapht.alg.interfaces.VertexColoringAlgorithm.Coloring; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.SimpleGraph; +import org.junit.Test; +/** + * Coloring tests + * + * @author Suchanda Bhattacharyya (dia007) + */ +public class DecompositionTreeColourTest { + + protected VertexColoringAlgorithm getAlgorithm(Graph, DefaultEdge> graph) + { + return new DecompositionTreeColour<>(graph); + } +//need to add more graphs + + final protected Graph, DefaultEdge> createGraph() + { + Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class); + + + List outerVertex1 = new ArrayList<>(); + List outerVertex2 = new ArrayList<>(); + List outerVertex3 = new ArrayList<>(); + List outerVertex4 = new ArrayList<>(); + List outerVertex5 = new ArrayList<>(); + + outerVertex1.add(1); + outerVertex2.add(1); outerVertex2.add(2);outerVertex2.add(3); + outerVertex3.add(2);outerVertex3.add(3); + outerVertex4.add(2); + outerVertex5.add(2);outerVertex5.add(4); + + Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); + Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); + Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); + Graphs.addEdgeWithVertices(graph, outerVertex4, outerVertex5); + return graph; + } + + @Test + public void testGreedy() + { + Graph, DefaultEdge> newGraph = createGraph(); + + Coloring coloring = new DecompositionTreeColour<>(newGraph).getColoring(); + assertEquals(3, coloring.getNumberColors()); + Map colors = coloring.getColors(); + assertEquals(0, colors.get(1).intValue()); + assertEquals(1, colors.get(2).intValue()); + assertEquals(2, colors.get(3).intValue()); + assertEquals(0, colors.get(4).intValue()); + } +} From 347e1c89dd3ca85da0164c5b93b8511d7c9097b4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 27 May 2018 03:58:33 +0200 Subject: [PATCH 113/131] needed to put it in a new package --- .../DecompositionTreeColour.java | 9 +-- .../alg/treedecomposition/package-info.java | 8 +++ .../jgrapht/alg/treedecomposition/test.java | 68 +++++++++++++++++++ .../DecompositionTreeColourTest.java | 2 +- .../alg/treedecomposition/package-info.java | 8 +++ 5 files changed, 86 insertions(+), 9 deletions(-) rename jgrapht-core/src/main/java/org/jgrapht/alg/{color => treedecomposition}/DecompositionTreeColour.java (98%) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java rename jgrapht-core/src/test/java/org/jgrapht/alg/{color => treedecomposition}/DecompositionTreeColourTest.java (97%) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java similarity index 98% rename from jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java rename to jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java index 86d60dd0c2e..d0e75247ecf 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java @@ -1,4 +1,4 @@ -package org.jgrapht.alg.color; +package org.jgrapht.alg.treedecomposition; import java.util.Collections; import java.util.HashMap; @@ -103,10 +103,3 @@ public Coloring getColoring() { } - - - - - - - diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java new file mode 100644 index 00000000000..735395e2f80 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author suchandra + * + */ +package org.jgrapht.alg.treedecomposition; \ No newline at end of file diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java new file mode 100644 index 00000000000..964fc7aa16b --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java @@ -0,0 +1,68 @@ +package org.jgrapht.alg.treedecomposition; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.jgrapht.EdgeFactory; +import org.jgrapht.Graph; +import org.jgrapht.Graphs; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.SimpleGraph; + +public class test { + + + public static void main(String[] args) { + + + + Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class) ; + List outerVertex1 = new ArrayList<>(); + List outerVertex2 = new ArrayList<>(); + List outerVertex3 = new ArrayList<>(); + List outerVertex4 = new ArrayList<>(); + List outerVertex5 = new ArrayList<>(); + List outerVertex6 = new ArrayList<>(); + + outerVertex1.add(1); + outerVertex2.add(1); outerVertex2.add(2);outerVertex2.add(3); + outerVertex3.add(2);outerVertex3.add(3); + outerVertex4.add(2); + outerVertex5.add(2);outerVertex5.add(4); + outerVertex6.add(null); + + Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); + Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); + Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); + Graphs.addEdgeWithVertices(graph, outerVertex4, outerVertex5); + Graphs.addEdgeWithVertices(graph, outerVertex5, outerVertex6); + + + /*List outerVertex1 = new ArrayList<>(); + List outerVertex2 = new ArrayList<>(); + List outerVertex3 = new ArrayList<>(); + List outerVertex4 = new ArrayList<>(); + List outerVertex5 = new ArrayList<>(); + + + outerVertex1.add(null); + outerVertex2.add(1); + outerVertex3.add(null); + outerVertex4.add(2); + outerVertex5.add(null); + Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); + Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); + Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); + Graphs.addEdgeWithVertices(graph, outerVertex4, outerVertex5); + */ + + + DecompositionTreeColour testClass = new DecompositionTreeColour(graph); + // testClass.getVertexOrdering(); //this works ok + testClass.getColoring(); + + } + +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java similarity index 97% rename from jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java rename to jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java index 3550cf2cd83..0621ec51ccf 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java @@ -1,4 +1,4 @@ -package org.jgrapht.alg.color; +package org.jgrapht.alg.treedecomposition; import static org.junit.Assert.assertEquals; diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java new file mode 100644 index 00000000000..735395e2f80 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author suchandra + * + */ +package org.jgrapht.alg.treedecomposition; \ No newline at end of file From 10cbd1a480a48c6ed46a3c57781443975fbe3fa7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 27 May 2018 11:42:07 +0200 Subject: [PATCH 114/131] good enough for now --- .../DecompositionTreeColour.java | 13 +++++ .../alg/treedecomposition/package-info.java | 8 --- .../DecompositionTreeColourTest.java | 49 +++++++++++++++++-- 3 files changed, 58 insertions(+), 12 deletions(-) delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java index d0e75247ecf..345bf5542ac 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java @@ -1,5 +1,6 @@ package org.jgrapht.alg.treedecomposition; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -8,6 +9,7 @@ import java.util.Objects; import java.util.Set; import org.jgrapht.Graph; +import org.jgrapht.Graphs; import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; /** @@ -44,7 +46,9 @@ public DecompositionTreeColour(Graph, E> graph) */ protected Iterable> getVertexOrdering() { + System.out.println((Iterable>) graph.vertexSet()); return (Iterable>) graph.vertexSet(); + } /* (non-Javadoc) @@ -58,9 +62,16 @@ public Coloring getColoring() { Set used = new HashSet<>(); Set free = new HashSet<>(); + //lself loops not allowed, repeatations of inner vertices not allowed for(List outerVertex:getVertexOrdering() ) { + + //the case of a generalised decomposition tree + /* for (E edge: graph.edgesOf(outerVertex)) { + List oppoSiteVertex = Graphs.getOppositeVertex(graph, edge, outerVertex); + }*/ + //need to sort the inner vertex here or do something so that sorting is not needed for(V innerVertex : outerVertex ) { //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour @@ -98,6 +109,8 @@ public Coloring getColoring() { } int maxColourAssigned = Collections.max(asssignedColors.values()); + + System.out.println(Arrays.asList(asssignedColors)); return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); } } diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java deleted file mode 100644 index 735395e2f80..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * - */ -/** - * @author suchandra - * - */ -package org.jgrapht.alg.treedecomposition; \ No newline at end of file diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java index 0621ec51ccf..26aba9578e3 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java @@ -24,9 +24,9 @@ protected VertexColoringAlgorithm getAlgorithm(Graph, Def { return new DecompositionTreeColour<>(graph); } -//need to add more graphs + //need to add more graphs - final protected Graph, DefaultEdge> createGraph() + final protected Graph, DefaultEdge> createGraph1() { Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class); @@ -50,10 +50,36 @@ final protected Graph, DefaultEdge> createGraph() return graph; } + final protected Graph, DefaultEdge> createGraph2() + { + Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class); + + + List outerVertex1 = new ArrayList<>(); + List outerVertex2 = new ArrayList<>(); + List outerVertex3 = new ArrayList<>(); + List outerVertex4 = new ArrayList<>(); + List outerVertex5 = new ArrayList<>(); + + outerVertex1.add(2); outerVertex1.add(1); + outerVertex2.add(3); outerVertex2.add(4);outerVertex2.add(2); + outerVertex3.add(4); + outerVertex4.add(5);outerVertex4.add(4); + + outerVertex5.add(4);outerVertex5.add(6); + Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); + Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); + Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); + Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex5); + + return graph; + } + + @Test - public void testGreedy() + public void testGreedy1() { - Graph, DefaultEdge> newGraph = createGraph(); + Graph, DefaultEdge> newGraph = createGraph1(); Coloring coloring = new DecompositionTreeColour<>(newGraph).getColoring(); assertEquals(3, coloring.getNumberColors()); @@ -63,4 +89,19 @@ public void testGreedy() assertEquals(2, colors.get(3).intValue()); assertEquals(0, colors.get(4).intValue()); } + @Test + public void testGreedy2() + { + Graph, DefaultEdge> newGraph = createGraph2(); + + Coloring coloring = new DecompositionTreeColour<>(newGraph).getColoring(); + assertEquals(3, coloring.getNumberColors()); + Map colors = coloring.getColors(); + assertEquals(0, colors.get(1).intValue()); + assertEquals(1, colors.get(2).intValue()); + assertEquals(0, colors.get(3).intValue()); + assertEquals(2, colors.get(4).intValue()); + assertEquals(0, colors.get(5).intValue()); + assertEquals(0, colors.get(6).intValue()); + } } From 8470e254d91d167fe9a6288037eadc4f07eff25a Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 31 May 2018 20:24:15 +0200 Subject: [PATCH 115/131] refactored structure for chordal graph decomposition --- ...va => IntervalGraphNiceDecomposition.java} | 160 ++-------------- .../NiceDecompositionBuilder.java | 175 ++++++++++++++++++ .../IntervalGraphDecompositionTest.java | 4 +- 3 files changed, 196 insertions(+), 143 deletions(-) rename jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/{IntervalGraphDecomposition.java => IntervalGraphNiceDecomposition.java} (64%) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphNiceDecomposition.java similarity index 64% rename from jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphDecomposition.java rename to jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphNiceDecomposition.java index e79e5b922d4..2f6bd0dab25 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphNiceDecomposition.java @@ -3,7 +3,6 @@ import java.util.*; import org.jgrapht.*; import org.jgrapht.alg.intervalgraph.IntervalGraphRecognizer; -import org.jgrapht.graph.*; import org.jgrapht.intervalgraph.*; import org.jgrapht.intervalgraph.interval.*; @@ -16,17 +15,8 @@ * @author Ira Justus Fesefeldt (PhoenixIra) * @since Mai 14, 2018 */ -public class IntervalGraphDecomposition, V> +public class IntervalGraphNiceDecomposition, V> extends NiceDecompositionBuilder { - // resulting forest of the decomposition - private Graph decomposition = null; - - // map from decomposition nodes to the interval sets - private Map> decompositionIntervalMap = null; - - // the root of the tree - private Integer root = null; - // input to the algorithm, list of sorted intervals private List> startSort, endSort; private Map, V> intervalToVertexMap; @@ -34,7 +24,6 @@ public class IntervalGraphDecomposition, V> // helper attributes private Integer currentVertex = null; - private Set currentSet = null; /** * Private constructor for the factory methods, which changes the inputs @@ -43,14 +32,17 @@ public class IntervalGraphDecomposition, V> * @param sortedByEndPoint the intervals sorted after the ending points * @param intervalToVertexMap maps intervals to the vertices of the graph (may be the same) */ - private IntervalGraphDecomposition( + private IntervalGraphNiceDecomposition( List> sortedByStartPoint, List> sortedByEndPoint, Map, V> intervalToVertexMap, Map> vertexToIntervalMap) { + super(); + this.startSort = sortedByStartPoint; this.endSort = sortedByEndPoint; this.intervalToVertexMap = intervalToVertexMap; this.vertexToIntervalMap = vertexToIntervalMap; + computeNiceDecomposition(); } @@ -68,7 +60,7 @@ private IntervalGraphDecomposition( * graph was no interval graph * @see IntervalGraphRecognizer */ - public static IntervalGraphDecomposition create(Graph graph) + public static IntervalGraphNiceDecomposition create(Graph graph) { IntervalGraphRecognizer recog = new IntervalGraphRecognizer<>(graph); @@ -80,7 +72,7 @@ public static IntervalGraphDecomposition create(Graph g vertexToIntegerMap.put(key, vertexToIntervalVertexMap.get(key).getInterval()); if (recog.isIntervalGraph()) - return new IntervalGraphDecomposition( + return new IntervalGraphNiceDecomposition( recog.getIntervalsSortedByStartingPoint(), recog.getIntervalsSortedByEndingPoint(), recog.getIntervalToVertexMap(), vertexToIntegerMap); @@ -103,7 +95,7 @@ public static IntervalGraphDecomposition create(Graph g * @see ArrayList#sort(Comparator) */ public static , E, VertexType, - T extends Comparable> IntervalGraphDecomposition create( + T extends Comparable> IntervalGraphNiceDecomposition create( IntervalGraph intervalGraph) { Set vertexSet = intervalGraph.vertexSet(); @@ -119,7 +111,7 @@ T extends Comparable> IntervalGraphDecomposition create( ArrayList> endSort = new ArrayList<>(intervals); startSort.sort(Interval. getStartingComparator()); endSort.sort(Interval. getEndingComparator()); - return new IntervalGraphDecomposition( + return new IntervalGraphNiceDecomposition( startSort, endSort, intervalToVertexMap, vertexToIntervalMap); } @@ -133,13 +125,13 @@ T extends Comparable> IntervalGraphDecomposition create( * @param the value of the intervals * @return the algorithm for the computation of the nice tree decomposition */ - public static > IntervalGraphDecomposition> create( + public static > IntervalGraphNiceDecomposition> create( List> sortedByStartPoint, List> sortedByEndPoint) { HashMap, Interval> identity = new HashMap<>(sortedByStartPoint.size()); for (Interval interval : sortedByStartPoint) identity.put(interval, interval); - return new IntervalGraphDecomposition>( + return new IntervalGraphNiceDecomposition>( new ArrayList>(sortedByStartPoint), new ArrayList>(sortedByEndPoint), identity, identity); } @@ -154,7 +146,7 @@ public static > IntervalGraphDecomposition> IntervalGraphDecomposition> create( + public static > IntervalGraphNiceDecomposition> create( List> intervals) { ArrayList> startSort = new ArrayList<>(intervals); @@ -169,12 +161,9 @@ public static > IntervalGraphDecomposition current : startSort) { // first forget until you need to introduce new nodes while (endSort.get(endIndex).getEnd().compareTo(current.getStart()) < 0) { - addForget(endSort.get(endIndex)); + V forgetElement = intervalToVertexMap.get(endSort.get(endIndex)); + currentVertex = addForget(forgetElement, currentVertex); endIndex++; } - addIntroduce(current); + V introduceElement = intervalToVertexMap.get(current); + currentVertex = addIntroduce(introduceElement, currentVertex); } // add the last forget nodes while (endIndex < endSort.size()) { - addForget(endSort.get(endIndex++)); + V forgetElement = intervalToVertexMap.get(endSort.get(endIndex++)); + currentVertex = addForget(forgetElement, currentVertex); } } - /** - * Method for initializing the decomposition - */ - private void initDecomposition() - { - // creating objects - decomposition = new DefaultDirectedGraph(DefaultEdge.class); - decompositionIntervalMap = new HashMap>(); - - // create root - currentVertex = 0; - root = 0; - currentSet = new HashSet<>(); - decompositionIntervalMap.put(currentVertex, currentSet); - decomposition.addVertex(currentVertex); - } - - /** - * Method for adding a new root as a joint node - * Will be used/changed in future - */ - @SuppressWarnings("unused") - private void addNewRoot() - { - Set nextVertex = new HashSet<>(); - currentSet = nextVertex; - - // new root - decomposition.addVertex(currentVertex + 1); - decompositionIntervalMap.put(currentVertex + 1, nextVertex); - - // set current Vertex - currentVertex++; - - // new current root - decomposition.addVertex(currentVertex + 1); - decompositionIntervalMap.put(currentVertex + 1, nextVertex); - - // make joint edges - decomposition.addEdge(currentVertex, currentVertex+1); - decomposition.addEdge(currentVertex, root); - root = currentVertex; - - // set current Vertex - currentVertex++; - } - - /** - * Method for adding introducing nodes - * - * @param vertex the vertex, which is introduced - */ - private void addIntroduce(Interval interval) - { - Set nextVertex = new HashSet<>(currentSet); - nextVertex.add(intervalToVertexMap.get(interval)); - currentSet = nextVertex; - decomposition.addVertex(currentVertex + 1); - decomposition.addEdge(currentVertex, currentVertex + 1); - decompositionIntervalMap.put(currentVertex + 1, nextVertex); - - // set current Vertex - currentVertex++; - } - - /** - * method for adding forget nodes - * - * @param vertex the vertex, which is introduced - */ - private void addForget(Interval interval) - { - Set nextVertex = new HashSet<>(currentSet); - nextVertex.remove(intervalToVertexMap.get(interval)); - currentSet = nextVertex; - decomposition.addVertex(currentVertex + 1); - decomposition.addEdge(currentVertex, currentVertex + 1); - decompositionIntervalMap.put(currentVertex + 1, nextVertex); - - // set current Vertex - currentVertex++; - } - - /** - * getter for the decomposition as an directed graph - * - * @return the computed decomposition - */ - public Graph getDecomposition() - { - return decomposition; - } - - /** - * getter for the map from integer nodes of the decomposition to the intervals of the interval - * graph - * - * @return a nodes to interval map - */ - public Map> getMap() - { - return decompositionIntervalMap; - } - - /** - * getter for all roots of the decomposition - * - * @return a set of roots - */ - public Integer getRoot() - { - return root; - } - /** * getter for interval to vertex Map * diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java new file mode 100644 index 00000000000..ff798a634f0 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java @@ -0,0 +1,175 @@ +package org.jgrapht.alg.treedecomposition; + +import java.util.*; + +import org.jgrapht.*; +import org.jgrapht.alg.util.*; +import org.jgrapht.graph.*; + +public class NiceDecompositionBuilder +{ + + // resulting forest of the decomposition + private Graph decomposition; + + // map from decomposition nodes to the interval sets + private Map> decompositionMap; + + // the root of the tree + private Integer root; + + //next integer for vertex generation + private Integer nextInteger; + + /** + * constructor for all methods used in the abstract method + */ + public NiceDecompositionBuilder() + { + // creating objects + decomposition = new DefaultDirectedGraph(DefaultEdge.class); + decompositionMap = new HashMap>(); + + // create root + root = 0; + nextInteger = 1; + decompositionMap.put(root, new HashSet()); + decomposition.addVertex(root); + } + + /** + * getter for the next free Integer + * @return unused integer + */ + private Integer getNextInteger() + { + return nextInteger++; + } + + /** + * Method for adding a new join node + * @param toJoin which nodes should get a join node + * @return the new children of the join node, + * first element has no children, + * second element has the children of toJoin + */ + public Pair addJoin(Integer toJoin) + { + Set vertexSet = null; + + // new + Integer vertexChildLeft = getNextInteger(); + decomposition.addVertex(vertexChildLeft); + vertexSet = new HashSet(decompositionMap.get(toJoin)); + decompositionMap.put(vertexChildLeft, vertexSet); + + // new current root + Integer vertexChildRight = getNextInteger(); + decomposition.addVertex(vertexChildRight); + vertexSet = new HashSet(decompositionMap.get(toJoin)); + decompositionMap.put(vertexChildRight, vertexSet); + + // redirect all edges to new parent (should be just one!) + for(Integer successor : Graphs.successorListOf(decomposition, toJoin)) + { + decomposition.removeEdge(toJoin,successor); + decomposition.addEdge(vertexChildRight,successor); + } + //make children of parent vertex + decomposition.addEdge(toJoin, vertexChildLeft); + decomposition.addEdge(toJoin, vertexChildRight); + + + return new Pair(vertexChildLeft,vertexChildRight); + } + + /** + * Method for adding introducing nodes + * + * @param introducingElement the element, which is introduced + * @param currentVertex the vertex this element is introduced to + * @return the next vertex + */ + public Integer addIntroduce(V introducingElement, Integer currentVertex) + { + Set nextVertexSet = new HashSet<>(decompositionMap.get(currentVertex)); + nextVertexSet.add(introducingElement); + Integer nextVertex = getNextInteger(); + decomposition.addVertex(nextVertex); + decomposition.addEdge(currentVertex, nextVertex); + decompositionMap.put(nextVertex, nextVertexSet); + + return nextVertex; + } + + /** + * method for adding forget nodes + * + * @param forgettingElement the element, which is forgotten + * @param currentVertex the vertex this element is forgotten + * @return the next vertex + */ + public Integer addForget(V forgettingElement, Integer currentVertex) + { + Set nextVertexSet = new HashSet<>(decompositionMap.get(currentVertex)); + nextVertexSet.remove(forgettingElement); + Integer nextVertex = getNextInteger(); + decomposition.addVertex(nextVertex); + decomposition.addEdge(currentVertex, nextVertex); + decompositionMap.put(nextVertex, nextVertexSet); + + return nextVertex; + } + + /** + * Adds to all current leaves in the decomposition forget nodes until only empty sets are leaves + */ + public void leafClosure() + { + //make leave nodes + for(Integer leaf : decompositionMap.keySet()) { + //leaf is not a leaf + if(Graphs.vertexHasSuccessors(decomposition,leaf)) + continue; + + //otherwise add forget until empty set + Set vertexSet = decompositionMap.get(leaf); + Integer current = leaf; + for(V forget : vertexSet) { + current = addForget(forget, current); + } + } + } + + + /** + * getter for the decomposition as an directed graph + * + * @return the computed decomposition + */ + public Graph getDecomposition() + { + return decomposition; + } + + /** + * getter for the map from integer nodes of the decomposition to the intervals of the interval + * graph + * + * @return a nodes to interval map + */ + public Map> getMap() + { + return decompositionMap; + } + + /** + * getter for all roots of the decomposition + * + * @return a set of roots + */ + public Integer getRoot() + { + return root; + } +} diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java index fd36bfed3d9..ba3f19d690f 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java @@ -128,7 +128,7 @@ public void testIntervalgraphDecompositionForRegularGraphs() } //compute decomposition - IntervalGraphDecomposition decomp = IntervalGraphDecomposition.create(g); + IntervalGraphNiceDecomposition decomp = IntervalGraphNiceDecomposition.create(g); assertNotNull("graph was detected as not an interval graph", decomp); //test for nice decomposition @@ -178,7 +178,7 @@ public void testIntervalgraphDecompositionForIntervalLists() { list.add(new Interval(10,10+i)); } - IntervalGraphDecomposition> decompalg = IntervalGraphDecomposition.create(list); + IntervalGraphNiceDecomposition> decompalg = IntervalGraphNiceDecomposition.create(list); Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); Integer root = decompalg.getRoot(); From 8971c518aeb13fd024b8048ad1f491c752e89ea2 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 31 May 2018 20:43:52 +0200 Subject: [PATCH 116/131] added javadoc for builder class --- .../NiceDecompositionBuilder.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java index ff798a634f0..0d14237dcb8 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java @@ -6,6 +6,23 @@ import org.jgrapht.alg.util.*; import org.jgrapht.graph.*; +/** + * A builder for nice tree decompositions. + * A tree decomposition of a graph G is a tree T and a map b: V(T) -> Set, which satisfies the properties: + * - for every edge e in E(G), there is a node t in V(T) with e is a subset of b(v) + * - for all vertices v in V(G) the set {t in V(T) | v in b(t)} is non-empty and connected in T + * + * A nice tree decomposition is a special tree decomposition, which satisfies the properties: + * - for root r in V(T) and leaf l in V(T): b(r)=b(t)=empty set + * - every non-leaf node t in V(T) is of one of the following three types: + * - introduce node: t has exactly one child d and b(t) = b(d) union w for some w in V(G) + * - forget node: t has exactly one child d and b(t) union w = b(d) for some w in V(G)\b(t) + * - join node: t has exactly two child d_1, d_2 and b(t)=b(d_1)=b(d_2) + * + * @author Ira Justus Fesefeldt (phoenixIra) + * + * @param the vertices of G + */ public class NiceDecompositionBuilder { From a2c9761f366d4bbb09328bf809ffcc0917e9e888 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Thu, 31 May 2018 20:59:29 +0200 Subject: [PATCH 117/131] removed some special symbols --- .../jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java index 0d14237dcb8..d4f8bd10094 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java @@ -8,7 +8,7 @@ /** * A builder for nice tree decompositions. - * A tree decomposition of a graph G is a tree T and a map b: V(T) -> Set, which satisfies the properties: + * A tree decomposition of a graph G is a tree T and a map b: V(T) to Set of V(G), which satisfies the properties: * - for every edge e in E(G), there is a node t in V(T) with e is a subset of b(v) * - for all vertices v in V(G) the set {t in V(T) | v in b(t)} is non-empty and connected in T * From 6a9fe77df79e83fab60c91b579c56394031dfe71 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Sat, 2 Jun 2018 19:05:52 +0200 Subject: [PATCH 118/131] Refactores tests methods a bit --- .../NiceDecompositionUtil.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java new file mode 100644 index 00000000000..3347353fee3 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java @@ -0,0 +1,114 @@ +package org.jgrapht.alg.treedecompostion; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.*; +import java.util.Map.*; + +import org.jgrapht.*; +import org.jgrapht.graph.*; + +public class NiceDecompositionUtil +{ + private NiceDecompositionUtil() {} + + /** + * tests whether the tree decomposition (decomposition, map) with root is nice + * + * @param decomposition the tree decomposition to check + * @param map the map of the tree decomposition + * @param root the root of the tree decomposition + */ + public static void testNiceDecomposition(Graph decomposition, Map> map, V root){ + + Queue queue = new LinkedList(); + + //test and add root + assertTrue(root+" is no valid root" + + "\n in decomposition "+decomposition + + "\n and map"+map, map.get(root).size() == 0); + queue.add(root); + + while(!queue.isEmpty()) + { + V current = queue.poll(); + List successor = Graphs.successorListOf(decomposition, current); + if(successor.size() == 0 && map.get(current).isEmpty()) continue; //leaf node + if(successor.size() == 1) //forget or introduce + { + V next = successor.get(0); + queue.add(next); + Set union = new HashSet(map.get(current)); + union.addAll(map.get(next)); + if(union.size() == map.get(next).size() || union.size() == map.get(current).size()) + { + if(map.get(current).size() == map.get(next).size()-1) continue; //introduce + else if(map.get(current).size()-1 == map.get(next).size()) continue; //forget + } + } + if(successor.size() == 2) //join + { + V first = successor.get(0); + V second = successor.get(1); + queue.add(first); + queue.add(second); + Set union = new HashSet(map.get(current)); + union.addAll(map.get(first)); + union.addAll(map.get(second)); + if(union.size() == map.get(current).size() + && union.size() == map.get(first).size() + && union.size() == map.get(second).size()) + continue; //join node! + } + assertFalse("Vertex Set "+current+" is not a valid node for a nice decomposition" + + "\nin decomposition "+decomposition + + "\nwith map "+map, true); //no valid node! + } + assertTrue(true); + } + + /** + * Test whether (decomposition, map) a tree decomposition of oldGraph is + * + * @param oldGraph the graph of the tree decomposition + * @param decomposition the tree decomposition + * @param map the map from vertices to the tree decomposition to the sets of the tree decomposition + */ + public static void testDecomposition(Graph oldGraph, Graph decomposition, Map> map){ + Set edgeSet = oldGraph.edgeSet(); + Set vertexSet = decomposition.vertexSet(); + //Every edge is represented + for(F e : edgeSet) + { + boolean hasVertex = false; + for(V v : vertexSet) + { + if(map.get(v).contains(oldGraph.getEdgeSource(e)) && map.get(v).contains(oldGraph.getEdgeTarget(e))) { + hasVertex = true; + continue; + } + } + assertTrue("Edge "+e+" is not found" + + "\nin graph "+decomposition + + "\nwith map "+map, hasVertex); + } + //every vertex has non-empty connected set of vertex sets + Set oldVertexSet = oldGraph.vertexSet(); + for(W w : oldVertexSet) + { + Set keySet = new HashSet(); + for(Entry> entry : map.entrySet()) + { + if(entry.getValue().contains(w)) + keySet.add(entry.getKey()); + } + //not empty + assertFalse("Vertex "+w+" is not represented\n in decomposition "+decomposition+"\n and map "+map, keySet.isEmpty()); + //connected + Graph subgraph = new AsSubgraph(decomposition,keySet); + assertTrue("Vertex "+w+" is not connected\n in decomposition "+decomposition+"\n and map "+map,GraphTests.isConnected(subgraph)); + } + } + +} From e4bcaa7a19ab16c38fa857d49ae6d0423a2d0040 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Sat, 2 Jun 2018 19:07:05 +0200 Subject: [PATCH 119/131] ... and this --- .../IntervalGraphDecompositionTest.java | 90 +------------------ 1 file changed, 3 insertions(+), 87 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java index ba3f19d690f..d744896d06a 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.*; import java.util.*; -import java.util.Map.Entry; import org.jgrapht.*; import org.jgrapht.alg.treedecomposition.*; @@ -14,89 +13,6 @@ public class IntervalGraphDecompositionTest { - private void testNiceDecomposition(Graph decomposition, Map> map, V root){ - - Queue queue = new LinkedList(); - - //test and add root - assertTrue(root+" is no valid root" - + "\n in decomposition "+decomposition - + "\n and map"+map, map.get(root).size() == 0); - queue.add(root); - - while(!queue.isEmpty()) - { - V current = queue.poll(); - List successor = Graphs.successorListOf(decomposition, current); - if(successor.size() == 0 && map.get(current).isEmpty()) continue; //leaf node - if(successor.size() == 1) //forget or introduce - { - V next = successor.get(0); - queue.add(next); - Set union = new HashSet(map.get(current)); - union.addAll(map.get(next)); - if(union.size() == map.get(next).size() || union.size() == map.get(current).size()) - { - if(map.get(current).size() == map.get(next).size()-1) continue; //introduce - else if(map.get(current).size()-1 == map.get(next).size()) continue; //forget - } - } - if(successor.size() == 2) //join - { - V first = successor.get(0); - V second = successor.get(1); - queue.add(first); - queue.add(second); - Set union = new HashSet(map.get(current)); - union.addAll(map.get(first)); - union.addAll(map.get(second)); - if(union.size() == map.get(current).size() - && union.size() == map.get(first).size() - && union.size() == map.get(second).size()) - continue; //join node! - } - assertFalse("Vertex Set "+current+" is not a valid node for a nice decomposition" - + "\nin decomposition "+decomposition - + "\nwith map "+map, true); //no valid node! - } - assertTrue(true); - } - - private void testDecomposition(Graph oldGraph, Graph decomposition, Map> map){ - Set edgeSet = oldGraph.edgeSet(); - Set vertexSet = decomposition.vertexSet(); - //Every edge is represented - for(F e : edgeSet) - { - boolean hasVertex = false; - for(V v : vertexSet) - { - if(map.get(v).contains(oldGraph.getEdgeSource(e)) && map.get(v).contains(oldGraph.getEdgeTarget(e))) { - hasVertex = true; - continue; - } - } - assertTrue("Edge "+e+" is not found" - + "\nin graph "+decomposition - + "\nwith map "+map, hasVertex); - } - //every vertex has non-empty connected set of vertex sets - Set oldVertexSet = oldGraph.vertexSet(); - for(W w : oldVertexSet) - { - Set keySet = new HashSet(); - for(Entry> entry : map.entrySet()) - { - if(entry.getValue().contains(w)) - keySet.add(entry.getKey()); - } - //not empty - assertFalse("Vertex "+w+" is not represented\n in decomposition "+decomposition+"\n and map "+map, keySet.isEmpty()); - //connected - Graph subgraph = new AsSubgraph(decomposition,keySet); - assertTrue("Vertex "+w+" is not connected\n in decomposition "+decomposition+"\n and map "+map,GraphTests.isConnected(subgraph)); - } - } /** * Interval Graph representation of the graph to test: @@ -132,8 +48,8 @@ public void testIntervalgraphDecompositionForRegularGraphs() assertNotNull("graph was detected as not an interval graph", decomp); //test for nice decomposition - testNiceDecomposition(decomp.getDecomposition(), decomp.getMap(), decomp.getRoot()); - testDecomposition(g, decomp.getDecomposition(), decomp.getMap()); + NiceDecompositionUtil.testNiceDecomposition(decomp.getDecomposition(), decomp.getMap(), decomp.getRoot()); + NiceDecompositionUtil.testDecomposition(g, decomp.getDecomposition(), decomp.getMap()); } @Test @@ -182,7 +98,7 @@ public void testIntervalgraphDecompositionForIntervalLists() Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); Integer root = decompalg.getRoot(); - testNiceDecomposition(decomp,map,root); + NiceDecompositionUtil.testNiceDecomposition(decomp,map,root); } From 139709b34f63ab25ea4e6266e7aa5230d8f2f391 Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Sun, 10 Jun 2018 01:19:57 +0200 Subject: [PATCH 120/131] refactored/renamed and changed an isEmpty --- ...ntervalGraphNiceDecompositionBuilder.java} | 20 +++++++++---------- .../NiceDecompositionBuilder.java | 2 +- .../package-info.java | 2 +- ...ntervalGraphDecompositionBuilderTest.java} | 14 ++++++------- .../NiceDecompositionBuilderTestUtil.java} | 8 ++++---- 5 files changed, 23 insertions(+), 23 deletions(-) rename jgrapht-core/src/main/java/org/jgrapht/alg/{treedecomposition/IntervalGraphNiceDecomposition.java => decomposition/IntervalGraphNiceDecompositionBuilder.java} (92%) rename jgrapht-core/src/main/java/org/jgrapht/alg/{treedecomposition => decomposition}/NiceDecompositionBuilder.java (99%) rename jgrapht-core/src/main/java/org/jgrapht/alg/{treedecomposition => decomposition}/package-info.java (55%) rename jgrapht-core/src/test/java/org/jgrapht/alg/{treedecompostion/IntervalGraphDecompositionTest.java => decompostion/IntervalGraphDecompositionBuilderTest.java} (82%) rename jgrapht-core/src/test/java/org/jgrapht/alg/{treedecompostion/NiceDecompositionUtil.java => decompostion/NiceDecompositionBuilderTestUtil.java} (95%) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphNiceDecomposition.java b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/IntervalGraphNiceDecompositionBuilder.java similarity index 92% rename from jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphNiceDecomposition.java rename to jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/IntervalGraphNiceDecompositionBuilder.java index 2f6bd0dab25..718688c2a26 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/IntervalGraphNiceDecomposition.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/IntervalGraphNiceDecompositionBuilder.java @@ -1,4 +1,4 @@ -package org.jgrapht.alg.treedecomposition; +package org.jgrapht.alg.decomposition; import java.util.*; import org.jgrapht.*; @@ -15,7 +15,7 @@ * @author Ira Justus Fesefeldt (PhoenixIra) * @since Mai 14, 2018 */ -public class IntervalGraphNiceDecomposition, V> extends NiceDecompositionBuilder +public class IntervalGraphNiceDecompositionBuilder, V> extends NiceDecompositionBuilder { // input to the algorithm, list of sorted intervals private List> startSort, endSort; @@ -32,7 +32,7 @@ public class IntervalGraphNiceDecomposition, V> extends * @param sortedByEndPoint the intervals sorted after the ending points * @param intervalToVertexMap maps intervals to the vertices of the graph (may be the same) */ - private IntervalGraphNiceDecomposition( + private IntervalGraphNiceDecompositionBuilder( List> sortedByStartPoint, List> sortedByEndPoint, Map, V> intervalToVertexMap, Map> vertexToIntervalMap) { @@ -60,7 +60,7 @@ private IntervalGraphNiceDecomposition( * graph was no interval graph * @see IntervalGraphRecognizer */ - public static IntervalGraphNiceDecomposition create(Graph graph) + public static IntervalGraphNiceDecompositionBuilder create(Graph graph) { IntervalGraphRecognizer recog = new IntervalGraphRecognizer<>(graph); @@ -72,7 +72,7 @@ public static IntervalGraphNiceDecomposition create(Graph( + return new IntervalGraphNiceDecompositionBuilder( recog.getIntervalsSortedByStartingPoint(), recog.getIntervalsSortedByEndingPoint(), recog.getIntervalToVertexMap(), vertexToIntegerMap); @@ -95,7 +95,7 @@ public static IntervalGraphNiceDecomposition create(Graph, E, VertexType, - T extends Comparable> IntervalGraphNiceDecomposition create( + T extends Comparable> IntervalGraphNiceDecompositionBuilder create( IntervalGraph intervalGraph) { Set vertexSet = intervalGraph.vertexSet(); @@ -111,7 +111,7 @@ T extends Comparable> IntervalGraphNiceDecomposition create( ArrayList> endSort = new ArrayList<>(intervals); startSort.sort(Interval. getStartingComparator()); endSort.sort(Interval. getEndingComparator()); - return new IntervalGraphNiceDecomposition( + return new IntervalGraphNiceDecompositionBuilder( startSort, endSort, intervalToVertexMap, vertexToIntervalMap); } @@ -125,13 +125,13 @@ T extends Comparable> IntervalGraphNiceDecomposition create( * @param the value of the intervals * @return the algorithm for the computation of the nice tree decomposition */ - public static > IntervalGraphNiceDecomposition> create( + public static > IntervalGraphNiceDecompositionBuilder> create( List> sortedByStartPoint, List> sortedByEndPoint) { HashMap, Interval> identity = new HashMap<>(sortedByStartPoint.size()); for (Interval interval : sortedByStartPoint) identity.put(interval, interval); - return new IntervalGraphNiceDecomposition>( + return new IntervalGraphNiceDecompositionBuilder>( new ArrayList>(sortedByStartPoint), new ArrayList>(sortedByEndPoint), identity, identity); } @@ -146,7 +146,7 @@ public static > IntervalGraphNiceDecomposition> IntervalGraphNiceDecomposition> create( + public static > IntervalGraphNiceDecompositionBuilder> create( List> intervals) { ArrayList> startSort = new ArrayList<>(intervals); diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java similarity index 99% rename from jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java rename to jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java index d4f8bd10094..429626031cb 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/NiceDecompositionBuilder.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java @@ -1,4 +1,4 @@ -package org.jgrapht.alg.treedecomposition; +package org.jgrapht.alg.decomposition; import java.util.*; diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/package-info.java similarity index 55% rename from jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java rename to jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/package-info.java index efe9ce81a6a..3e43e3d84ee 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/package-info.java @@ -3,4 +3,4 @@ * Tree Decomposition related algorithms * */ -package org.jgrapht.alg.treedecomposition; +package org.jgrapht.alg.decomposition; diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java similarity index 82% rename from jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java rename to jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java index d744896d06a..9625b5377c0 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/IntervalGraphDecompositionTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java @@ -1,4 +1,4 @@ -package org.jgrapht.alg.treedecompostion; +package org.jgrapht.alg.decompostion; import static org.junit.Assert.*; @@ -10,7 +10,7 @@ import org.jgrapht.intervalgraph.interval.*; import org.junit.*; -public class IntervalGraphDecompositionTest +public class IntervalGraphDecompositionBuilderTest { @@ -44,12 +44,12 @@ public void testIntervalgraphDecompositionForRegularGraphs() } //compute decomposition - IntervalGraphNiceDecomposition decomp = IntervalGraphNiceDecomposition.create(g); + IntervalGraphNiceDecomposition decomp = IntervalGraphNiceDecompositionBuilder.create(g); assertNotNull("graph was detected as not an interval graph", decomp); //test for nice decomposition - NiceDecompositionUtil.testNiceDecomposition(decomp.getDecomposition(), decomp.getMap(), decomp.getRoot()); - NiceDecompositionUtil.testDecomposition(g, decomp.getDecomposition(), decomp.getMap()); + NiceDecompositionBuilderTestUtil.testNiceDecomposition(decomp.getDecomposition(), decomp.getMap(), decomp.getRoot()); + NiceDecompositionBuilderTestUtil.testDecomposition(g, decomp.getDecomposition(), decomp.getMap()); } @Test @@ -94,11 +94,11 @@ public void testIntervalgraphDecompositionForIntervalLists() { list.add(new Interval(10,10+i)); } - IntervalGraphNiceDecomposition> decompalg = IntervalGraphNiceDecomposition.create(list); + IntervalGraphNiceDecomposition> decompalg = IntervalGraphNiceDecompositionBuilder.create(list); Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); Integer root = decompalg.getRoot(); - NiceDecompositionUtil.testNiceDecomposition(decomp,map,root); + NiceDecompositionBuilderTestUtil.testNiceDecomposition(decomp,map,root); } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java b/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/NiceDecompositionBuilderTestUtil.java similarity index 95% rename from jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java rename to jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/NiceDecompositionBuilderTestUtil.java index 3347353fee3..c9985d2aa88 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecompostion/NiceDecompositionUtil.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/NiceDecompositionBuilderTestUtil.java @@ -1,4 +1,4 @@ -package org.jgrapht.alg.treedecompostion; +package org.jgrapht.alg.decompostion; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -9,9 +9,9 @@ import org.jgrapht.*; import org.jgrapht.graph.*; -public class NiceDecompositionUtil +public class NiceDecompositionBuilderTestUtil { - private NiceDecompositionUtil() {} + private NiceDecompositionBuilderTestUtil() {} /** * tests whether the tree decomposition (decomposition, map) with root is nice @@ -27,7 +27,7 @@ public static void testNiceDecomposition(Graph decomposition, Map Date: Sun, 10 Jun 2018 01:42:29 +0200 Subject: [PATCH 121/131] ci fix --- .../decompostion/IntervalGraphDecompositionBuilderTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java index 9625b5377c0..f1e69a982f9 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/decompostion/IntervalGraphDecompositionBuilderTest.java @@ -5,7 +5,7 @@ import java.util.*; import org.jgrapht.*; -import org.jgrapht.alg.treedecomposition.*; +import org.jgrapht.alg.decomposition.*; import org.jgrapht.graph.*; import org.jgrapht.intervalgraph.interval.*; import org.junit.*; @@ -44,7 +44,7 @@ public void testIntervalgraphDecompositionForRegularGraphs() } //compute decomposition - IntervalGraphNiceDecomposition decomp = IntervalGraphNiceDecompositionBuilder.create(g); + IntervalGraphNiceDecompositionBuilder decomp = IntervalGraphNiceDecompositionBuilder.create(g); assertNotNull("graph was detected as not an interval graph", decomp); //test for nice decomposition @@ -94,7 +94,7 @@ public void testIntervalgraphDecompositionForIntervalLists() { list.add(new Interval(10,10+i)); } - IntervalGraphNiceDecomposition> decompalg = IntervalGraphNiceDecompositionBuilder.create(list); + IntervalGraphNiceDecompositionBuilder> decompalg = IntervalGraphNiceDecompositionBuilder.create(list); Graph decomp = decompalg.getDecomposition(); Map>> map = decompalg.getMap(); Integer root = decompalg.getRoot(); From e6c6609b2466cfb9968db99c5aacbbbedbc6026b Mon Sep 17 00:00:00 2001 From: Ira Justus Fesefeldt Date: Wed, 13 Jun 2018 13:10:12 +0200 Subject: [PATCH 122/131] changed abstract nice Decomposition Builder class --- .../NiceDecompositionBuilder.java | 126 ++++++++++-------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java index 429626031cb..8ba47a265ca 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/decomposition/NiceDecompositionBuilder.java @@ -7,55 +7,57 @@ import org.jgrapht.graph.*; /** - * A builder for nice tree decompositions. - * A tree decomposition of a graph G is a tree T and a map b: V(T) to Set of V(G), which satisfies the properties: - * - for every edge e in E(G), there is a node t in V(T) with e is a subset of b(v) - * - for all vertices v in V(G) the set {t in V(T) | v in b(t)} is non-empty and connected in T + * A builder for nice tree decompositions. + * A tree decomposition of a graph G is a tree T and a map b:V(T) → Set<V(G)>, + * which satisfies the properties: + *

  • for every edge e in E(G), there is a node t in V(T) with e is a subset of b(v)
  • + *
  • for all vertices v in V(G) the set {t ∈ V(T) | v ∈ b(t)} is non-empty and connected in T
* - * A nice tree decomposition is a special tree decomposition, which satisfies the properties: - * - for root r in V(T) and leaf l in V(T): b(r)=b(t)=empty set - * - every non-leaf node t in V(T) is of one of the following three types: - * - introduce node: t has exactly one child d and b(t) = b(d) union w for some w in V(G) - * - forget node: t has exactly one child d and b(t) union w = b(d) for some w in V(G)\b(t) - * - join node: t has exactly two child d_1, d_2 and b(t)=b(d_1)=b(d_2) + * A nice tree decomposition is a special tree decomposition, which satisfies the properties: + *
  • for root r ∈ V(T) and leaf l ∈ V(T): b(r)=b(t)=∅
  • + *
  • every non-leaf node t ∈ V(T) is of one of the following three types: + *
    • introduce node: t has exactly one child d and b(t) = b(d) ∪ w for some w ∈ V(G)
    • + *
    • forget node: t has exactly one child d and b(t) ∪ w = b(d) for some w ∈ V(G)\b(t)
    • + *
    • join node: t has exactly two child d_1, d_2 and b(t)=b(d_1)=b(d_2)
* - * @author Ira Justus Fesefeldt (phoenixIra) + * @author Ira Justus Fesefeldt (PhoenixIra) * * @param the vertices of G */ -public class NiceDecompositionBuilder +abstract public class NiceDecompositionBuilder { - - // resulting forest of the decomposition + + // resulting decomposition private Graph decomposition; - + // map from decomposition nodes to the interval sets - private Map> decompositionMap; - + private Map> decompositionMap; + // the root of the tree private Integer root; - - //next integer for vertex generation + + // next integer for vertex generation private Integer nextInteger; - + /** * constructor for all methods used in the abstract method */ - public NiceDecompositionBuilder() + protected NiceDecompositionBuilder() { // creating objects decomposition = new DefaultDirectedGraph(DefaultEdge.class); decompositionMap = new HashMap>(); - + // create root root = 0; nextInteger = 1; decompositionMap.put(root, new HashSet()); decomposition.addVertex(root); } - + /** * getter for the next free Integer + * * @return unused integer */ private Integer getNextInteger() @@ -65,49 +67,48 @@ private Integer getNextInteger() /** * Method for adding a new join node + * * @param toJoin which nodes should get a join node - * @return the new children of the join node, - * first element has no children, - * second element has the children of toJoin + * @return the new children of the join node, first element has no children, second element has + * the children of toJoin */ - public Pair addJoin(Integer toJoin) + protected Pair addJoin(Integer toJoin) { Set vertexSet = null; - - // new + + // new Integer vertexChildLeft = getNextInteger(); decomposition.addVertex(vertexChildLeft); vertexSet = new HashSet(decompositionMap.get(toJoin)); decompositionMap.put(vertexChildLeft, vertexSet); - + // new current root Integer vertexChildRight = getNextInteger(); decomposition.addVertex(vertexChildRight); vertexSet = new HashSet(decompositionMap.get(toJoin)); decompositionMap.put(vertexChildRight, vertexSet); - + // redirect all edges to new parent (should be just one!) - for(Integer successor : Graphs.successorListOf(decomposition, toJoin)) - { - decomposition.removeEdge(toJoin,successor); - decomposition.addEdge(vertexChildRight,successor); + for (Integer successor : Graphs.successorListOf(decomposition, toJoin)) { + decomposition.removeEdge(toJoin, successor); + decomposition.addEdge(vertexChildRight, successor); } - //make children of parent vertex + // make children of parent vertex decomposition.addEdge(toJoin, vertexChildLeft); decomposition.addEdge(toJoin, vertexChildRight); - - return new Pair(vertexChildLeft,vertexChildRight); + return new Pair(vertexChildLeft, vertexChildRight); } /** - * Method for adding introducing nodes + * Method for adding introducing nodes. It is only usable if the vertex currentVertex is a leaf. + * It then adds the new introducing node as the child of currentVertex * * @param introducingElement the element, which is introduced * @param currentVertex the vertex this element is introduced to * @return the next vertex */ - public Integer addIntroduce(V introducingElement, Integer currentVertex) + protected Integer addIntroduce(V introducingElement, Integer currentVertex) { Set nextVertexSet = new HashSet<>(decompositionMap.get(currentVertex)); nextVertexSet.add(introducingElement); @@ -120,13 +121,14 @@ public Integer addIntroduce(V introducingElement, Integer currentVertex) } /** - * method for adding forget nodes + * method for adding forget nodes. It is only usable if the vertex currentVertex is a leaf. + * It then adds the new forget node as the child of currentVertex * * @param forgettingElement the element, which is forgotten * @param currentVertex the vertex this element is forgotten * @return the next vertex */ - public Integer addForget(V forgettingElement, Integer currentVertex) + protected Integer addForget(V forgettingElement, Integer currentVertex) { Set nextVertexSet = new HashSet<>(decompositionMap.get(currentVertex)); nextVertexSet.remove(forgettingElement); @@ -137,51 +139,51 @@ public Integer addForget(V forgettingElement, Integer currentVertex) return nextVertex; } - + /** - * Adds to all current leaves in the decomposition forget nodes until only empty sets are leaves + * Adds to all current leaves in the decomposition forget/introduce nodes until only empty sets are leafes */ - public void leafClosure() + protected void leafClosure() { - //make leave nodes - for(Integer leaf : decompositionMap.keySet()) { - //leaf is not a leaf - if(Graphs.vertexHasSuccessors(decomposition,leaf)) + Set vertices = new HashSet(decomposition.vertexSet()); + // make leave nodes + for (Integer leaf : vertices) { + // leaf is not a leaf + if (Graphs.vertexHasSuccessors(decomposition, leaf)) continue; - - //otherwise add forget until empty set + + // otherwise add forget until empty set Set vertexSet = decompositionMap.get(leaf); Integer current = leaf; - for(V forget : vertexSet) { + for (V forget : vertexSet) { current = addForget(forget, current); } } } - - + /** - * getter for the decomposition as an directed graph + * Getter for the decomposition as an unmodifiable, directed graph * * @return the computed decomposition */ public Graph getDecomposition() { - return decomposition; + return new AsUnmodifiableGraph<>(decomposition); } /** - * getter for the map from integer nodes of the decomposition to the intervals of the interval + * Getter for an unmodifiable map from integer nodes of the decomposition to the intervals of the interval * graph * * @return a nodes to interval map */ public Map> getMap() { - return decompositionMap; + return Collections.unmodifiableMap(decompositionMap); } /** - * getter for all roots of the decomposition + * Getter for the root of the decomposition * * @return a set of roots */ @@ -189,4 +191,10 @@ public Integer getRoot() { return root; } + + @Override + public String toString() + { + return getDecomposition() + "\n " + getMap(); + } } From 7f922492d9a29d5b1bb8a12d0bc0f2cd7ab52564 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 16 Jun 2018 12:01:57 +0200 Subject: [PATCH 123/131] Minor changes, need to change the input parameters --- .../java/org/jgrapht/alg/treedecomposition/package-info.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java new file mode 100644 index 00000000000..83ec80de9ce --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java @@ -0,0 +1,4 @@ +/** + * Greedy colouring for decomposition trees + */ +package org.jgrapht.alg.treedecomposition; From e3289bea5be47365ce237df46d9565d0bff79733 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 16 Jun 2018 12:04:44 +0200 Subject: [PATCH 124/131] Minor changes, need to change the input parameters --- .../DecompositionTreeColour.java | 27 ++++++++----------- .../DecompositionTreeColourTest.java | 4 +++ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java index 345bf5542ac..58bddb16fbe 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java @@ -29,26 +29,25 @@ public class DecompositionTreeColour implements VertexColoringAlgorithm */ private Graph, E> graph; - + /** - * @param graph + * @param graph graph */ - + public DecompositionTreeColour(Graph, E> graph) { this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); } - - + + /** * Getting the ordering for the vertices * @return the ordering of the vertices */ protected Iterable> getVertexOrdering() { - System.out.println((Iterable>) graph.vertexSet()); return (Iterable>) graph.vertexSet(); - + } /* (non-Javadoc) @@ -62,16 +61,13 @@ public Coloring getColoring() { Set used = new HashSet<>(); Set free = new HashSet<>(); - //lself loops not allowed, repeatations of inner vertices not allowed + //self loops not allowed, repetitions of inner vertices not allowed for(List outerVertex:getVertexOrdering() ) { - - //the case of a generalised decomposition tree - /* for (E edge: graph.edgesOf(outerVertex)) { - List oppoSiteVertex = Graphs.getOppositeVertex(graph, edge, outerVertex); - }*/ - + + + //need to sort the inner vertex here or do something so that sorting is not needed for(V innerVertex : outerVertex ) { //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour @@ -109,8 +105,7 @@ public Coloring getColoring() { } int maxColourAssigned = Collections.max(asssignedColors.values()); - - System.out.println(Arrays.asList(asssignedColors)); + return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java index 26aba9578e3..92e81e0418d 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java @@ -1,6 +1,7 @@ package org.jgrapht.alg.treedecomposition; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import java.util.ArrayList; import java.util.List; @@ -88,6 +89,9 @@ public void testGreedy1() assertEquals(1, colors.get(2).intValue()); assertEquals(2, colors.get(3).intValue()); assertEquals(0, colors.get(4).intValue()); + + //iterate over all edges/vertices and check if the test can be done better + assertNotEquals(colors.get(1).intValue(), colors.get(2).intValue()); } @Test public void testGreedy2() From 8253cc49e831200df27c88c1449449b858058d6a Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 16 Jun 2018 18:10:26 +0200 Subject: [PATCH 125/131] Input parameters changed to Graph and Map> --- .../DecompositionTreeColour.java | 28 ++++++++++--------- .../alg/treedecomposition/package-info.java | 8 ------ 2 files changed, 15 insertions(+), 21 deletions(-) delete mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java index 58bddb16fbe..5e6f4f558d3 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java @@ -16,7 +16,7 @@ * Colouring of decomposition trees (currently done for interval graphs). This algorithm iterates over lists of vertices and assigns * the smallest colour to each of the vertices such that the no vertex in the same list has the same colour. * - * @author Suchanda Bhattacharyya + * @author Suchanda Bhattacharyya (dia007) * * @param The type of graph vertex * @param The type of graph edge @@ -25,18 +25,19 @@ public class DecompositionTreeColour implements VertexColoringAlgorithm { /** - * The input graph + * The input graph */ - private Graph, E> graph; - - + private Graph graph; /** - * @param graph graph + * The map of the vertices in the input graph to it's interval sets */ + private Map > decompositionMap; + - public DecompositionTreeColour(Graph, E> graph) + public DecompositionTreeColour(Graph graph,Map > decompositionMap) { this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); + this.decompositionMap = Objects.requireNonNull(decompositionMap, "there must be some decomposition present"); } @@ -44,9 +45,10 @@ public DecompositionTreeColour(Graph, E> graph) * Getting the ordering for the vertices * @return the ordering of the vertices */ - protected Iterable> getVertexOrdering() + + protected Iterable getVertexOrdering() { - return (Iterable>) graph.vertexSet(); + return (Iterable) graph.vertexSet(); } @@ -64,12 +66,12 @@ public Coloring getColoring() { //self loops not allowed, repetitions of inner vertices not allowed - for(List outerVertex:getVertexOrdering() ) { - + for(Integer vertex:getVertexOrdering() ) { + //find the intervals corresponding to the vertex + Set intervalSet = decompositionMap.get(vertex); - //need to sort the inner vertex here or do something so that sorting is not needed - for(V innerVertex : outerVertex ) { + for(V innerVertex : intervalSet ) { //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour if(asssignedColors.containsKey(innerVertex)) { used.add(asssignedColors.get(innerVertex)); diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java deleted file mode 100644 index 735395e2f80..00000000000 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * - */ -/** - * @author suchandra - * - */ -package org.jgrapht.alg.treedecomposition; \ No newline at end of file From f014e2134cc23ca114444e6083c8d3717f5f2f3c Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 16 Jun 2018 18:44:30 +0200 Subject: [PATCH 126/131] Added tests, need to add more tests --- .../DecompositionTreeColour.java | 15 +-- .../DecompositionTreeColourTest.java | 105 ++++++------------ 2 files changed, 45 insertions(+), 75 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java index 5e6f4f558d3..50bdd4285bd 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java @@ -1,6 +1,5 @@ package org.jgrapht.alg.treedecomposition; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -8,8 +7,8 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import org.jgrapht.Graph; -import org.jgrapht.Graphs; import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; /** @@ -49,6 +48,7 @@ public DecompositionTreeColour(Graph graph,Map > dec protected Iterable getVertexOrdering() { return (Iterable) graph.vertexSet(); + } @@ -68,15 +68,16 @@ public Coloring getColoring() { for(Integer vertex:getVertexOrdering() ) { - //find the intervals corresponding to the vertex - Set intervalSet = decompositionMap.get(vertex); + //find the intervals corresponding to the vertex + //need to sort the vertices + List intervalSet = decompositionMap.get(vertex).stream().sorted().collect(Collectors.toList()); + for(V innerVertex : intervalSet ) { //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour if(asssignedColors.containsKey(innerVertex)) { used.add(asssignedColors.get(innerVertex)); - - + } else { @@ -105,9 +106,9 @@ public Coloring getColoring() { used.clear(); } + int maxColourAssigned = Collections.max(asssignedColors.values()); - return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); } } diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java index 92e81e0418d..3af88f1c06e 100644 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java @@ -4,8 +4,12 @@ import static org.junit.Assert.assertNotEquals; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.jgrapht.Graph; import org.jgrapht.Graphs; @@ -21,91 +25,56 @@ */ public class DecompositionTreeColourTest { - protected VertexColoringAlgorithm getAlgorithm(Graph, DefaultEdge> graph) + protected VertexColoringAlgorithm getAlgorithm(Graph graph, Map > decompositionMap) { - return new DecompositionTreeColour<>(graph); + return new DecompositionTreeColour<>(graph, decompositionMap); } //need to add more graphs - final protected Graph, DefaultEdge> createGraph1() + final protected List createGraph1() { - Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class); - - List outerVertex1 = new ArrayList<>(); - List outerVertex2 = new ArrayList<>(); - List outerVertex3 = new ArrayList<>(); - List outerVertex4 = new ArrayList<>(); - List outerVertex5 = new ArrayList<>(); - - outerVertex1.add(1); - outerVertex2.add(1); outerVertex2.add(2);outerVertex2.add(3); - outerVertex3.add(2);outerVertex3.add(3); - outerVertex4.add(2); - outerVertex5.add(2);outerVertex5.add(4); - - Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); - Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); - Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); - Graphs.addEdgeWithVertices(graph, outerVertex4, outerVertex5); - return graph; + Graph graph = new SimpleGraph<>(DefaultEdge.class) ; + Map > decompositionMap = new HashMap<>(); + List returnArrayList= new ArrayList<>(); + + Graphs.addEdgeWithVertices(graph, 0, 1); + Graphs.addEdgeWithVertices(graph, 1, 2); + Graphs.addEdgeWithVertices(graph, 2, 3); + Graphs.addEdgeWithVertices(graph, 3, 4); + Graphs.addEdgeWithVertices(graph, 4, 5); + + int v1 = 11,v2=22,v3=33,v4=44; + Set set0 = new HashSet<>(); + Set set1 = new HashSet<>(); + Set set2 = new HashSet<>(); + Set set3 = new HashSet<>(); + Set set4 = new HashSet<>(); + Set set5 = new HashSet<>(); + set0.add(Collections.emptySet()); set1.add(v1); set2.add(v1); set2.add(v2); set2.add(v3);set3.add(v2); set3.add(v3); set4.add(v2); set5.add(v2); set5.add(v4); + + decompositionMap.put(0,set0); decompositionMap.put(1,set1 ); decompositionMap.put(2,set2 );decompositionMap.put(3,set3 );decompositionMap.put(4,set4 );decompositionMap.put(5,set5 ); + returnArrayList.add(graph); returnArrayList.add(decompositionMap); + + return returnArrayList; } - final protected Graph, DefaultEdge> createGraph2() - { - Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class); - - - List outerVertex1 = new ArrayList<>(); - List outerVertex2 = new ArrayList<>(); - List outerVertex3 = new ArrayList<>(); - List outerVertex4 = new ArrayList<>(); - List outerVertex5 = new ArrayList<>(); - - outerVertex1.add(2); outerVertex1.add(1); - outerVertex2.add(3); outerVertex2.add(4);outerVertex2.add(2); - outerVertex3.add(4); - outerVertex4.add(5);outerVertex4.add(4); - - outerVertex5.add(4);outerVertex5.add(6); - Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); - Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); - Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); - Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex5); - - return graph; - } @Test public void testGreedy1() + { - Graph, DefaultEdge> newGraph = createGraph1(); + List returnArrayList= createGraph1(); + Graph newGraph = (Graph) returnArrayList.get(0); + Map > newDecompositionMap = (Map>) returnArrayList.get(1); - Coloring coloring = new DecompositionTreeColour<>(newGraph).getColoring(); + Coloring coloring = new DecompositionTreeColour<>(newGraph,newDecompositionMap).getColoring(); assertEquals(3, coloring.getNumberColors()); Map colors = coloring.getColors(); - assertEquals(0, colors.get(1).intValue()); - assertEquals(1, colors.get(2).intValue()); - assertEquals(2, colors.get(3).intValue()); - assertEquals(0, colors.get(4).intValue()); - //iterate over all edges/vertices and check if the test can be done better - assertNotEquals(colors.get(1).intValue(), colors.get(2).intValue()); - } - @Test - public void testGreedy2() - { - Graph, DefaultEdge> newGraph = createGraph2(); - Coloring coloring = new DecompositionTreeColour<>(newGraph).getColoring(); - assertEquals(3, coloring.getNumberColors()); - Map colors = coloring.getColors(); - assertEquals(0, colors.get(1).intValue()); - assertEquals(1, colors.get(2).intValue()); - assertEquals(0, colors.get(3).intValue()); - assertEquals(2, colors.get(4).intValue()); - assertEquals(0, colors.get(5).intValue()); - assertEquals(0, colors.get(6).intValue()); + //iterate over all edges/vertices and check if the test can be done better + assertNotEquals(colors.get(11).intValue(), colors.get(22).intValue(), colors.get(33).intValue()); } } From 08517c2d0cb00c7f773d22aace04a6406e4ca73e Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 10 Aug 2018 17:06:19 +0200 Subject: [PATCH 127/131] Moved DecompositionTreeColour to the color package --- .../alg/color/DecompositionTreeColour.java | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java new file mode 100644 index 00000000000..fed83ac5965 --- /dev/null +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java @@ -0,0 +1,116 @@ +package org.jgrapht.alg.color; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import org.jgrapht.Graph; +import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; + +/** + * Colouring of decomposition trees (currently done for interval graphs). This algorithm iterates over lists of vertices and assigns + * the smallest colour to each of the vertices such that the no vertex in the same list has the same colour. + * + * @author Suchanda Bhattacharyya (dia007) + * + * @param The type of graph vertex + * @param The type of graph edge + */ + +public class DecompositionTreeColour implements VertexColoringAlgorithm { + + /** + * The input graph + */ + private Graph graph; + /** + * The map of the vertices in the input graph to it's interval sets + */ + private Map > decompositionMap; + + + public DecompositionTreeColour(Graph graph,Map > decompositionMap) + { + this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); + this.decompositionMap = Objects.requireNonNull(decompositionMap, "there must be some decomposition present"); + } + + + /** + * Getting the ordering for the vertices + * @return the ordering of the vertices + */ + + protected Iterable getVertexOrdering() + { + return (Iterable) graph.vertexSet(); + + + } + + /* (non-Javadoc) + * @see org.jgrapht.alg.interfaces.VertexColoringAlgorithm#getColoring() + */ + @Override + public Coloring getColoring() { + + + Map asssignedColors = new HashMap<>(); + Set used = new HashSet<>(); + Set free = new HashSet<>(); + + //self loops not allowed, repetitions of inner vertices not allowed + + + for(Integer vertex:getVertexOrdering() ) { + + //find the intervals corresponding to the vertex + //need to sort the vertices + List intervalSet = decompositionMap.get(vertex).stream().sorted().collect(Collectors.toList()); + + + for(V innerVertex : intervalSet ) { + //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour + if(asssignedColors.containsKey(innerVertex)) { + used.add(asssignedColors.get(innerVertex)); + + + } + else { + //these are the vertices without any assigned colours + free.add(innerVertex); + + } + } + + //here we assign colours to the free vertices + + for(V freeVertex: free) { + int colourCandidate = 0; + while (used.contains(colourCandidate)) { + colourCandidate++; + } + + asssignedColors.put(freeVertex,colourCandidate); + + + used.add(colourCandidate); + + + } + free.clear(); + used.clear(); + + } + + int maxColourAssigned = Collections.max(asssignedColors.values()); + + return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); + } +} + + From 1826b31dce25d0c6e489eb7466abe14b47eb2466 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 10 Aug 2018 17:42:49 +0200 Subject: [PATCH 128/131] Moved DecompositionTreeColourTest to color package --- .../color/DecompositionTreeColourTest.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java new file mode 100644 index 00000000000..e47e0f87db6 --- /dev/null +++ b/jgrapht-core/src/test/java/org/jgrapht/alg/color/DecompositionTreeColourTest.java @@ -0,0 +1,80 @@ +package org.jgrapht.alg.color; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jgrapht.Graph; +import org.jgrapht.Graphs; +import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; +import org.jgrapht.alg.interfaces.VertexColoringAlgorithm.Coloring; +import org.jgrapht.graph.DefaultEdge; +import org.jgrapht.graph.SimpleGraph; +import org.junit.Test; +/** + * Coloring tests + * + * @author Suchanda Bhattacharyya (dia007) + */ +public class DecompositionTreeColourTest { + + protected VertexColoringAlgorithm getAlgorithm(Graph graph, Map > decompositionMap) + { + return new DecompositionTreeColour<>(graph, decompositionMap); + } + //need to add more graphs + + final protected List createGraph1() + { + + Graph graph = new SimpleGraph<>(DefaultEdge.class) ; + Map > decompositionMap = new HashMap<>(); + List returnArrayList= new ArrayList<>(); + + Graphs.addEdgeWithVertices(graph, 0, 1); + Graphs.addEdgeWithVertices(graph, 1, 2); + Graphs.addEdgeWithVertices(graph, 2, 3); + Graphs.addEdgeWithVertices(graph, 3, 4); + Graphs.addEdgeWithVertices(graph, 4, 5); + + int v1 = 11,v2=22,v3=33,v4=44; + Set set0 = new HashSet<>(); + Set set1 = new HashSet<>(); + Set set2 = new HashSet<>(); + Set set3 = new HashSet<>(); + Set set4 = new HashSet<>(); + Set set5 = new HashSet<>(); + set0.add(Collections.emptySet()); set1.add(v1); set2.add(v1); set2.add(v2); set2.add(v3);set3.add(v2); set3.add(v3); set4.add(v2); set5.add(v2); set5.add(v4); + + decompositionMap.put(0,set0); decompositionMap.put(1,set1 ); decompositionMap.put(2,set2 );decompositionMap.put(3,set3 );decompositionMap.put(4,set4 );decompositionMap.put(5,set5 ); + returnArrayList.add(graph); returnArrayList.add(decompositionMap); + + return returnArrayList; + } + + + + @Test + public void testGreedy1() + + { + List returnArrayList= createGraph1(); + Graph newGraph = (Graph) returnArrayList.get(0); + Map > newDecompositionMap = (Map>) returnArrayList.get(1); + + Coloring coloring = new DecompositionTreeColour<>(newGraph,newDecompositionMap).getColoring(); + assertEquals(3, coloring.getNumberColors()); + Map colors = coloring.getColors(); + + + //iterate over all edges/vertices and check if the test can be done better + assertNotEquals(colors.get(11).intValue(), colors.get(22).intValue(), colors.get(33).intValue()); + } +} From c251b2c3511c68bb38117ca173961aa89db69a0d Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 13 Aug 2018 12:39:29 +0200 Subject: [PATCH 129/131] temporary changes --- .../alg/color/DecompositionTreeColour.java | 2 +- .../DecompositionTreeColour.java | 116 ------------------ .../alg/treedecomposition/package-info.java | 4 - .../jgrapht/alg/treedecomposition/test.java | 68 ---------- .../DecompositionTreeColourTest.java | 80 ------------ 5 files changed, 1 insertion(+), 269 deletions(-) delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java delete mode 100644 jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java delete mode 100644 jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java index fed83ac5965..32edc7bc295 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java @@ -1,6 +1,7 @@ package org.jgrapht.alg.color; import java.util.Collections; +import org.jgrapht.Graph; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -8,7 +9,6 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -import org.jgrapht.Graph; import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; /** diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java deleted file mode 100644 index 50bdd4285bd..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColour.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.jgrapht.alg.treedecomposition; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; -import org.jgrapht.Graph; -import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; - -/** - * Colouring of decomposition trees (currently done for interval graphs). This algorithm iterates over lists of vertices and assigns - * the smallest colour to each of the vertices such that the no vertex in the same list has the same colour. - * - * @author Suchanda Bhattacharyya (dia007) - * - * @param The type of graph vertex - * @param The type of graph edge - */ - -public class DecompositionTreeColour implements VertexColoringAlgorithm { - - /** - * The input graph - */ - private Graph graph; - /** - * The map of the vertices in the input graph to it's interval sets - */ - private Map > decompositionMap; - - - public DecompositionTreeColour(Graph graph,Map > decompositionMap) - { - this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); - this.decompositionMap = Objects.requireNonNull(decompositionMap, "there must be some decomposition present"); - } - - - /** - * Getting the ordering for the vertices - * @return the ordering of the vertices - */ - - protected Iterable getVertexOrdering() - { - return (Iterable) graph.vertexSet(); - - - } - - /* (non-Javadoc) - * @see org.jgrapht.alg.interfaces.VertexColoringAlgorithm#getColoring() - */ - @Override - public Coloring getColoring() { - - - Map asssignedColors = new HashMap<>(); - Set used = new HashSet<>(); - Set free = new HashSet<>(); - - //self loops not allowed, repetitions of inner vertices not allowed - - - for(Integer vertex:getVertexOrdering() ) { - - //find the intervals corresponding to the vertex - //need to sort the vertices - List intervalSet = decompositionMap.get(vertex).stream().sorted().collect(Collectors.toList()); - - - for(V innerVertex : intervalSet ) { - //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour - if(asssignedColors.containsKey(innerVertex)) { - used.add(asssignedColors.get(innerVertex)); - - - } - else { - //these are the vertices without any assigned colours - free.add(innerVertex); - - } - } - - //here we assign colours to the free vertices - - for(V freeVertex: free) { - int colourCandidate = 0; - while (used.contains(colourCandidate)) { - colourCandidate++; - } - - asssignedColors.put(freeVertex,colourCandidate); - - - used.add(colourCandidate); - - - } - free.clear(); - used.clear(); - - } - - int maxColourAssigned = Collections.max(asssignedColors.values()); - - return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); - } -} - - diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java deleted file mode 100644 index 83ec80de9ce..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Greedy colouring for decomposition trees - */ -package org.jgrapht.alg.treedecomposition; diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java b/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java deleted file mode 100644 index 964fc7aa16b..00000000000 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/treedecomposition/test.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.jgrapht.alg.treedecomposition; - - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.jgrapht.EdgeFactory; -import org.jgrapht.Graph; -import org.jgrapht.Graphs; -import org.jgrapht.graph.DefaultEdge; -import org.jgrapht.graph.SimpleGraph; - -public class test { - - - public static void main(String[] args) { - - - - Graph, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class) ; - List outerVertex1 = new ArrayList<>(); - List outerVertex2 = new ArrayList<>(); - List outerVertex3 = new ArrayList<>(); - List outerVertex4 = new ArrayList<>(); - List outerVertex5 = new ArrayList<>(); - List outerVertex6 = new ArrayList<>(); - - outerVertex1.add(1); - outerVertex2.add(1); outerVertex2.add(2);outerVertex2.add(3); - outerVertex3.add(2);outerVertex3.add(3); - outerVertex4.add(2); - outerVertex5.add(2);outerVertex5.add(4); - outerVertex6.add(null); - - Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); - Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); - Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); - Graphs.addEdgeWithVertices(graph, outerVertex4, outerVertex5); - Graphs.addEdgeWithVertices(graph, outerVertex5, outerVertex6); - - - /*List outerVertex1 = new ArrayList<>(); - List outerVertex2 = new ArrayList<>(); - List outerVertex3 = new ArrayList<>(); - List outerVertex4 = new ArrayList<>(); - List outerVertex5 = new ArrayList<>(); - - - outerVertex1.add(null); - outerVertex2.add(1); - outerVertex3.add(null); - outerVertex4.add(2); - outerVertex5.add(null); - Graphs.addEdgeWithVertices(graph, outerVertex1, outerVertex2); - Graphs.addEdgeWithVertices(graph, outerVertex2, outerVertex3); - Graphs.addEdgeWithVertices(graph, outerVertex3, outerVertex4); - Graphs.addEdgeWithVertices(graph, outerVertex4, outerVertex5); - */ - - - DecompositionTreeColour testClass = new DecompositionTreeColour(graph); - // testClass.getVertexOrdering(); //this works ok - testClass.getColoring(); - - } - -} diff --git a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java b/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java deleted file mode 100644 index 3af88f1c06e..00000000000 --- a/jgrapht-core/src/test/java/org/jgrapht/alg/treedecomposition/DecompositionTreeColourTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.jgrapht.alg.treedecomposition; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.jgrapht.Graph; -import org.jgrapht.Graphs; -import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; -import org.jgrapht.alg.interfaces.VertexColoringAlgorithm.Coloring; -import org.jgrapht.graph.DefaultEdge; -import org.jgrapht.graph.SimpleGraph; -import org.junit.Test; -/** - * Coloring tests - * - * @author Suchanda Bhattacharyya (dia007) - */ -public class DecompositionTreeColourTest { - - protected VertexColoringAlgorithm getAlgorithm(Graph graph, Map > decompositionMap) - { - return new DecompositionTreeColour<>(graph, decompositionMap); - } - //need to add more graphs - - final protected List createGraph1() - { - - Graph graph = new SimpleGraph<>(DefaultEdge.class) ; - Map > decompositionMap = new HashMap<>(); - List returnArrayList= new ArrayList<>(); - - Graphs.addEdgeWithVertices(graph, 0, 1); - Graphs.addEdgeWithVertices(graph, 1, 2); - Graphs.addEdgeWithVertices(graph, 2, 3); - Graphs.addEdgeWithVertices(graph, 3, 4); - Graphs.addEdgeWithVertices(graph, 4, 5); - - int v1 = 11,v2=22,v3=33,v4=44; - Set set0 = new HashSet<>(); - Set set1 = new HashSet<>(); - Set set2 = new HashSet<>(); - Set set3 = new HashSet<>(); - Set set4 = new HashSet<>(); - Set set5 = new HashSet<>(); - set0.add(Collections.emptySet()); set1.add(v1); set2.add(v1); set2.add(v2); set2.add(v3);set3.add(v2); set3.add(v3); set4.add(v2); set5.add(v2); set5.add(v4); - - decompositionMap.put(0,set0); decompositionMap.put(1,set1 ); decompositionMap.put(2,set2 );decompositionMap.put(3,set3 );decompositionMap.put(4,set4 );decompositionMap.put(5,set5 ); - returnArrayList.add(graph); returnArrayList.add(decompositionMap); - - return returnArrayList; - } - - - - @Test - public void testGreedy1() - - { - List returnArrayList= createGraph1(); - Graph newGraph = (Graph) returnArrayList.get(0); - Map > newDecompositionMap = (Map>) returnArrayList.get(1); - - Coloring coloring = new DecompositionTreeColour<>(newGraph,newDecompositionMap).getColoring(); - assertEquals(3, coloring.getNumberColors()); - Map colors = coloring.getColors(); - - - //iterate over all edges/vertices and check if the test can be done better - assertNotEquals(colors.get(11).intValue(), colors.get(22).intValue(), colors.get(33).intValue()); - } -} From 7c61980cd4e96291645c329e5d116007701756bb Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 14 Aug 2018 13:14:33 +0200 Subject: [PATCH 130/131] changed the tabs to spaces and added javadoc --- .../alg/color/DecompositionTreeColour.java | 149 +++++++++--------- 1 file changed, 74 insertions(+), 75 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java index 32edc7bc295..575444165e3 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java @@ -12,105 +12,104 @@ import org.jgrapht.alg.interfaces.VertexColoringAlgorithm; /** - * Colouring of decomposition trees (currently done for interval graphs). This algorithm iterates over lists of vertices and assigns - * the smallest colour to each of the vertices such that the no vertex in the same list has the same colour. + * Colouring of decomposition trees (currently done for interval graphs). This + * algorithm iterates over lists of vertices and assigns the smallest colour to + * each of the vertices such that the no vertex in the same list has the same + * colour. * * @author Suchanda Bhattacharyya (dia007) * - * @param The type of graph vertex - * @param The type of graph edge + * @param + * The type of graph vertex + * @param + * The type of graph edge */ -public class DecompositionTreeColour implements VertexColoringAlgorithm { +public class DecompositionTreeColour implements VertexColoringAlgorithm { - /** - * The input graph - */ - private Graph graph; - /** - * The map of the vertices in the input graph to it's interval sets - */ - private Map > decompositionMap; + /** + * The input graph + */ + private Graph graph; + /** + * The map of the vertices in the input graph to it's interval sets + */ + private Map> decompositionMap; + /** + * + * @param graph + * @param decompositionMap + */ + public DecompositionTreeColour(Graph graph, Map> decompositionMap) { + this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); + this.decompositionMap = Objects.requireNonNull(decompositionMap, "there must be some decomposition present"); + } - public DecompositionTreeColour(Graph graph,Map > decompositionMap) - { - this.graph = Objects.requireNonNull(graph, "Graph cannot be null"); - this.decompositionMap = Objects.requireNonNull(decompositionMap, "there must be some decomposition present"); - } + /** + * Getting the ordering for the vertices + * + * @return the ordering of the vertices + */ + protected Iterable getVertexOrdering() { + return (Iterable) graph.vertexSet(); - /** - * Getting the ordering for the vertices - * @return the ordering of the vertices - */ + } - protected Iterable getVertexOrdering() - { - return (Iterable) graph.vertexSet(); - + /* + * (non-Javadoc) + * + * @see org.jgrapht.alg.interfaces.VertexColoringAlgorithm#getColoring() + */ + @Override + public Coloring getColoring() { - } + Map asssignedColors = new HashMap<>(); + Set used = new HashSet<>(); + Set free = new HashSet<>(); - /* (non-Javadoc) - * @see org.jgrapht.alg.interfaces.VertexColoringAlgorithm#getColoring() - */ - @Override - public Coloring getColoring() { + // self loops not allowed, repetitions of inner vertices not allowed + for (Integer vertex : getVertexOrdering()) { - Map asssignedColors = new HashMap<>(); - Set used = new HashSet<>(); - Set free = new HashSet<>(); + // find the intervals corresponding to the vertex + // need to sort the vertices + List intervalSet = decompositionMap.get(vertex).stream().sorted().collect(Collectors.toList()); - //self loops not allowed, repetitions of inner vertices not allowed + for (V innerVertex : intervalSet) { + // first need to iterate over each innerVertex in the outerVertex to check that + // if there is any vertex with an already assigned colour + if (asssignedColors.containsKey(innerVertex)) { + used.add(asssignedColors.get(innerVertex)); + } else { + // these are the vertices without any assigned colours + free.add(innerVertex); - for(Integer vertex:getVertexOrdering() ) { + } + } - //find the intervals corresponding to the vertex - //need to sort the vertices - List intervalSet = decompositionMap.get(vertex).stream().sorted().collect(Collectors.toList()); - + // here we assign colours to the free vertices - for(V innerVertex : intervalSet ) { - //first need to iterate over each innerVertex in the outerVertex to check that if there is any vertex with an already assigned colour - if(asssignedColors.containsKey(innerVertex)) { - used.add(asssignedColors.get(innerVertex)); - + for (V freeVertex : free) { + int colourCandidate = 0; + while (used.contains(colourCandidate)) { + colourCandidate++; + } - } - else { - //these are the vertices without any assigned colours - free.add(innerVertex); + asssignedColors.put(freeVertex, colourCandidate); - } - } + used.add(colourCandidate); - //here we assign colours to the free vertices + } + free.clear(); + used.clear(); - for(V freeVertex: free) { - int colourCandidate = 0; - while (used.contains(colourCandidate)) { - colourCandidate++; - } + } - asssignedColors.put(freeVertex,colourCandidate); + int maxColourAssigned = Collections.max(asssignedColors.values()); - - used.add(colourCandidate); - - - } - free.clear(); - used.clear(); - - } - - int maxColourAssigned = Collections.max(asssignedColors.values()); - - return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); - } + return new ColoringImpl<>(asssignedColors, maxColourAssigned + 1); + } } - - From c57371f9416ef1a7357acf56eed376a6a8dfbc6b Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 14 Aug 2018 13:22:50 +0200 Subject: [PATCH 131/131] added javadoc --- .../java/org/jgrapht/alg/color/DecompositionTreeColour.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java index 575444165e3..1661c3e3eaf 100644 --- a/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java +++ b/jgrapht-core/src/main/java/org/jgrapht/alg/color/DecompositionTreeColour.java @@ -38,8 +38,8 @@ public class DecompositionTreeColour implements VertexColoringAlgorithm /** * - * @param graph - * @param decompositionMap + * @param graph the input graph + * @param decompositionMap the input decomposition map */ public DecompositionTreeColour(Graph graph, Map> decompositionMap) { this.graph = Objects.requireNonNull(graph, "Graph cannot be null");