Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
First commit
- Loading branch information
0 parents
commit a6a5dea
Showing
13 changed files
with
400,919 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import java.io.File; | ||
import java.io.FileNotFoundException; | ||
import java.util.Comparator; | ||
import java.util.Scanner; | ||
|
||
public class Main { | ||
public static void main(String[] args) { | ||
runTests(); | ||
} | ||
|
||
/** | ||
* | ||
*/ | ||
public static void runTests() { | ||
System.out.println("For 1,000 points: "); | ||
PointList p1 = readFile(1000); | ||
runClosetDistanceAlgorithm(p1); | ||
testBrute(p1); | ||
System.out.println(); | ||
|
||
System.out.println("For 10,000 points: "); | ||
PointList p2 = readFile(10000); | ||
runClosetDistanceAlgorithm(p2); | ||
testBrute(p2); | ||
System.out.println(); | ||
|
||
System.out.println("For 100,000 points: "); | ||
PointList p3 = readFile(100000); | ||
runClosetDistanceAlgorithm(p3); | ||
testBrute(p3); | ||
System.out.println("Tests completed"); | ||
|
||
} | ||
|
||
/** | ||
* Reads the CSV file, creating a MyPoint instance for each coordinate it reads and adding each of | ||
* these MyPoints to a PointList | ||
* @return PointList with all points read | ||
*/ | ||
public static PointList readFile() { | ||
PointList plist = new PointList(); | ||
|
||
String csvFile = "src/xy.csv"; | ||
Scanner scanner = null; | ||
String csvRegex = ","; | ||
|
||
try { | ||
scanner = new Scanner(new File(csvFile)); | ||
|
||
// Read over first line | ||
scanner.nextLine(); | ||
|
||
// Read the next line while there is a next line and create new MyPoint objects for each | ||
while(scanner.hasNext()) { | ||
String s = scanner.nextLine(); | ||
String[] values = s.split(csvRegex); | ||
double xVal = Double.parseDouble(values[0]); | ||
double yVal = Double.parseDouble(values[1]); | ||
MyPoint p = new MyPoint(xVal, yVal); | ||
plist.add(p); | ||
} | ||
|
||
|
||
} catch (FileNotFoundException e) { | ||
e.printStackTrace(); | ||
} | ||
return plist; | ||
} | ||
|
||
/** | ||
* Reads the CSV files to a desired depth. Used mostly for comparing run times of the 2 algorithms used | ||
* @param depth at which file reading will stop | ||
* @return PointList with all points up to depth read | ||
*/ | ||
public static PointList readFile(int depth) { | ||
PointList plist = new PointList(); | ||
|
||
String csvFile = "src/xy.csv"; | ||
Scanner scanner = null; | ||
String csvRegex = ","; | ||
|
||
try { | ||
scanner = new Scanner(new File(csvFile)); | ||
|
||
// Read over first line | ||
scanner.nextLine(); | ||
|
||
// Read the next line until specified depth is reached | ||
for(int i=0; i<depth; i++) { | ||
String s = scanner.nextLine(); | ||
String[] values = s.split(csvRegex); | ||
double xVal = Double.parseDouble(values[0]); | ||
double yVal = Double.parseDouble(values[1]); | ||
MyPoint p = new MyPoint(xVal, yVal); | ||
plist.add(p); | ||
} | ||
|
||
} catch (FileNotFoundException e) { | ||
e.printStackTrace(); | ||
} | ||
return plist; | ||
} | ||
|
||
/** | ||
* Runs the brute force algorithm and prints the execution time | ||
* @param plist to be tested | ||
*/ | ||
public static void testBrute(PointList plist) { | ||
long tStart = System.currentTimeMillis(); | ||
System.out.println("Result: " + PointList.getClosestDistanceBrute(plist)); | ||
long tEnd = System.currentTimeMillis(); | ||
long tDelta = tEnd - tStart; | ||
double elapsedSeconds = tDelta / 1000.0; | ||
System.out.println("Brute force takes " + elapsedSeconds + " seconds"); | ||
} | ||
|
||
/** | ||
* Calls parent method for divide and conquer method and prints execution time | ||
* @param plist to be tested | ||
*/ | ||
public static void runClosetDistanceAlgorithm(PointList plist) { | ||
long tStart = System.currentTimeMillis(); | ||
System.out.println("Result: " + PointList.closestDistance(plist)); | ||
long tEnd = System.currentTimeMillis(); | ||
long tDelta = tEnd - tStart; | ||
double elapsedSeconds = tDelta / 1000.0; | ||
System.out.println("Divide and conquer algorithm takes " + elapsedSeconds + " seconds."); | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import java.awt.geom.Point2D; | ||
|
||
public class MyPoint extends Point2D.Double | ||
{ | ||
private static final long serialVersionUID = 1L; | ||
|
||
// MyPoint constructor | ||
public MyPoint(double x, double y) | ||
{ | ||
super(x,y); | ||
} | ||
|
||
/** | ||
* Uses method in Double to compute the distance | ||
* @param p | ||
* @return | ||
*/ | ||
public double computeDistanceBetween(MyPoint p) | ||
{ | ||
double distance = Double.distance(this.getX(), this.getY(), p.getX(), p.getY()); | ||
return distance; | ||
} | ||
|
||
/** | ||
* Overrides the Point2D.Double toString to better display MyPoints | ||
*/ | ||
@Override | ||
public String toString() | ||
{ | ||
return "(" + this.x + "," + this.y + ")"; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
|
||
import java.util.ArrayList; | ||
import java.util.Comparator; | ||
|
||
public class PointList extends ArrayList<MyPoint> | ||
{ | ||
private static final long serialVersionUID = 1L; | ||
private static final int _sigmaAreaStop = 15; | ||
private static final int _smallestSize = 3; | ||
|
||
/** | ||
* Builds an empty PointList by initializing the ArrayList that it wraps | ||
*/ | ||
public PointList() { | ||
super(); | ||
} | ||
|
||
/** | ||
* @param size of the PointList | ||
*/ | ||
public PointList(int size) { | ||
super(size); | ||
} | ||
|
||
/** | ||
* Prints all points in the PointList | ||
*/ | ||
public void printList() { | ||
for(int i=0; i<this.size(); i++) { | ||
System.out.println(this.get(i).toString()); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Uses brute force algorithm to find closest pair of points in a list of points | ||
* | ||
* @param PointList p | ||
* @return minimum distance of the points in p | ||
*/ | ||
public static double getClosestDistanceBrute(PointList p) { | ||
double min = p.get(0).computeDistanceBetween(p.get(1)); | ||
for(int i=0; i<p.size(); i++) { | ||
for(int j=i+1; j<p.size(); j++) { | ||
double currentDistance = p.get(i).computeDistanceBetween(p.get(j)); | ||
if(currentDistance<min) { | ||
min = currentDistance; | ||
} | ||
} | ||
} | ||
return min; | ||
} | ||
|
||
/** | ||
* Parent method for the divide and conquer closest pair of points algorithm | ||
* @param pointlist | ||
* @return distance between the closest pair of points | ||
*/ | ||
public static double closestDistance(PointList p) { | ||
PointList px = sortByX(p); | ||
PointList py = sortByY(p); | ||
return closestPairRec(px, py); | ||
} | ||
|
||
/** | ||
* Recursive divide and conquer algorithm that finds the closest pair of sorted points and | ||
* returns the distance between those points | ||
* @param PointList sorted by x-coordinate | ||
* @param PointList sorted by y-coordinate | ||
* @return distance between closest pair of points | ||
*/ | ||
public static double closestPairRec(PointList px, PointList py) | ||
{ | ||
if(px.size() <= _smallestSize && py.size() <= _smallestSize) { | ||
return Math.min(getClosestDistanceBrute(px), getClosestDistanceBrute(py)); | ||
} | ||
int mid = (int) Math.floor(px.size() / 2); | ||
PointList qx = constructQ(px, mid); | ||
PointList rx = constructR(px, mid); | ||
PointList qy = constructQ(py, mid); | ||
PointList ry = constructR(py, mid); | ||
double qMin = closestPairRec(qx, qy); | ||
double rMin = closestPairRec(rx, ry); | ||
double delta = Math.min(qMin, rMin); | ||
double maxXinQCoord = qx.get(qx.size()-1).getX(); | ||
PointList sy = constructSy(maxXinQCoord, delta, py); | ||
if(sy.isEmpty() || sy.size()==1) { | ||
return delta; | ||
} else { | ||
double nearLineMin = getNearLineMin(sy, delta); | ||
return Math.min(delta, nearLineMin); | ||
} | ||
|
||
} | ||
|
||
|
||
/** | ||
* Searches for the minimum distance in a PointList by searching the next 15 | ||
* elements of each of the elements. Uses brute force search | ||
* | ||
* @param y sorted PointList | ||
* @return minimum distance in the searched space | ||
*/ | ||
private static double getNearLineMin(PointList sy, double delta) { | ||
double currentMin = delta; | ||
for(int i=0; i<sy.size(); i++) { | ||
MyPoint current = sy.get(i); | ||
// Get stopping point 15 nodes away | ||
int k = i + _sigmaAreaStop; | ||
for(int j=i+1; i<k; j++) { | ||
if(j<=sy.size()) { | ||
break; | ||
} | ||
double distance = current.computeDistanceBetween(sy.get(j)); | ||
if(distance < currentMin) { | ||
currentMin = distance; | ||
} | ||
} | ||
} | ||
return currentMin; | ||
} | ||
|
||
/** | ||
* Adds all points within a distance delta from the middle line L | ||
* | ||
* @param double midLineCoord | ||
* @param double delta | ||
* @param PointList sorted by y-coordinate | ||
* @return y-coordinate with all points within delta from line L | ||
*/ | ||
private static PointList constructSy(double midLineCoord, double delta, PointList py) | ||
{ | ||
PointList sy = new PointList(); | ||
double min = midLineCoord - delta; | ||
double max = midLineCoord + delta; | ||
for(int i=0; i<py.size(); i++) { | ||
MyPoint current = py.get(i); | ||
double currentXcoord = py.get(i).getX(); | ||
if(currentXcoord>min && currentXcoord<max) { | ||
sy.add(current); | ||
} | ||
} | ||
return sy; | ||
} | ||
|
||
/** | ||
* Returns list of points in Q (left of line L) and returns a list sorted in the same order it came in | ||
* @param Point list to be split | ||
* @param median index | ||
* @return PointList of points left of L sorted in same order it came in as | ||
*/ | ||
private static PointList constructQ(PointList p, int mid) { | ||
PointList q = new PointList(); | ||
for(int i=0; i<mid; i++) { | ||
q.add(p.get(i)); | ||
} | ||
return q; | ||
} | ||
|
||
/** | ||
* Returns list of points in R (right of line L) and returns a list sorted in the same order it came in | ||
* @param Point list to be split, median location | ||
* @return PointList of points right of L sorted in same order it came in as | ||
*/ | ||
private static PointList constructR(PointList p, int mid) { | ||
PointList r = new PointList(); | ||
for(int i=mid; i<p.size(); i++) { | ||
r.add(p.get(i)); | ||
} | ||
return r; | ||
} | ||
|
||
/** | ||
* Sorts the given PointList by from smallest to largest x-coordinate | ||
* @param PointList to be sorted | ||
* @return PointList sorted by x-coordinate | ||
*/ | ||
private static PointList sortByX(PointList p) { | ||
PointList newP = new PointList(p.size()); | ||
for(int i=0; i<p.size(); i++) { | ||
newP.add(p.get(i)); | ||
} | ||
newP.sort(new Comparator<MyPoint>() { | ||
@Override | ||
public int compare(MyPoint p1, MyPoint p2) { | ||
if (p1.getX() < p2.getX()) return -1; | ||
if (p1.getX() > p2.getX()) return 1; | ||
return 0; | ||
} | ||
}); | ||
return newP; | ||
} | ||
|
||
/** | ||
* Sorts the given PointList by from smallest to largest y-coordinate | ||
* @param PointList to be sorted | ||
* @return PointList sorted by y-coordinate | ||
*/ | ||
private static PointList sortByY(PointList p) { | ||
PointList newP = new PointList(p.size()); | ||
for(int i=0; i<p.size(); i++) { | ||
newP.add(p.get(i)); | ||
} | ||
newP.sort(new Comparator<MyPoint>() { | ||
@Override | ||
public int compare(MyPoint p1, MyPoint p2) { | ||
if (p1.getY() < p2.getY()) return -1; | ||
if (p1.getY() > p2.getY()) return 1; | ||
return 0; | ||
} | ||
}); | ||
return newP; | ||
} | ||
|
||
|
||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.