Skip to content
Snippets Groups Projects
Commit 5e0b31d5 authored by Christopher Schankula's avatar Christopher Schankula :earth_africa:
Browse files

Merge branch 'KDTree' into 'TeamB'

Kd tree

See merge request schankuc/2XB3!6
parents 97555f7e 9a7aad79
No related branches found
No related tags found
No related merge requests found
package biotree;
import sort.KDT;
public class Data {
KDT data = new KDT<Integer>();
public static void initialize(Record rec) {
}
}
package sandbox;
public class Point implements Comparable<Point> {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public String toString() {
return String.format("(%d,%d)", x, y);
}
@Override
public int compareTo(Point o) {
// TODO Auto-generated method stub
return 0;
}
}
package sort;
public enum Bound {
LOWER, UPPER, LOWHIGH, ANY;
}
package sort;
public interface GeneralCompare<T> {
/**
* Compare two Comparable elements based on an arbitrary ordering definition.
* @param a1 The first value to be compared.
* @param a2 The second value to be compared
* @return Integer < 0 if a1 is less than a2, 0 if equal and > 0 if a1 is bigger than a2
*/
public int compare(Comparable<T> a1, Comparable<T> a2);
}
package sort;
public interface GeneralRange<T extends Comparable<T>> {
/**
* Compare two Comparable elements based on an arbitrary ordering definition.
* @param a1 The first value to be compared.
* @param a2 The second value to be compared
* @return Integer < 0 if a1 is less than a2, 0 if equal and > 0 if a1 is bigger than a2
*/
public int isInBounds(T a1);
}
package sort;
import sandbox.Point;
import java.util.ArrayList;
public class KDT<KeyVal extends Comparable<KeyVal>> {
Node root;
ArrayList<GeneralCompare<KeyVal>> axes;
public static void main(String[] args) {
GeneralCompare<Point> compX = (p1, p2) -> ((Point) p1).getX() - ((Point) p2).getX();
GeneralCompare<Point> compY = (p1, p2) -> ((Point) p1).getY() - ((Point) p2).getY();
//(2,3), (4,7), (5,4), (7,2), (8,1), (9,6)
//(8,1), (7,2), (2,3), (5,4), (9,6), (4,7)
Point p1 = new Point(2,3);
Point p2 = new Point(5,4);
Point p3 = new Point(9,6);
Point p4 = new Point(4,7);
Point p5 = new Point(8,1);
Point p6 = new Point(7,2);
ArrayList<GeneralCompare<Point>> axes = new ArrayList<GeneralCompare<Point>>();
axes.add(compX);
axes.add(compY);
Point[] pts = {p1, p2, p3, p4, p5, p6};
KDT<Point> kdt = new KDT<Point>(axes, pts);
System.out.println(kdt.size());
System.out.println(kdt.height());
//GeneralRange<Point> xRange = p -> 4 <= p.getX() && p.getX() <= 6;
//GeneralRange<Point> yRange = p -> 3 <= p.getY() && p.getY() <= 5;
GeneralRange<Point> xRange = p -> p.getX() < 2 ? -1 : (p.getX() > 7 ? 1 : 0);
GeneralRange<Point> yRange = p -> 0;//p.getY() < 3 ? -1 : (p.getY() > 6 ? 1 : 0);
ArrayList<GeneralRange<Point>> ranges = new ArrayList<GeneralRange<Point>>();
ranges.add(xRange);
ranges.add(yRange);
Iterable<Point> results = kdt.rangeSearch(ranges);
System.out.println("Results");
for (Point p : results) {
System.out.println(p);
}
System.out.println(kdt.toString());
}
private class Node{
private KeyVal keyval;
private Node left, right;
private int n;
public Node(KeyVal keyval, int n) {
this.keyval = keyval;
this.n = n;
}
}
/**
* Create a new KD-tree from an array of key-value paired objects.
* @param axes A sequence of k GeneralCompare functions which compare based on each of the k axes.
* For example, to order a point based on x in the first axis and y in the second, the two
* GeneralCompares should correspond to x and y respectively. The length k of this list also
* defines the number of axes contained within the tree (the number of unique values on which
* to index the data).
* @param keyvals An array of key-value pairs to be inserted into the tree initially.
*/
public KDT(ArrayList<GeneralCompare<KeyVal>> axes, Comparable<KeyVal>[] keyvals) {
this.axes = axes;
root = buildTree(keyvals, 0, keyvals.length - 1, 0);
}
private Node buildTree(Comparable<KeyVal>[] keyvals, int lo, int hi, int depth) {
if (lo > hi) return null;
int axis = depth % getK();
int mid = (lo + hi) / 2;
MergeSort.sort(keyvals, lo, hi, axes.get(axis));
KeyVal median = (KeyVal) keyvals[mid];
System.out.println(median);
//TODO: fix size
Node newNode = new Node(median, 0);
newNode.left = buildTree(keyvals, lo, mid - 1, depth + 1);
newNode.right = buildTree(keyvals, mid + 1, hi, depth + 1);
newNode.n = size(newNode.left) + size(newNode.right) + 1;
return newNode;
}
/**
* Range search by providing k GeneralRange functions.
* @param range An ArrayList sequence of k GeneralRange functions for searching on
* each of the k axes. Must equal the number of axes used in the current tree.
* @return An Iterable object of all results found within the range specified.
*/
public Iterable<KeyVal> rangeSearch(ArrayList<GeneralRange<KeyVal>> range){
ArrayList<KeyVal> result = new ArrayList<KeyVal>();
rangeSearch(root, range, result, 0);
return result;
}
private void rangeSearch(Node x, ArrayList<GeneralRange<KeyVal>> range, ArrayList<KeyVal> result, int depth) {
if (x == null) return;
int axis = depth % getK();
GeneralRange<KeyVal> rg = range.get(axis);
System.out.println("Try: " + x.keyval);
int bounds = rg.isInBounds((KeyVal) x.keyval);
if (bounds == 0) {
System.out.println(pointInside(x.keyval, range));
if (pointInside(x.keyval, range)) {
result.add(x.keyval);
}
rangeSearch(x.left, range, result, depth + 1);
rangeSearch(x.right, range, result, depth + 1);
} else if (bounds > 0) {
rangeSearch(x.left, range, result, depth + 1);
} else if (bounds < 0)
rangeSearch(x.right, range, result, depth + 1);
return;
}
private boolean pointInside(KeyVal pt, ArrayList<GeneralRange<KeyVal>> range) {
for (int i = 0; i < axes.size(); i++)
if (range.get(i).isInBounds(pt) != 0) return false;
return true;
}
public int size() {
return size(root);
}
public int height() {
return height(root);
}
private int height(Node x) {
if (x == null) return 0;
return 1 + Math.max(height(x.left), height(x.right));
}
private int size(Node x) {
if (x == null) return 0;
else return x.n;
}
/**
* Get the number of axes in this tree.
* @return The number of axes, k, in the current tree.
*/
public int getK() {
return axes.size();
}
public String toString() {
return toString(root, "");
}
private String toString(Node x, String depth) {
if (x == null) return depth + "null\n";
String result = "";
result += depth + x.keyval.toString() + "\n";
result += toString(x.left, depth + " ");
result += toString(x.right, depth + " ");
return result;
}
}
......@@ -37,7 +37,7 @@ public class MergeSort{
int mid = lo + (n/2);
// Fill auxiliary array
System.out.println("lo, mid, hi: " + lo + ", " + mid + ", " + hi);
//System.out.println("lo, mid, hi: " + lo + ", " + mid + ", " + hi);
for(int k = lo; k <= hi; k++){
aux[k] = x[k];
......
package sort;
public class Range<Key extends Comparable<Key>> {
private final Bound boundType;
private final Key lower;
private final Key upper;
public Range(Bound bt) throws Exception {
if (bt == Bound.ANY) {
boundType = bt;
lower = null;
upper = null;
}
else
throw new Exception("Must provide ANY bound.");
}
public Range(Bound bt, Key upperOrLower) throws Exception {
if (bt == Bound.UPPER) {
upper = upperOrLower;
lower = null;
} else if (bt == Bound.LOWER) {
upper = upperOrLower;
lower = null;
}
else
throw new Exception("Must provide UPPER OR LOWER bound.");
boundType = bt;
}
public Range(Bound bt, Key lower, Key upper) throws Exception {
if (bt == Bound.LOWHIGH) {
this.lower = lower;
this.upper = upper;
} else
throw new Exception("Must provide LOWHIGH bound.");
this.boundType = bt;
}
public <T> boolean inBounds(T key) {
if (boundType == Bound.ANY) return true;
else if (boundType == Bound.LOWER) return gc.compare(lower, key) <= 0;
else if (boundType == Bound.UPPER) return gc.compare(upper, key) >= 0;
else return gc.compare(lower, key) <= 0 && gc.compare(upper, key) >= 0;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment