I started writing some code today to test some different solutions to the traveling salesman problem. I have run some tests for the random algorithm and the nearest neighbor algorithm, however, I am struggling with the brute force method.
What my program does is ask the user how many cities they will add. It then asks them to input the cities name followed by their longitude and latitude. I have created a method to then generate a 2-dimensional array in which the distances between all cities are stored.
What I want my brute force algorithm to do is calculate the distance between all combinations of cities and at the end output the shortest distance.
For example:
3 cities are entered(New York, Paris, Shanghai)
The distances between them is then stored.
[0.0, 5834.0, 11851.0]
[5834.0, 0.0, 9257.0]
[11851.0, 9257.0, 0.0]
Now I want to work out all the possible combinations and their total distance:
NY-P-S-NY
NY-S-P-NY
P-NY-S-P
P-S-NY-P
S-NY-P-S
S-P-NY-S
My issue is avoiding the 0.0 distances from the array, which will obviously result in shorter routes.
Any help is much appreciated. Please note I am only just learning to code so if possible I prefer less efficient and easier to understand answers :)
The code below is my attempt of getting it to work for 4 cities, however, I wish for the program to be able to complete this task for any amount of cities. I am well aware what I tried is unsuccessful:
int numCities = weights.length();
List<Integer> brute = new ArrayList<Integer>();
for (int i = 0; i< 4; i++){
brute.add(i);
}
System.out.println(brute);
double weight = 0.0;
double tempWeight = 0.0;
int temp1 = 0;
int temp2 = 0;
int temp3 = 0;
int temp4 = 0;
int removing = 0;
int valuetoRemove = 0;
for (int a = 0; a < 4; a++){
for (int b = 0; b < 3; b++){
temp2 = brute.get(b);
//System.out.println(temp2);
List<Integer> brute2 = new ArrayList<Integer>();
brute2.addAll(brute);
brute.remove(b);
System.out.println(brute);
for (int c = 0; c < 2; c++){
temp3 = brute.get(c);
//System.out.println(temp3);
List<Integer> brute2 = new ArrayList<Integer>();
brute2.addAll(brute);
brute.remove(c);
//System.out.println(brute);
temp4 = brute.get(0);
//System.out.println(temp4);
//brute.remove(0);
//System.out.println(brute);
tempWeight = weights[temp1][temp2] + weights[temp2][temp3] + weights[temp3][temp4] + weights[temp4][temp1];
System.out.println(tempWeight);
brute = brute2;
}
}
}
Related
I wanna calculate Euclidean distances between each pairs of elements in a two dimensional array list in JAVA. this two dimensional array list consists of 40000 records in 40 dimensions. I encountered a memory deficiency problem:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
I increased the heap-memory size to: Xmx16000M (16Gb RAM). but the problem also exists. so, how can I get rid of out of memory problem? In the following you can see the pseudocode that exactly describe my code. Thank you all of the respondents.
ArrayList<ArrayList<Double> dataset = new ArrayList<ArrayList<Double>>();
dataset = readDataset(); // a method returns data to my 2-d arraylist
//now I have 40000 records in 40 dim in dataset!
distanceMatrix = new double[dataset.size()][dataset.size()];
for (int i=0 ; i<dataset.size(); i++) {
for (int j=0 ; j<(dataset.size()-i); j++) {
if (i == j) {
distanceMatrix[i][j] = 0.0;
continue;
}
double ans= getDistance(dataset.get(i), dataset.get(j));
distanceMatrix[i][j] = ans;
distanceMatrix[j][i] = ans;
}
}
public double getDistance(ArrayList<Double> a , ArrayList<Double> b) {
double dist=0;
for (int i = 0; i < 40; i++) {
double c = Math.abs(a.get(i) - b.get(i));
dist += Math.pow(c, 2);
}
dist = Math.sqrt(dist);
return dist;
}
In Java, given a 2D array of double values with dim as 6000*6000, is there an efficient way to query the row max and the row sum?
I am using the data structure double[][] and a two-layer loop to get the row max and sum, but it is not sufficiently efficient, as this function is called frequently.
double MinRowMax = Double.POSITIVE_INFINITY;
int num = 6000;
double[][] array2DDist = new double[num][num];
Random rand = new Random();
// initialising the array2DDist
for(int i=0;i<num;++i)
for(int j=0;j<num;++j)
array2DDist[i][j] = rand.nextDouble();
// get the row.max and row.sum
for(int i=0;i<num;++i) {
double maxDist = Double.NEGATIVE_INFINITY;
double sumDist = 0;
for(int j=0;j<num;++j) {
double dist = array2DDist[i][j];
maxDist = Double.max(maxDist, dist);
sumDist+=dist;
}
if(maxDist < MinRowMax) {
MinRowMax = maxDist;
}
}
Is there any Java library that provides more efficient solutions? Is there any Java library that is similar to Matrix class in Python or R?
Thanks!
To compute the sum of an array, or largest value in an array, you have to visit every element of the array. You cannot speed that up.
However, if the array is not going to change, and you are going to need the sum and max for the array multiple times, then you can compute them once and then look them up. There are two approaches:
Compute the required values for all rows of your 2-D array at the start and store them in a lookup table. This is a form or eager cache.
Use (say) a HashMap<Integer, CacheEntry> (where CacheEntry represents the sum and max), and then use this to lazily cache the required values for each row (indexed by the key).
(Or some variation on the implementation of the above.)
Is there any Java library that provides more efficient solutions? Is there any Java library that is similar to Matrix class in Python or R?
Not to my knowledge. Certainly, not in the standard Java class libraries.
However, if you use eager or lazy caching, you should not need a library ... for this problem.
I don't know if more efficient but way shorter using Stream. Here is a demo using 4x4 array :
double MinRowMax = Double.POSITIVE_INFINITY;
int num = 4;
double[][] array2DDist = new double[num][num];
Random rand = new Random();
// initializing the array2DDist
for(int i=0;i<num;++i) {
for(int j=0;j<num;++j) {
array2DDist[i][j] = rand.nextDouble();
}
}
// get the row.max and row.sum
for(int row=0;row<num;++row) {
double maxDist = Double.NEGATIVE_INFINITY;
double sumDist = 0;
for(int col=0;col<num;++col) {
double dist = array2DDist[row][col];
maxDist = Double.max(maxDist, dist);
sumDist+=dist;
}
//System.out.println(Arrays.toString(array2DDist[row]));
System.out.println("row sum - max " + sumDist +" - " + maxDist);
System.out.println("row sum - max " + Arrays.stream(array2DDist[row]).parallel().sum()
+" - " + Arrays.stream(array2DDist[row]).parallel() .max().getAsDouble());
if(maxDist < MinRowMax) {
MinRowMax = maxDist;
}
}
// Programme to get sum of rows value and column values seprately.
int[] colSum =new int[array[0].length];
for (int i = 0; i < array.length; i++){
for (int j = 0; j < array[i].length; j++){
sum += array[i][j];
colSum[j] += array[i][j];
}
System.out.println("Print the sum of rows =" + sum);
}
for(int k=0;k<colSum.length;k++){
System.out.println("Print the sum of columns =" + colSum[k]);
}
// Programme to get maximum in 2D array.
map<int, int> temp;
int currentMax= -999999,maxCount=0;
for(i=0; i< numberOflines ;i++)
{
for(j=0;j< array[i].length;j++)
{
int newCount = ++temp[array[i][j]];
if (maxCount < newCount) {
maxCount = newCount;
currentMax = array[i][j];
}
}
}
I am trying to write a java program that generates a population of random characters and eventually lands at an inputted string to simulate something like the infinite monkey theorem (https://en.wikipedia.org/wiki/Infinite_monkey_theorem). The issue I am having is as I am testing it, all of the starting population have a fitness level of 0 so nothing gets added to the mating pool during the natural selection process. Here is what the project entails.
Target: the string "Hello"
Mutation Rate: 0.01
Population Max: 100 DNA objects each containing a char[] array for the genes.
Here is my function for calculating the fitness:
public void calcFitness(String target){
double score = 0.0;
for(int i = 0; i < this.genes.length; i++){
if(this.genes[i] == target.charAt(i)){
score++;
}
}
this.fitness = score/this.genes.length;
}
I am new to genetic programming and not sure what I am doing wrong, any help would be appreciated and any tips or insight about genetic programming would also be appreciated.
EDIT
Here is the code for the selection process:
public void naturalSelection(){
ArrayList<DNA> selection = new ArrayList<>();
Random rand = new Random();
String child = "";
DNA[] newPop = new DNA[popMax];
for(int i = 0; i < population.length; i++){
for(int j = 0; j < population[i].getFitness(); j++){
selection.add(population[i]);
}
}
for(int i = 0; i < selection.size(); i++){
int parentSelect = rand.nextInt(selection.size());
DNA parent1 = selection.get(parentSelect);
child = parent1.split(true);
parentSelect = rand.nextInt(selection.size());
DNA parent2 = selection.get(parentSelect);
child += parent2.split(false);
newPop[i] = new DNA(child);
}
double mutation = rand.nextDouble();
if(mutation < this.mutationRate){
this.population = swapMutation(newPop);
calcFittest();
}
else{
this.population = newPop;
calcFittest();
}
}
Where swap mutation swaps two random chars if mutation occurs.
I would suggest using a fitness function that measures distance from a candidate to the target string. You would then minimise overall fitness instead of maximising.
To do this:
public void calcFitness(String target){
double score = 0.0;
for(int i = 0; i < this.genes.length; i++){
score += Math.abs((int)this.genes[i] - (int)target.charAt(i));
}
this.fitness = score / this.genes.length;
}
This should work better because it will differentiate each candidate much better. Without seeing the random string generator you are using it is hard to say but it is likely that the number of possible candidates is astronomical with a very low chance that any of them score a single point with your fitness function.
Might also be worth pointing out that your code is likely part of a Genetic Algorithm rather than Genetic Programming.
If you want to improve the selection I would recommend as an easy to program technique Tournament Selection - choose n random individuals from the population and then select the best fitness individual from the n individuals. This gives better candidates a higher chance of being selected than other individuals and has the added bonus that you don't need to calculate fitness for every individual in a population.
I just finished a GA for infinite monkey theorem. You may find at https://github.com/Willtl/infinite_monkey_theorem
It is in C++ but it would not be difficult to do the same in Java. You can open the project it using Eclipse CPP.
void Individual::calculateFitness(vector<char> chromosomePlate) {
fitness = 0;
for (int i = 0; i < chromosome.size(); i++) {
int gene = (int) chromosome[i];
int genePlate = (int) chromosomePlate[i];
if (gene == genePlate && gene != 32) {
fitness++;
}
}
First of all, when I read the input I put it to lower case. Then to make it easy to randomize and compare, I am using ASCII. So as I am just considering lower case my characters range goes from 97 to 122. I also keep the spaces at the chromosome, however in the fitness function I ignore it (32).
Anything that you need just post here I will be more than happy to help.
So currently I have the following which finds me the shortest/nearest neighbor by taking the smallest distance value from my "distance" array which has the calculated distances. Then it does another search to track down it's index which then indicates to me which patient it belongs to.
However say I wanted to find the 3 nearest neighbors, how would I do that? Do I need to change my code entirely to accommodate for this?
Many thanks
int min = 99;
int d = 1;
String diagnosis;
//Finding smallest value from an array containing distance to new 'patient'
for(d=1; d<= numberOFinstances; d++){
if(distance[d] < min)
min = distance[d];
}
for (int p = 1; p < numberOFinstances; p++)
{
if (distance[p] == min){
System.out.println("Nearest patient to new patient is Patient "+p+ " with a distance of: " + min);
//Here I'm saying 6 because the diagnosis is in column 6 within the matrix
diagnosis = data[p][6];
System.out.println("The new patient's diagnosis is: " + diagnosis);
}
}
Best way to accomplish would be to use Arrays.sort(int[])
Arrays.sort(distance);
int[] toReturn = new int[k];
for (int i = 0; i < k; i++) {
toReturn[i] = distance[i];
}
I have a function that defines a very long polynomial useful in operations with matrices.
The formula multiplies binomials of the form (1+xi*yj) , where i and j are subscripted and correspond to the rows and columns of the matrix in question, respectively. The polynomial that results is the product of all binomials with every permutation of i and j.
For example, a 3 x 2 matrix will have the polynomial product be:
(1+x1*y1)(1+x1*y2)(1+x2*y1)(1+x2*y2)(1+x3*y1)(1+x3*y2)
For clarification, every number after the variable should be treated as a subscript.
Is it possible for java to compute something of this massive amount, or can the task be delegated to another mathematics engine?
If possible, how would one go about implementing this?
Maybe this idea will help you to solve your problem:
int result = 1;
int x = 2;
int y = 3;
Integer [][] polynomials = new Integer[x][y];
polynomials[0][0] = 1;
polynomials[0][1] = 2;
polynomials[0][2] = 3;
polynomials[1][0] = 4;
polynomials[1][1] = 5;
polynomials[1][2] = 6;
for(int i = 0; i<x; i++) {
for(int j = 0; j<y; j++) {
result *= (1 + polynomials[i][j]);
}
}
System.out.println(result);