Clarke Wright Looping Issue - java

I'm trying to implement the Clarke Wright algorithm. The problem I seem to be having is that it merges lots of routes regardless of the tests I've put into place. I've been staring at this for a long time, so I thought it may help to cast a fresh pair of eyes over it.
Instead of creating routes that are valid (ie, the van has enough space to carry everything), it wildly creates routes everywhere regardless of whether it's got the capacity or not.
public void CWVRSolution(){
List<SavingsNode> savings = new ArrayList<SavingsNode>();
// ArrayList<List<Customer>> routes = new ArrayList<List<Customer>>();
this.soln = new ArrayList<List<Customer>>();
//ArrayList<List<Customer>> routelist = new ArrayList<List<Customer>>();
for (int i=0; i < prob.customers.size(); i++){
for (int j=i+1; j<prob.customers.size();j++){
if (i != j){
double savingVal = (prob.depot.distance(prob.customers.get(i)) + prob.depot.distance(prob.customers.get(j))) - prob.customers.get(i).distance(prob.customers.get(j));
savings.add(new SavingsNode(prob.customers.get(i),prob.customers.get(j),savingVal));
}
}
}
Collections.sort(savings);
Collections.reverse(savings);
int sncounter = 0;
for (SavingsNode sn: savings ){
// for every route in prob.soln
// if from or to isnt in any of those routes
// do that stuff
if (!soln.contains(sn.i)){
if(!soln.contains(sn.j)){
if ((sn.i.c + sn.j.c) <= 50){
ArrayList<Customer> route = new ArrayList<Customer>();
route.add(sn.i);
route.add(sn.j);
soln.add(route);
}
}
}else if(!soln.contains(sn.j)){
//find a route that ends in from
int d = 0;
int e = 0;
for (List<Customer> c: soln){
for (Customer x : c){
d += x.c;
}
if (c.get(c.size()-1) == sn.i){
if (d + sn.j.c <= 50){
// Customer route = new Customer(sn.i.c, sn.j.c, cust.requirement);
ArrayList<Customer> newRoute = new ArrayList<Customer>();
newRoute.add(sn.i);
// prob.customers.remove(sn.j);
// soln.remove(c);
c.addAll(newRoute);
soln.add(c);
d=0;
//newRoute.clear();
break;
}
}
}
}
if (!soln.contains(sn.i)){
int d = 0;
int e = 0;
for (List<Customer> c:soln){
if (c.get(0) == sn.j){
for (Customer x : c){
d += x.c;
}
if (d+ sn.i.c <= 50){
ArrayList<Customer> newRoute = new ArrayList<Customer>();
newRoute.add(sn.j);
soln.remove(c);
c.addAll(0, newRoute);
soln.add(c);
d=0;
// soln.remove(arg0)
break;
}
}
}
}
List<Customer> merged = null;
int mergescounter = 0;
int xreq= 0;
int yreq = 0;
for (List<Customer> routeX: soln){
if (merged != null){
break;
}
if (routeX.get(routeX.size()-1) == sn.i){
for(Customer c:routeX){
xreq += c.c;
}
for (List<Customer> routeY: soln){
if (routeY.get(0) == sn.j){
for(Customer c:routeY){
yreq += c.c;
}
if ((routeX!=null)&&(routeY!=null)){
if (routeX != routeY){
int capnec = 0;
capnec = yreq+xreq;
if (sn.i.c +sn.j.c + capnec <= 50){
List<Customer> merged1 = new ArrayList<Customer>();
merged1.addAll(routeY);
merged1.addAll(routeX);
// route.add(merged1);
soln.add(merged1);
mergescounter++;
merged = routeX;
capnec=0;
break;
}
}
}
}
}
}
}
if (merged!=null){
soln.remove(merged);
}
}
Customer class:
public class Customer extends Point2D.Double{
// Requirements of the customer (number to be delivered)
public static int c;
public int requirement;
public Customer(int x, int y, int requirement){
this.x = x;
this.y = y;
//parcel requirement
this.c = requirement;
}
SavingsNode class
SavingsNode(Customer i, Customer j, double savingVal){
this.i = i;
this.j= j;
this.savingVal = savingVal;
}
Any help would be appreciated.

Related

How to correctly implement maximum weight independent set of positive tree using BFS

can someone help me implement the maximum weight independent set for a TREE (not a graph)?
The tree is represented by an adjacency matrix, and we have an array for the weights of the vertices.
BFS output: // 0: distances from start vertex
// 1: BFS-order
// 2: parent-IDs
I tried this code, it doesn't work on all test cases and it says most of the time that the weight is too small.
Can someone help me find the errors?
import java.io.*;
import java.util.*;
public class Lab5
{
/**
* Problem: Find a maximum weight independent set using dynammic programming.
*/
private static int[] problem(Tree t, int[] weights)
{
// Implement me!
//base cases
if (t.noOfVertices==0) {
return new int[] {};
}
if (t.noOfVertices==1) {
return new int[] {weights[0]};
}
//we will implement this using bfs, we will use 0 as the root
int[][] bfs = t.bfs(0);
//finding leaves
int leaf[] = new int [t.noOfVertices];
//now we can implement our algorithm
//M is the maximum weight of the tree if it contains i, and M1 is the maximum weight of the tree if it doesn't contain i
int M[]=new int[t.noOfVertices];
int M1[]=new int[t.noOfVertices];
//treating elements that aren't leaves
int nodeDiscovered[] = new int[t.noOfVertices];
for (int i = 0; i<t.noOfVertices; i++) {
if (t.edges[i].length==1) {
leaf[i]=1;
M[i]=weights[i];
nodeDiscovered[i]=1;
M1[i]=0;
}
else {
leaf[i]=0;
nodeDiscovered[i]=0;
}
}
for (int i = 1; i<t.noOfVertices; i++) {
if (leaf[i]==1) {
int node = bfs[2][i];
if (nodeDiscovered[node]!=0) {
continue;
}
while (node>-1) {
int parent = bfs[2][node];
ArrayList<Integer> sibs = new ArrayList<Integer>();
if (parent!=-1) {
for (int j = 0; j<t.edges[parent].length; j++) {
if (t.edges[parent][j]!=bfs[2][parent]) {
sibs.add(t.edges[parent][j]);
}
}
}
else {
sibs.add(node);
}
for (int sib : sibs) {
if (nodeDiscovered[sib]!=0) {
continue;
}
M[sib]=weights[sib];
for (int k : t.edges[sib]) {
if(bfs[0][sib]==bfs[0][k]-1) {
M[sib]=M[sib]+M1[k];
M1[sib]+=(M[k]>M1[k])?M[k]:M1[k];
}
}
nodeDiscovered[sib]=1;
}
node = bfs[2][node];
}
}
}
//putting the answers in an arraylist
ArrayList<Integer> set = new ArrayList<Integer>();
if (M[0]>M1[0]) {
set.add(0);
}
for (int i = 1; i<t.noOfVertices; i++) {
if (!set.contains(bfs[2][i]) && M[i]>=M1[i] ) {
set.add(i);
}
}
System.out.println(set);
//putting the elements of the arraylist into an array of int
int[] set1 = new int[set.size()];
for (int i = 0; i<set.size(); i++) {
set1[i]=set.get(i);
}
return set1;
}
// ---------------------------------------------------------------------
// Do not change any of the code below!
// Do not change any of the code below!
/**
* Determines if a given set of vertices is an independent set for the given tree.
*/
private static boolean isIndSet(Tree t, int[] set)
{
if (set == null) return false;
boolean[] covered = new boolean[t.noOfVertices];
for (int i = 0; i < set.length; i++)
{
int vId = set[i];
int[] neighs = t.edges[vId];
if (covered[vId]) return false;
covered[vId] = true;
for (int j = 0; j < neighs.length; j++)
{
int nId = neighs[j];
covered[nId] = true;
}
}
return true;
}
private static final int LabNo = 5;
private static final String course = "CS 427";
private static final String quarter = "Fall 2021";
private static final Random rng = new Random(190817);
private static boolean testProblem(int[][] testCase)
{
int[] parents = testCase[0];
int[] weights = testCase[1];
Tree t = Tree.fromParents(parents);
int[] solution = maxIsWeight(t, weights);
int isWeight = solution[0];
int isSize = solution[1];
int[] answer = problem(t, weights.clone());
if (!isIndSet(t, answer))
{
System.out.println("Not an independent set.");
return false;
}
int ansWeight = 0;
for (int i = 0; i < answer.length; i++)
{
ansWeight += weights[answer[i]];
}
if (ansWeight < isWeight)
{
System.out.println("Weight too small.");
return false;
}
if (answer.length < isSize)
{
System.out.println("Set too small.");
return false;
}
return true;
}
private static int[] maxIsWeight(Tree t, int[] weigh)
{
int n = t.noOfVertices;
int[][] dfs = t.dfs(0);
int[] post = dfs[2];
int[] w = new int[n];
for (int i = 0; i < n; i++)
{
w[i] = weigh[i] * n + 1;
}
boolean[] isCandidate = new boolean[n];
for (int i = 0; i < n; i++)
{
int vId = post[i];
if (w[vId] <= 0) continue;
isCandidate[vId] = true;
int[] neighs = t.edges[vId];
for (int j = 0; j < neighs.length; j++)
{
int uId = neighs[j];
w[uId] = Math.max(w[uId] - w[vId], 0);
}
}
int isWeight = 0;
int isSize = 0;
for (int i = n - 1; i >= 0; i--)
{
int vId = post[i];
if (!isCandidate[vId]) continue;
isWeight += weigh[vId];
isSize++;
int[] neighs = t.edges[vId];
for (int j = 0; j < neighs.length; j++)
{
int uId = neighs[j];
isCandidate[uId] = false;
}
}
return new int[] { isWeight, isSize };
}
public static void main(String args[])
{
System.out.println(course + " -- " + quarter + " -- Lab " + LabNo);
int noOfTests = 300;
boolean passedAll = true;
System.out.println("-- -- -- -- --");
System.out.println(noOfTests + " random test cases.");
for (int i = 1; i <= noOfTests; i++)
{
boolean passed = false;
boolean exce = false;
try
{
int[][] testCase = createProblem(i);
passed = testProblem(testCase);
}
catch (Exception ex)
{
passed = false;
exce = true;
ex.printStackTrace();
}
if (!passed)
{
System.out.println("Test " + i + " failed!" + (exce ? " (Exception)" : ""));
passedAll = false;
//break;
}
}
if (passedAll)
{
System.out.println("All test passed.");
}
}
private static int[][] createProblem(int testNo)
{
int size = rng.nextInt(Math.min(testNo, 5000)) + 5;
// -- Generate tree. ---
int[] parents = new int[size];
parents[0] = -1;
for (int i = 1; i < parents.length; i++)
{
parents[i] = rng.nextInt(i);
}
// -- Generate weights. ---
int[] weights = new int[size];
for (int i = 0; i < weights.length; i++)
{
weights[i] = rng.nextInt(256);
}
return new int[][] { parents, weights };
}
}
I attached an image that contains the algorithm that I used.

Why am I getting this IndexOutOfBoundsException error?

hi so im currently trying to get past this error in my code, if anyone could explain where I went wrong, would be greatly appreciated.
public class Lab07vst100SD
{
public static void main (String[] args)
{
System.out.println();
int size = 10;
School bhs = new School(size);
System.out.println(bhs);
System.out.println(bhs.linearSearch("Meg"));
System.out.println(bhs.linearSearch("Sid"));
System.out.println();
bhs.selectionSort();
System.out.println(bhs);
System.out.println(bhs.binarySearch("Meg"));
System.out.println(bhs.binarySearch("Sid"));
System.out.println();
}
}
class School
{
private ArrayList<Student> students;
private int size;
public School (int s)
{
students = new ArrayList<Student>();
size = s;
}
public void addData()
{
String [] name = {"Tom","Ann","Bob","Jan","Joe","Sue","Jay","Meg","Art","Deb"};
int[] age = {21,34,18,45,27,19,30,38,40,35};
double[] gpa = {1.685,3.875,2.5,4.0,2.975,3.225,3.65,2.0,3.999,2.125};
for(int i = 0; i < name.length; i++)
{
students.add(new Student(name[i], age[i], gpa[i]));
}
size = students.size();
}
public void selectionSort ()
{
for(int h = 0; h < students.size(); h++)
{
int index = h;
Student least = students.get(h);
for (int t = 0; t < size; t++) {
if (students.get(t).equals(least)) {
least = students.get(t);
index = t;
}
Student temp = students.get(h);
students.set(h, least);
students.set(t, temp);
}
}
}
public int linearSearch (String str)
{
// new arraylist
ArrayList<String> names = new ArrayList<String>();
for (int q = 0; q < size; q++) {
names.add(students.get(q).getName());
}
//comparison
for (int y = 0; y < size; y++) {
if (names.get(y).equals(str))
return y;
}
return -1;
};
public int binarySearch (String str) {
// new arraylist and variables
ArrayList<String> names = new ArrayList<String>();
Boolean found = false;
int lo = 0;
int hi = size;
int mid = (lo + hi) / 2;
//for loop for to transverse the array.
for (int m = 0; m < size; m++) {
names.add(students.get(m).getName());
}
while (lo <= hi && !found) {
if (names.get(mid).compareTo(str) == 0)
{
found = true;
return mid;
}
if (names.get(mid).compareTo(str) < 0) {
lo = mid + 1;
mid = (lo + hi) / 2;
}
else {
hi = mid -1;
mid = (lo + hi) / 2;
}
}
if (found)
return mid;
else
return -1;
}
public String toString() {
String temp = "";
for (int s = 0; s < students.size(); s++) {
temp += students.get(s);
}
return temp;
}
}
also, I should mention this uses the student class.
here
public class Student
{
private String name;
private int age;
private double gpa;
public Student (String n, int a, double g)
{
name = n;
age = a;
gpa = g;
}
public String getName() {
return name; }
public int getAge() {
return age; }
public double getGPA() {
return gpa; }
public String toString()
{
String temp = name + " " + age + " " + gpa + "\n";
return temp;
}
}
the school class calls to the student class.
this is what comes back.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:359)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at School.linearSearch(Lab07vst100SD.java:78)
at Lab07vst100SD.main(Lab07vst100SD.java:16)
I'm completely confused on why this is happening, I think it may have to do with the ArrayList, other than that, I'm not sure.
please help, and thank you
p.s. I'm new so please bear with my horrible format.
You need call addData:
public static void main (String[] args)
{
System.out.println();
int size = 10;
School bhs = new School(size);
bhs.addData(); // here
System.out.println(bhs);
System.out.println(bhs.linearSearch("Meg"));
System.out.println(bhs.linearSearch("Sid"));
System.out.println();
bhs.selectionSort();
System.out.println(bhs);
System.out.println(bhs.binarySearch("Meg"));
System.out.println(bhs.binarySearch("Sid"));
System.out.println();
}
...
class School
{
private ArrayList<Student> students;
private int size;
public School (int s)
{
students = new ArrayList<Student>(); // Here, it can throw IndexOutOfBoundsException
size = s;
}
...
Please see https://www.tutorialspoint.com/java/util/arraylist_add_index.htm
The capacity of ArrayList must be initialized before ArrayList.add method
.

"Cannot find symbol: Method" but method is defined and declared in Storm.java

In my driver program methods: setDuration, setWind, setPressure, NewStorm, getCategory cannot not be found although they are clearly declared in my Storm.java file. I can't refer to any of them.
import java.io.*;
import java.util.Scanner;
public class StormChaser {
public static void main(String[] args)
{
// Constants
final int MAX_STORMS = 200;
Storm[] List = new Storm[MAX_STORMS]; // array of Storms
Storm CurrentStorm; // storm returned by GetStorm
int NStorms = 0; // number in array List
int Total = 0; // total number of storms in the input file
Scanner fileInput;
// Openning hurricane data file
try{
System.out.println("Openning hurricane data file...");
fileInput = new Scanner(new File("hurricane.data"));
}
catch(FileNotFoundException e){
System.err.println("FileNotFoundException: " + e.getMessage());
return;
}
System.out.println( "File opened successfully...");
System.out.println( "Reading file..." );
// Read Storm data from file until EOF
while( fileInput.hasNextLine())
{
CurrentStorm = GetStorm(fileInput);
++Total;
if( CurrentStorm.getCategory() >= 3 )
{
List[NStorms++] = CurrentStorm;
}
}
System.out.println( "Number of storms: " + Total);
System.out.println( "Hurricanes with category 3 and above: " + NStorms );
DisplayStorms( "First Ten Storms", List, 10 );
Sort( List, NStorms );
DisplayStorms( "Top Ten Storms", List, 10 );
fileInput.close();
}
public static Storm GetStorm( Scanner in )
{
// Build a Storm object and return it
int year = 0, month = 0, day = 0, hour = 0, sequence = 0, wind = 0, pressure
= 0;
String name = new String();
double junk = 0.0;
int current = 0, beginDate = 0, duration = 0;
Storm NewStorm;
// Check for end of file
if( !in.hasNextLine() )
{
NewStorm = new Storm(beginDate, duration, name, wind, pressure);
return NewStorm;
}
// Read next record.
year = in.nextInt();
month = in.nextInt();
day = in.nextInt();
hour = in.nextInt();
sequence = in.nextInt();
name = in.next();
junk = in.nextDouble();
junk = in.nextDouble();
wind = in.nextInt();
pressure = in.nextInt();
// Make a storm object and initialize it with info from the current
record
beginDate = year * 10000 + month * 100 + day;
NewStorm = new Storm(beginDate, duration, name, wind, pressure);
current = sequence;
while( in.hasNextLine() && current == sequence)
{
//update storm info
duration += 6;
NewStorm.setDuration(duration);
NewStorm.SetWind(wind);
NewStorm.setPressure(pressure);
//get next record
}
// and return the new storm object
return NewStorm;
}
public static void DisplayStorms( String title, Storm[] List, int NStorms )
{
// display NStorms storms
// print some title and column headings
System.out.println(title + "\n");
System.out.println("Begin Date Duration Name Category Maximum
Minimum");
System.out.println(" (hours) Winds (mph)
Press. (mb)");
System.out.println("----------------------------------------------------
----
--------");
for( int k = 0; k < NStorms; k++ )
System.out.println(List[k].toString());
System.out.println ("\n");
}
public static void Sort( Storm[] StormList, int N )
{
// bubble sort the list of Storms
int pass = 0, k, switches;
Storm temp;
switches = 1;
while( switches != 0 )
{
switches = 0;
pass++;
for( k = 0; k < N - pass; k++ )
{
if( StormList[k].getCategory() < StormList[k+1].getCategory() )
{
temp = StormList[k];
StormList[k] = StormList[k+1];
StormList[k+1] = temp;
switches = 1;
}
}
}
}
}
And this is the Storm.java.
public class Storm {
private final double KnotsToMPH = 1.15;
// global user-defined types:
private int beginDate = 0;
private int duration = 0;
private String name;
private int category = 0;
private int wind = 0;
private int pressure = 0;
public Storm( int bdate, int dur, String sname, int w, int p )
{
beginDate = bdate;
setDuration(dur);
name = sname;
wind = 0;
pressure = 0;
setWind(w);
setPressure(p);
}
public void setDuration( int d )
{
duration = d;
}
public void setWind( int w )
{
double temp = 0.0;
temp = KnotsToMPH * w;
if(temp > wind)
wind = (int)temp;
SaffirSimpson();
}
public void setPressure( int p )
{
if(pressure == 0)
pressure = p;
if(pressure > p && p != 0)
pressure = p;
SaffirSimpson();
}
public void SaffirSimpson()
{
// Compute storm category, using the Saffir-Simpson scale
if(pressure <= 920 && wind >= 156)
{
category = 5; // Category 5
}
if(pressure > 920 && wind < 156)
{
category = 4; // Category 4
}
if(pressure > 945 && wind < 113)
{
category = 3; // Category 3
}
if(pressure > 965 && wind < 96)
{
category = 2; // Category 2
}
if(pressure > 980 && wind < 83)
{
category = 1; // Category 1
}
if(wind < 64)
{
category = -1; // Tropical Storm
}
if(wind < 34)
{
category = -2; // Tropical Depression
}
if(pressure == 0)
{
category = 0; // Missing pressure
}
}
public int getCategory()
{
return category;
}
public String toString()
{
return String.format("%9d %8d %10s %4d %9d %10d\n", beginDate,
duration,
name, category, wind, pressure);
}
}
I am pretty sure it has something to do with the default constructor that NetBeans creates, I'm just not sure where that exact problem is located..
Java is case sensitive, SetWind is not the same as setWind
The method in Storm is defined as setWind
public static class Storm {
//...
public void setWind(int w) {
//...
}
//...
}
But you are using SetWind in you code NewStorm.SetWind(wind);

How do I fill an ArrayList with random generated products?

I'd like some help with getting a randomizer working for my code. I am working on a hill-climbing algorithm for a school project. The algorithm works only I don't know how I can make it add random product(locations it needs to visit.)
Here is the main class. If I have to provide anymore then feel free to ask and I will.
package hillclimbing;
import java.util.ArrayList;
import java.util.Arrays;
public class Driver {
private ArrayList<Product> initialProducts = new ArrayList<Product>(Arrays.asList(
new Product("Tandpasta", 42.3601, -71.0589),
new Product("Banaan", 29.7064, -95.3698),
new Product("Kaas", 30.2672, -97.7431),
new Product("Laptop", 37.7749, -122.4194),
new Product("Vliegtuig", 39.0000, -104.0000),
new Product("Robot", 34.0000, -118.0000),
new Product("Magazijn", 41.0000, -87.0000),
new Product("Kubus", 40.0000, -74.0000),
new Product("Doos", 32.0000, -96.0000),
new Product("Lego", 47.0000, -122.0000)
));
public static void main(String[] args) {
Driver driver = new Driver();
Route route = new Route(driver.initialProducts);
printHeading(route);
System.out.print(route + " | " + route.getTotalDistance());
new HillClimbing().findShortestRoute(route);
}
public static void printHeading(Route route){
String headingColumn1 = "Route";
String remainingHeadingColumns = "Distance (in miles) | Compare adjacent to current route";
int productNamesLength = 0;
for(int x = 0; x < route.getProducts().size(); x++) productNamesLength += route.getProducts().get(x).getName().length();
int arrayLength = productNamesLength + route.getProducts().size()*2;
int partialLength = (arrayLength - headingColumn1.length()/2);
for(int x = 0; x < partialLength; x++)System.out.print(" ");
System.out.print(headingColumn1);
for(int x = 0; x < partialLength; x++)System.out.print(" ");
if((arrayLength % 2) == 0)System.out.print(" ");
System.out.println(" | " + remainingHeadingColumns);
productNamesLength += remainingHeadingColumns.length() + 3;
for(int x = 0; x < productNamesLength + route.getProducts().size()*2; x++)System.out.print("-");
System.out.println("");
}
}
And here is the randomizer that should be able to fill/replace the ArrayList
package hillclimbing;
import java.util.*;
public class RandomProducten {
public HashMap<Integer, Product> producten;
public RandomProducten(int aantal){
Random rand = new Random();
producten = new HashMap<Integer, Product>();
for(int i = 1; i <= aantal;i++){
boolean geaccepteerd = false;
int randx = rand.nextInt(5) + 1;
int randy = rand.nextInt(5) + 1;
while (! geaccepteerd){
if (hasDuplicates(randx, randy)){
randx = rand.nextInt(5) + 1;
randy = rand.nextInt(5) + 1;
} else {
geaccepteerd = true;
}
}
Product p = new Product("Product " + i, randx, randy);
producten.put(i, p);
}
}
public boolean hasDuplicates(int x, int y) {
boolean antwoord = false;
for (Map.Entry<Integer, Product> entry : producten.entrySet()) {
if (entry.getValue().getX() == x && entry.getValue().getY() == y){
antwoord = true;
}
}
return antwoord;
}
public String toString(){
String antwoord = "";
for (Map.Entry<Integer, Product> entry : producten.entrySet()) {
antwoord += entry.getValue();
}
return antwoord;
}
}

Even though copies are made, referencing is going wrong

Unfortunately, I am having a reference issue. The variable emptyRoutes does change as soon as I have called ELIMINATOR. However, in ELIMINATOR I have made a copy (new ArrayList(emptyRoutes) of the route, so changing the route in eliminator should not change emptyRoutes?
Does someone know what is going wrong?
MAIN CODE:
public Triple<List<ROUTE>, Integer, List<Customer>> initialization()
{
boolean initialization = true;
// Create the empty routes (also used in the for loop)
Customer vertex0 = u.get(0);
Pair<List<ROUTE>, Integer> results = createEmptyRoutes(vertex0, num_routes);
u.remove(0);
List<ROUTE> emptyRoutes = new ArrayList<ROUTE>(results.getFirst());
int profit = results.getSecond();
// Initialize the values of the variables
List<ROUTE> bestroutes = new ArrayList<ROUTE>(4);
List<Customer> best_u = new ArrayList<Customer>(u);
int tpBestSolution = 0;
int tdBestSolution = 1000000000;
int inU = u.size();
int num = (emptyRoutes.get(0).getLocations().size()-2) + (emptyRoutes.get(1).getLocations().size()-2) + (emptyRoutes.get(2).getLocations().size()-2)+ (emptyRoutes.get(3).getLocations().size()-2);
if (inU + num != 50)
{
System.out.println();
}
for (int i = 0; i < (3*N); i++)
{
Collections.shuffle(u, rnd);
ELIMINATOR B = new ELIMINATOR(u, emptyRoutes, profit, initialization, name, rnd);
inU = B.getU().size();
num = (B.getRoutes().get(0).getLocations().size()-2) + (B.getRoutes().get(1).getLocations().size()-2) + (B.getRoutes().get(2).getLocations().size()-2)+ (B.getRoutes().get(3).getLocations().size()-2);
if (inU + num != 50)
{
System.out.println(i);
}
POSTPROCEDURE PP = new POSTPROCEDURE(B.getRoutes(), profitRoutes(B.getRoutes()), B.getU(), name);
// Temporary solution
List<ROUTE> tempRoutes = PP.getBestSolution();
for (int p = 0; p < PP.getBestSolution().size(); p++)
{
ROUTE r = PP.getBestSolution().get(p);
addToPOOL(r);
}
boolean improvement = false;
if (PP.getTP() > tpBestSolution)
{
improvement = true;
}
else if (PP.getTP() == tpBestSolution)
{
if (PP.getTD() < tdBestSolution)
{
improvement = true;
}
}
if (improvement == true)
{
best_u = new ArrayList<Customer>(PP.getU());
bestroutes = new ArrayList<ROUTE>(tempRoutes);
tpBestSolution = new Integer(PP.getTP());
tdBestSolution = new Integer(PP.getTD());
}
}
return new Triple<List<ROUTE>, Integer, List<Customer>>(bestroutes, tpBestSolution, best_u);
}
ELIMINATOR:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class ELIMINATOR extends BASIS
{
private List<Customer> u;
private List<ROUTE> routes;
private int totalprofit;
private Random prob;
public ELIMINATOR(List<Customer> u, List<ROUTE> routes, int profit, boolean initialization, String name, Random rnd)
{
super(name);
this.u = new ArrayList<Customer>(u);
this.routes = new ArrayList<ROUTE>(routes);
this.totalprofit = new Integer(profit);
this.prob = rnd;
if (initialization == true)
{
addCustomers();
for (ROUTE route : routes)
{
checkCorrectNess(route, "after adding procedure in eliminator");
}
}
else
{
removeCustomers();
for (ROUTE route : routes)
{
checkCorrectNess(route, "after removing procedure in eliminator");
}
addCustomers();
for (ROUTE route : routes)
{
checkCorrectNess(route, "after removing and adding procedure in eliminator");
}
}
}
public void removeCustomers()
{
double Ph = 0.1;
double Pl = 0.3;
double total_profit = totalprofit;
int num_customers = 0;
// Calculate average profit
double average_profit = total_profit/num_customers;
// For each customer on each route, determine whether he/she will be removed
for(ROUTE r : routes)
{
List<RouteNode> route = r.getLocations();
int routesize = route.size();
int j = 1;
while (j < routesize-1)
{
boolean removed = false;
RouteNode node = route.get(j);
if (node.customer.getProfit() >= average_profit)
{
if (prob.nextDouble() < Ph)
{
removed = true;
RouteNode node_toberemoved = node;
int index_node = route.indexOf(node);
route.remove(index_node);
u.add(node.customer);
route = removal(route, node_toberemoved, index_node);
r.setLocations(route);
r.setDistance(distanceOneRoute(route));
r.setProfit(profitOneRoute(route));
checkCorrectNess(r, "remove customers eliminator");
}
}
else
{
if (prob.nextDouble() < Pl)
{
removed = true;
RouteNode node_toberemoved = node;
int index_node = route.indexOf(node);
route.remove(index_node);
u.add(node.customer);
route = removal(route, node_toberemoved, index_node);
r.setLocations(route);
r.setDistance(distanceOneRoute(route));
r.setProfit(profitOneRoute(route));
checkCorrectNess(r, "remove customers eliminator");
}
}
if (removed == false)
{
j++;
}
else
{
routesize = route.size();
}
}
}
totalprofit = profitRoutes(routes);
}
public void addCustomers()
{
List<Customer> u_copy = new ArrayList<Customer>(u);
List<Customer> u_temp = new ArrayList<Customer>(u);
for (Customer c : u_temp)
{
boolean added = false;
for (ROUTE r : routes)
{
checkCorrectNess(r, "add customers eliminator");
if (added == true)
{
break;
}
Customer customer = c;
u_copy.remove(c);
List<RouteNode> route = r.getLocations();
for (int i = 0; i < route.size()-1; i++)
{
RouteNode possibleNode = new RouteNode();
possibleNode.customer = customer;
List<Integer> distances = calculateDistances(route.get(i), possibleNode, route.get(i+1));
// Calculate shift for customer under consideration
int arrivalTime = route.get(i).timeStartService+ route.get(i).customer.getService() + distances.get(0);
int wait = Math.max(0, customer.getOpeningTW()-arrivalTime);
int serviceDuration = customer.getService();
int shift = distances.get(0) + wait + serviceDuration + distances.get(2) - distances.get(1);
// Determine Start Service
int startServiceTime = Math.max(customer.getOpeningTW(), arrivalTime);
// Obtain waiting time of next customer
int waiting_next = route.get(i+1).wait;
// Obtain MaxShift of next customer
int maxShift = route.get(i+1).maxShift;
if (shift <= (waiting_next + maxShift) & startServiceTime <= customer.getClosingTW() )
{
// Customer can be inserted
added = true;
RouteNode newNode = new RouteNode();
newNode.customer = customer;
newNode.arrivalTime = arrivalTime;
newNode.timeStartService = startServiceTime;
newNode.shift = shift;
newNode.wait = wait;
int pos_insertion = i + 1;
route = ADD(route, newNode, pos_insertion);
r.setLocations(route);
r.setDistance(distanceOneRoute(route));
r.setProfit(profitOneRoute(route));
checkCorrectNess(r, "add customers eliminator");
// exit the last for loop
break;
}
}
}
if (added == false)
{
u_copy.add(c);
}
}
u = new ArrayList<Customer>(u_copy);
totalprofit = profitRoutes(routes);
}
/**
* Returns list of unvisited customers
* #return
*/
public List<Customer> getU()
{
return u;
}
/**
* Returns list of routes
* #return
*/
public List<ROUTE> getRoutes()
{
return routes;
}
}
I think the problem is that copying a List<Route> object, doesn't copy the Route objects1 that the list contains.
Thus, you end up with two lists containing the same Route objects. The effects of changing a Route found in one list affects the same object in the other list.
1 - I refuse to follow your bad Java style decisions!

Categories

Resources