Brute Force out of memory space - java

I'm busy creating a brute force TSP algorithm, the program currently works and calculates the shortest possible route I input. Sadly the maximum amount of nodes I can use is 10, this is because whenever I go higher I get: "Java.lang.OutofMemoryError: Java heap space". I've already been trying to optimize the code but the result has been negligible. How can I further optimize my code so I can use more nodes while running my algorithm?
This is my code:
import com.sybrand.TSP.*;
import java.util.*;
public class BruteForce extends TSP_Algorithm {
private ArrayList<Coordinate> sortedCoords = new ArrayList<>();
ArrayList<Coordinate> coords = new ArrayList<>();
ArrayList<Coordinate> shortestRoute;
public BruteForce(ArrayList<Coordinate> coords) {
sortedCoords.addAll(coords);
permutation(sortedCoords);
}
public void permutation(ArrayList<Coordinate> nums) {
List<List<Coordinate>> accum = new ArrayList<>();
permutation(accum, Collections.emptyList(), nums);
float shortestDistance = 0.0f;
for (List<Coordinate> routeOption: accum) {
Path calcDistance = new Path((ArrayList<Coordinate>) routeOption);
if (shortestDistance == 0.0f || calcDistance.getDistance() < shortestDistance) {
shortestDistance = calcDistance.getDistance();
this.shortestRoute = (ArrayList<Coordinate>) routeOption;
}
}
}
private static void permutation(List<List<Coordinate>> accum, List<Coordinate> prefix, List<Coordinate> nums) {
int n = nums.size();
if (n == 0) {
accum.add(prefix);
} else {
for (int i = 0; i < n; ++i) {
List<Coordinate> newPrefix = new ArrayList<>(prefix);
newPrefix.add(nums.get(i));
List<Coordinate> numsLeft = new ArrayList<>(nums);
numsLeft.remove(i);
permutation(accum, newPrefix, numsLeft);
}
}
}
public ArrayList<Coordinate> getSortedCoordinates() {
return shortestRoute;
}
}

Related

How to overcome this stack overflow issue when finding SCCs?

This is the code I wrote to find SCCs usigng Kosaraju's Two-Passed Algorithm. When I run the main method, I get a StackOverFlowError on SCC.revDFS. How can I avoid the stack overflow error when having a large amount of recursive calls?
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
import java.util.Scanner;
public class SCC {
int n = 875714;
Map<Integer,List<Integer>> adjList;
Map<Integer,List<Integer>> adjListRev;
int[] ft;
int t;
int s;
boolean[] marked;
int[] leaders;
public SCC() {
init();
t = 0;
s = 0;
marked = new boolean[n + 1];
leaders = new int[n + 1];
}
void init() {
adjList = new HashMap<Integer,List<Integer>>();
adjListRev = new HashMap<Integer,List<Integer>>();
ft = new int[n + 1];
List<Integer> adj;
try {
Scanner scanner = new Scanner (new InputStreamReader(this.getClass().
getClassLoader().getResourceAsStream("SCC.txt")));
while(scanner.hasNextLine()) {
String s = scanner.nextLine().trim();
String[] num = s.split(" ");
if (!adjList.containsKey(Integer.parseInt(num[0]))) {
adjList.put(Integer.parseInt(num[0]), new ArrayList<Integer>());
}
adj = adjList.get(Integer.parseInt(num[0]));
adj.add(Integer.parseInt(num[1]));
adjList.put(Integer.parseInt(num[0]), adj);
if (!adjListRev.containsKey(Integer.parseInt(num[1]))) {
adjListRev.put(Integer.parseInt(num[1]), new ArrayList<Integer>());
}
adj = adjListRev.get(Integer.parseInt(num[1]));
adj.add(Integer.parseInt(num[0]));
adjListRev.put(Integer.parseInt(num[1]), adj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void DFS_Loop() {
for (int i = 1; i < n + 1; i++) {
marked[i] = false;
}
for (int i = n; i > 0; i--) {
if (!marked[i]) {
revDFS(i);
}
}
for (int i = 1; i < n + 1; i++) {
marked[i] = false;
leaders[i] = 0;
}
for (int i = n; i > 0; i--) {
if (!marked[ft[i]]) {
s = ft[i];
DFS(ft[i]);
}
}
}
public void revDFS(int i) {
marked[i] = true;
List<Integer> edges = adjListRev.get(i);
if (edges != null) {
for (int j: edges) {
if (!marked[j]) {
revDFS(j);
}
}
}
t += 1;
ft[t] = i;
}
public void DFS(int i) {
marked[i] = true;
leaders[s] += 1;
List<Integer> edges = adjList.get(i);
if (edges != null) {
for (int j: edges) {
if (!marked[j]) {
DFS(j);
}
}
}
}
public static void main(String[] args) {
SCC scc = new SCC();
scc.DFS_Loop();
Arrays.sort(scc.leaders);
for (int i = scc.n; i < scc.n - 5; i--) {
System.out.println(scc.leaders[i]);
}
}
}
Maybe you can try to convert the logic to iterative approach. Also, do check if you have base and edge cases handled properly.
The basic idea for converting a recursive function into an iterative function is that a recursive function consumes arguments from a stack.
So you can create a stack and push the values into it and then consume them in a loop.
public void _revDFS(int _i) {
LinkedList<Integer> stack = new LinkedList<>();
stack.push(_i);
while(!stack.isEmpty()){
int i = stack.pop();
marked[i] = true;
List<Integer> edges = adjListRev.get(i);
if (edges != null) {
for (int j: edges) {
if (!marked[j]) {
stack.push(j);
//revDFS(j);
}
}
}
t += 1;
ft[t] = i;
}
}
I can't really test it to see if I made a mistake of some kind and revDFS is a function with a lot of side effect and it does not return a value, so is a bit difficult to reason with it.
But the gist is that instead of calling the function itself you can just push the edge indexes onto the stack and then consume them.
The child edges will be processed in reverse order so if you want to keep the same order of processing of the original you should read the edges in reverse order :
ListIterator<Integer> li = edges.listIterator(edges.size());
while(li.hasPrevious()){
int j = li.previous();
if (!marked[j]) {
stack.push(j);
//revDFS(j);
}
}
you have implemented your Dfs function recursively which causes "stack overflow". To overcome this issue you need to implement it using stack data structure.
see link bellow for more motivations
https://github.com/sinamalakouti/MyFavoriteAlgorithmProblems

Sorting arraylist with mergesort vs custom sort

I am writing a program which has to be able to sort up to 1 billion random Squares. I wrote a small example program below that creates a random ArrayList of Squares and then sorts it with two different methods.
When I was looking for an efficient method of sorting I found that using a Merge Sort was meant to be the most efficient/quickest. However, when comparing a merge sort to a custom sort (don't know if this sort of sort has a name) which I wrote I found the sort I wrote was more efficient.
The output I got from my program was
Time in nanoseconds for comparator sort: 2346757466
Time in nanoseconds for merge sort: 24156585699
Standard Sort is faster
So why is the sort I wrote so much quicker than a merge sort?
Can either of the used sorts be improved to make a faster, more efficient sort?
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Objects;
public class SortSquares {
public void run() {
ArrayList<Square> list = new ArrayList<Square>();
SecureRandom rand = new SecureRandom();
int randSize = 10;
for(int i = 1; i <= 10000000; i++)
list.add(new Square(i + rand.nextInt(randSize), i + rand.nextInt(randSize)));
//Create shallow copies to allow for timing
ArrayList<Square> comp = new ArrayList<Square>(list);
ArrayList<Square> merge = new ArrayList<Square>(list);
long startTime = System.nanoTime();
comp.sort(new SquareSort());
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println("Time in nanoseconds for comparator sort: " + duration);
long startTime1 = System.nanoTime();
merge = mergeSort(merge);
long endTime1 = System.nanoTime();
long duration1 = (endTime1 - startTime1);
System.out.println("Time in nanoseconds for merge sort: " + duration1);
if(duration < duration1)
System.out.println("Standard Sort is faster");
else if(duration == duration1)
System.out.println("The sorts are the same");
else
System.out.println("Merge Sort is faster");
}
private class SquareSort implements Comparator<Square> {
#Override
public int compare(Square s1, Square s2) {
if(s1.getLocation()[0] > s2.getLocation()[0]) {
return 1;
} else if(s1.getLocation()[0] == s2.getLocation()[0]) {
if(s1.getLocation()[1] > s2.getLocation()[1]) {
return 1;
} else if(s1.getLocation()[1] == s2.getLocation()[1]) {
return 0;
} else {
return -1;
}
} else {
return -1;
}
}
}
public ArrayList<Square> mergeSort(ArrayList<Square> whole) {
ArrayList<Square> left = new ArrayList<Square>();
ArrayList<Square> right = new ArrayList<Square>();
int center;
if (whole.size() <= 1) {
return whole;
} else {
center = whole.size()/2;
for (int i = 0; i < center; i++) {
left.add(whole.get(i));
}
for (int i = center; i < whole.size(); i++) {
right.add(whole.get(i));
}
left = mergeSort(left);
right = mergeSort(right);
merge(left, right, whole);
}
return whole;
}
private void merge(ArrayList<Square> left, ArrayList<Square> right, ArrayList<Square> whole) {
int leftIndex = 0;
int rightIndex = 0;
int wholeIndex = 0;
while (leftIndex < left.size() && rightIndex < right.size()) {
if ((left.get(leftIndex).compareTo(right.get(rightIndex))) < 0) {
whole.set(wholeIndex, left.get(leftIndex));
leftIndex++;
} else {
whole.set(wholeIndex, right.get(rightIndex));
rightIndex++;
}
wholeIndex++;
}
ArrayList<Square> rest;
int restIndex;
if (leftIndex >= left.size()) {
rest = right;
restIndex = rightIndex;
} else {
rest = left;
restIndex = leftIndex;
}
for (int i = restIndex; i < rest.size(); i++) {
whole.set(wholeIndex, rest.get(i));
wholeIndex++;
}
}
private class Square {
private int[] location = new int[2];
public Square(int x, int y) {
location[0] = x;
location[1] = y;
}
public int[] getLocation() {
return location;
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Square)
if(getLocation()[0] == ((Square) obj).getLocation()[0] &&
getLocation()[1] == ((Square) obj).getLocation()[1])
return true;
return false;
}
#Override
public int hashCode() {
return Objects.hash(getLocation()[0], getLocation()[1]);
}
public int compareTo(Square arg0) {
if(getLocation()[0] > arg0.getLocation()[0]) {
return 1;
} else if(getLocation()[0] == arg0.getLocation()[0]) {
if(getLocation()[1] > arg0.getLocation()[1]) {
return 1;
} else if(getLocation()[1] == arg0.getLocation()[1]) {
return 0;
} else {
return -1;
}
} else {
return -1;
}
}
}
public static void main(String[] args) {
SortSquares e = new SortSquares();
e.run();
}
}
You can use java.util.Collections.sort( List list ) method from jdk. As mentioned above it uses merge sort with complexity O(nlogn).
In order to measure the performance of your implementation and compared it against other implementation I would suggest to use jmh http://openjdk.java.net/projects/code-tools/jmh/. Please find below a short example.
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.*;
import java.util.concurrent.TimeUnit;
#BenchmarkMode( Mode.AverageTime )
#OutputTimeUnit( TimeUnit.NANOSECONDS )
#State( Scope.Benchmark )
#Warmup( iterations = 5)
#Measurement( iterations = 5 )
#Fork( value = 1)
public class SortingPerformanceBenchmark
{
private final int[] dataArray = new int[10_000_000];
List<Integer> arrayList;
#Setup
public void load() {
Random rand = new Random();
for (int i = 0; i < dataArray.length; ++i) {
dataArray[i] = rand.nextInt();
}
}
#Benchmark
public List<Integer> Benchmark_SortObjects() {
arrayList = new ArrayList( Arrays.asList( dataArray ) );
Collections.sort( arrayList );
return arrayList;
}
public static void main(String... args) throws Exception {
Options opts = new OptionsBuilder()
.include(SortingPerformanceBenchmark.class.getSimpleName())
.build();
new Runner( opts).run();
}
}
The opposite is true: the standard method is much faster.
First, you create two arrays in each call to the recursive function mergeSort. The standard one probably merges the elements inplace in the original array, and use indices to the begin and the end of a range.
Second, the standard method can start new threads on multicore machines.
Considering algorithms It depends largely on the data.
Supposedly your sort method is quicksort.
You have O(n2) worst-case runtime and O(nlogn) average case runtime.
Mergesort is always O(n log n). This means stability. That's why it was chosen for sorting for the java collections.
Both sort and the mergesort you implemented is the same algorithm (sort on java collections is based on merge sort). You need to run the same code many times and warm up your jvm first to have more reliable results.
Somehow you can ensure that your custom mergesort is efficient and make comparisons with the collections one.
In any case you don't have to implement you own merge sort for something simple.

Number of Swappings/DataMovement in QuickSort Using Recursion

I can't seem to get how to find the number of dataMovements/Swappings in this code. Will there even be swappings/dataMovements in this Recursion Code ? 0_o and
what would be it's memory space requirement ?
package skirmish;
public class QuickSort
{
public static int countComparisons = 0;
public static int countSwappings = 0;
public LinkedList qSort(LinkedList l)
{
if(l.count() <= 1)
return l;
int p = l.peekStart();
l.removeFromStart();
LinkedList s = new LinkedList();
LinkedList g = new LinkedList();
while(!l.isEmpty())
{
countComparisons++;
if(l.peekStart() < p)
s.addAtEnd(l.peekStart());
else
g.addAtEnd(l.peekStart());
l.removeFromStart();
}
s = qSort(s);
g = qSort(g);
s.addAtEnd(p);
countSwappings++;
while(!g.isEmpty())
{
s.addAtEnd(g.peekStart());
g.removeFromStart();
countSwappings++;
}
return s;
}
}

Find the minimum distance beween 2 nodes

Can anyone help me figure it out how to solve my problem. I need to find the shortest path between 2 given nodes. So far I have managed to save all posible paths in a list, and now I'm trying to find the minimal distance.
here is my code:
public class A {
private static int[][] adjacency = new int [6][6];
static int n = 6;
private static final int START = 1;
private static final int END = 4;
private Map<Integer, LinkedHashSet<Integer>> map = new HashMap();
private Map<Integer, List<Integer>> pathsFound = new HashMap();
public void addEdge(int node1, int node2) {
LinkedHashSet<Integer> adjacent = map.get(node1);
if(adjacent==null) {
adjacent = new LinkedHashSet();
map.put(node1, adjacent);
}
adjacent.add(node2);
}
public LinkedList<Integer> adjacentNodes(Integer last) {
LinkedHashSet<Integer> adjacent = map.get(last);
if(adjacent==null) {
return new LinkedList();
}
return new LinkedList<Integer>(adjacent);
}
public static void main(String[] args) {
LinkedList<Integer> visited = new LinkedList<Integer>();
visited.add(START);
A graph = new A();
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
adjacency[i][j] = 0;
adjacency[0][1] = 1;
adjacency[0][2] = 2;
adjacency[1][0] = 1;
adjacency[1][3] = 5;
adjacency[1][4] = 9;
adjacency[1][5] = 6;
adjacency[2][0] = 2;
adjacency[2][4] = 7;
adjacency[2][5] = 2;
adjacency[3][1] = 5;
adjacency[4][1] = 9;
adjacency[4][2] = 7;
adjacency[4][5] = 1;
adjacency[5][1] = 6;
adjacency[5][2] = 2;
adjacency[5][4] = 1;
graph.addEdge(0,1);
graph.addEdge(0,2);
graph.addEdge(1,0);
graph.addEdge(1,3);
graph.addEdge(1,4);
graph.addEdge(1,5);
graph.addEdge(2,0);
graph.addEdge(2,4);
graph.addEdge(2,5);
graph.addEdge(3,1);
graph.addEdge(4,1);
graph.addEdge(4,2);
graph.addEdge(4,5);
graph.addEdge(5,1);
graph.addEdge(5,2);
graph.addEdge(5,4);
graph.breadthFirst(visited);
}
public void breadthFirst(LinkedList<Integer> visited) {
LinkedList<Integer> nodes = adjacentNodes(visited.getLast());
List<List<Integer>> allPaths = new ArrayList<List<Integer>>();
List<Integer> distances = new ArrayList<Integer>();
for (int node : nodes) {
if (visited.contains(node))
continue;
if (node == END) {
visited.add(node);
List<Integer> path = getPath(visited);
System.out.println(path);
??allPaths.add(path);
visited.removeLast();
break;
}
}
for (int node : nodes) {
if (visited.contains(node) || node == END)
continue;
visited.addLast(node);
breadthFirst(visited);
visited.removeLast();
}
System.out.println(allPaths.get(0));
}
public static List<Integer> getPath(LinkedList<Integer> visited) {
List<Integer> path = new ArrayList<Integer>();
for (int node : visited)
path.add(node);
return path;
}
}
If I do like this System.out.println(path); it prints the path, which means that the function getPath() works.
But when I want to put this path in a list : allPaths.add(path); something goes wrong, because when I call after the for loop end System.out.println(allPaths.get(0)); I get an IndexOutOfBoundException. I really don't understand why my allPaths list is empty...
Why don't you iterate with a foreach ?
for (int number : arrlist) {
System.out.println("Number = " + number);
}
Are you perhaps invoking the last snippet (in your question) before you have filled in the distances collection? You need to invoke it afterwards, not before.
[Aside: In the future, if you have an exception, you really need to provide the exception message and stack trace. Makes helping you much easier...]

Collections.sort compile error - incompatible types

I have been developing an implementation of the neighbourhood algorithm in Java for a physics project I am working on. I'm brand new to Java so I apologize for any idiocy that results.
I have been getting the error
''
incompatible types
found : void
required: java.util.List<VoronoiPoint>
'' on line 22 from the Java compiler in attempting to compile the program shown below. I cannot figure out why the variable ''thelist'' somehow turns into a void when I declared it to be of type List<VoronoiPoint>. If anybody can explain to me what is going on it would be much appreciated!
import java.lang.Double;
import java.util.*;
public class VoronoiTiling
{
public static void main(String args[])
{
Integer n = 10; //Number of dimensions of model parameter space
Integer ns = 20; //Number of points per iteration
Integer nr = 4; //Number of cells to populate
Integer iterations = 5; //Number of iterations
List<VoronoiPoint> thelist = VoronoiList.startlist(ns,n);
//System.out.println(thelist);
//System.out.println(thelist.get(1).misfit);
for (Integer i=0 ; i<thelist.size() ; i++)
{
thelist.get(i).setmisfit();
}
List<VoronoiPoint> orderedlist = Collections.sort(thelist);
Double distance = EuclidianDistance((thelist.get(1)).location,(thelist.get(2)).location);
System.out.println(distance);
}
public static Double EuclidianDistance(Double[] point1, Double[] point2)
{
Double distance=0.0;
for (int i = 0; i < point1.length; i++)
{
distance = distance + Math.pow((point1[i]-point2[i]),2);
}
return Math.sqrt(distance);
}
}
The other classes I used are here:
The VoronoiList class:
import java.util.*;
public class VoronoiList
{
public static List<VoronoiPoint> startlist(Integer ns, Integer n)
{
List<VoronoiPoint> thestartlist = new ArrayList<VoronoiPoint>();
for (int i = 0; i < ns; i++)
{
thestartlist.add(new VoronoiPoint(0.,n));
}
return thestartlist;
}
}
The VoronoiPoint class:
import java.util.Random;
public class VoronoiPoint implements Comparable<VoronoiPoint>
{
Double[] location;
private Random generator = new Random();
Double misfit = -1.;
//***************************************************************
public VoronoiPoint(Double misfit, Integer n)
{
location = new Double[n];
ParameterBoundaries boundaries = new ParameterBoundaries(n);
for(int i = 0; i < n; i++)
{
location[i] = boundaries.getboundaries(2*i)+2*generator.nextDouble();
}
}
//***************************************************************
//public Double[] getlocation()
//{
//return location;
//}
public void setlocationi(Integer i, Double j)
{
location[i] = j;
}
//***************************************************************
public void setmisfit()
{
Integer n = location.length;
Double tempmisfit = 0.0;
for(Integer i = 0; i < n; i++)
{
tempmisfit = tempmisfit + Math.pow((location[i]),2);
}
misfit = Math.sqrt(tempmisfit); // Temporarily just distance to centre
}
//public Double getmisfit()
//{
//return misfit;
//}
public int compareTo(VoronoiPoint b)
{
if (this.misfit<b.misfit) return -1;
else if (this.misfit==b.misfit) return 0;
return 1;
}
}
And the parameter boundaries class:
public class ParameterBoundaries
{
private Double[] boundaries; /*Set to 2n where n is dimensions of parameter space,
* it just makes it easier*/
public ParameterBoundaries(Integer n)
{
boundaries = new Double[2*n];
for(Integer i = 0; i<n; i++)
{
boundaries[2*i] = -1.0;
boundaries[2*i+1] = 1.0;
}
}
public Double getboundaries(Integer i)
{
return boundaries[i];
}
}
Collections.sort(..) sorts the original list. It doesn't return a new list. (Its return type is void)
Your code is wrong. Collections.sort() is an in-place sort function; it modifies the given list argument and returns nothing (void).

Categories

Resources