I should really know what the problem is by now but I am having trouble. My problem is with the Java Arraylist. I am trying to add objects to an arraylist through a class method (addStartingPop in kgenetics class). This method gets called in main which should update the class member of kgenetics which is an arrayList. After called addStartPop() in main, I try to print out the new population in main right after. However if you notice, the Item arrays are not how I expect the to be. PROBLEM: The problem is that the values do get added to the array list but it seems that they are not completely modified how I want them to be.
Here it the output from running the program:
This is what should be in the Arraylist after the called to addStartPop()
I print each knapsack before it gets added to the arraylist(knapsackSamples)
Item: (1.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (4.0, 6.0, true)
Item: (3.0, 2.0, false)
Item: (1.0, 2.0, true)
Item: (8.0, 10.0, false)
Item: (1.0, 2.0, true)
Item: (5.0, 1.0, true)
Item: (7.0, 8.0, true)
Item: (6.0, 9.0, false)
Score: 37.0
Item: (1.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (4.0, 6.0, false)
Item: (3.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (8.0, 10.0, false)
Item: (1.0, 2.0, true)
Item: (5.0, 1.0, true)
Item: (7.0, 8.0, true)
Item: (6.0, 9.0, false)
Score: 24.0
This is what gets printed out though when I print the samples in the main method. The score(calculated from the two numbers that make an item) is correct but the array is the last array that was added)
Item 0
Item: (1.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (4.0, 6.0, false)
Item: (3.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (8.0, 10.0, false)
Item: (1.0, 2.0, true)
Item: (5.0, 1.0, true)
Item: (7.0, 8.0, true)
Item: (6.0, 9.0, false)
Score: 37.0
Item 1
Item: (1.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (4.0, 6.0, false)
Item: (3.0, 2.0, false)
Item: (1.0, 2.0, false)
Item: (8.0, 10.0, false)
Item: (1.0, 2.0, true)
Item: (5.0, 1.0, true)
Item: (7.0, 8.0, true)
Item: (6.0, 9.0, false)
Score: 24.0
I’m really not sure but I believe that it could be an issue with how Java implicitly uses references. Can anyone help me out?
Here’s my code and I will outline what is wrong:
in the main method, after starting population is created, I print out what should be the new population with the randomly created samples but what ksim.printPopulation() prints out is not correct. The problem must be with how to create and save the new samples in the second block of code.
package gaknapsack2;
import java.util.List;
import java.util.ArrayList;
public class GAknapsackmain {
public static void main(String[] args) {
float knapsackCapacity = 18.5f;
int startPop = 2;
int populationLimit = 1000;
List<Knapsack> listholder = new ArrayList<Knapsack>(populationLimit);
Item[] items = new Item[10];
items[0] = new Item(1.0f,2.0f,false);
items[1] = new Item(1.0f,2.0f,false);
items[2] = new Item(4.0f,6.0f,false);
items[3] = new Item(3.0f,2.0f,false);
items[4] = new Item(1.0f,2.0f,false);
items[5] = new Item(8.0f,10.0f,false);
items[6] = new Item(1.0f,2.0f,false);
items[7] = new Item(5.0f,1.0f,false);
items[8] = new Item(7.0f,8.0f,false);
items[9] = new Item(6.0f,9.0f,false);
Knapsack itemKnapsack = new Knapsack(items.length,knapsackCapacity,items,0);
kgenetics ksim = new kgenetics(populationLimit,itemKnapsack,knapsackCapacity,startPop);
ksim.addStartingPop();
//ksim.setPopulation(listholder);
ksim.printPopulation();
}
}
package gaknapsack2;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class kgenetics {
private int maxPopulation;
private int startingPopulationSize;
//private Knapsack[] knapsackSamples;
private List<Knapsack> knapsackSamples = new ArrayList<Knapsack>(100);
//the knapsack to base all other knapsacks from
private Knapsack baseKnapsack;
private float knapsackCapacity;
public kgenetics(int mP,Knapsack ks, float capacity, int startPop){
this.maxPopulation = mP;
this.baseKnapsack = ks;
this.knapsackCapacity = capacity;
this.startingPopulationSize = startPop;
}
public float calculateScore(Knapsack k){
float weightTotal = 0.0f;
float valueTotal = 0.0f;
float totalScore = 0.0f;
for(int i = 0; i < k.getNumberOfItems();i++){
if(k.getItemAtIndex(i).isPresent() == true){
weightTotal += k.getItemAtIndex(i).getWeight();
valueTotal += k.getItemAtIndex(i).getValue();
}
}
//if oversize, take items out of knapsack until it is legal weight
if(weightTotal > this.knapsackCapacity){
int i = 0;
while(weightTotal > this.knapsackCapacity){
if(k.getItemAtIndex(i).isPresent() == true){
weightTotal -= k.getItemAtIndex(i).getWeight();
valueTotal -= k.getItemAtIndex(i).getValue();
k.getItemAtIndex(i).setPresent(false);
}
i++;
}
}
totalScore = weightTotal + valueTotal;
return totalScore;
}
public void printPopulation(){
for(int i = 0; i < this.knapsackSamples.size(); i++){
System.out.println("Item " + i);
this.knapsackSamples.get(i).printKnapsack();
System.out.println();
}
}
public void setPopulation(List<Knapsack> r){
this.knapsackSamples = r;
}
public void makeRandomSample(Knapsack k){
for(int i = 0; i < k.getNumberOfItems(); i++){
Random rand = new Random();
float x = rand.nextFloat();
if(x > 0.5){
k.getItemAtIndex(i).setPresent(true);
}
}
}
public void addNew(Knapsack k){
this.knapsackSamples.add(k);
}
public void addStartingPop(){
//Knapsack newKnapsack = new Knapsack(this.baseKnapsack.getNumberOfItems(),this.baseKnapsack.getCapacity(),this.baseKnapsack.getItemsArray(),this.baseKnapsack.getScore());
Knapsack newKnapsack;
for(int i = 0; i < this.startingPopulationSize;i++){
newKnapsack = new Knapsack(this.baseKnapsack.getNumberOfItems(),this.baseKnapsack.getCapacity(),this.baseKnapsack.getItemsArray(),this.baseKnapsack.getScore());
//might be a trouble area if pass by reference or value
//might have to test
newKnapsack.setRandomKnapsackItems(newKnapsack);
//this.makeRandomSample(newKnapsack);
float score = calculateScore(newKnapsack);
newKnapsack.setScore(score);
newKnapsack.setItems(newKnapsack.getItemsArray());
newKnapsack.printKnapsack();
this.knapsackSamples.add(newKnapsack);
}
//return newKnapsack;
}
//create a crossover between knapsacks thus creating a new possible solution
//add the probability for a mutation to occur during cross over
public Knapsack crossOver(Knapsack p1, Knapsack p2){
System.out.print("performing crossover\n");
p1.printKnapsack();
Random r = new Random();
Knapsack newKnapsack = new Knapsack(p1.getNumberOfItems(),p1.getCapacity(),p1.getItemsArray(),p1.getScore());
//Knapsack newKnapsack = new Knapsack();
//newKnapsack = p1;
//newKnapsack.printKnapsack();
//no bigger crossover than half of the number of items in knapsack
int rangeCrossover = r.nextInt(this.baseKnapsack.getNumberOfItems()/2);
int positionStart = r.nextInt(this.baseKnapsack.getNumberOfItems());
int positionEnd = (positionStart + rangeCrossover);
System.out.println("Crossover - posStart: "+ positionStart + " posEnd: " + positionEnd);
for(int i = 0; i < this.baseKnapsack.getNumberOfItems();i++){
if(i >= positionStart && i <= positionEnd){
newKnapsack.setItemAtIndex(i, p2.getItemAtIndex(i).isPresent());
}
}
System.out.print("finished crossover\n");
newKnapsack.printKnapsack();
return newKnapsack;
}
//create the reproduction function that performs the crossover on all knapsacks
public void reproduction(){
for(int i = 0; i < this.knapsackSamples.size();i+=2){
if(this.knapsackSamples.get(i + 1) != null){
Knapsack child = new Knapsack();
//Knapsack child = new Knapsack(p1.getNumberOfItems(),p1.getCapacity(),p1.getItemsArray(),p1.getScore());
//child.copyKnapsack(this.knapsackSamples.get(i));
//child.printKnapsack();
child = this.crossOver(this.knapsackSamples.get(i),this.knapsackSamples.get(i + 1));
child.setScore(this.calculateScore(child));
System.out.println("new child");
//child.printKnapsack();
Knapsack addthis = new Knapsack(child.getNumberOfItems(),child.getCapacity(),child.getItemsArray(),child.getScore());
//addthis.printKnapsack();
this.knapsackSamples.add(addthis);
}
}
}
}
the Knapsack object as requested:
package gaknapsack2;
import java.util.Random;
public class Knapsack{
private int totalNumberOfItems;
private float knapSackCapacity;
private Item[] knapsackItems;
private float knapsackScore;
private float weight;
private float value;
public Knapsack(int totalNumOfItems, float cap, Item[] items, float s){
this.totalNumberOfItems = totalNumOfItems;
this.knapSackCapacity = cap;
this.knapsackItems = items;
this.knapsackScore = s;
}
public Knapsack(){
this.totalNumberOfItems = 0;
this.knapSackCapacity = 0;
this.knapsackItems = null;
this.knapsackScore = 0;
}
//randomly select items from the baseknapsack that was instaniated and
//set Items in it to have itemPresent = true
public void setRandomKnapsackItems(Knapsack k){
for(int i = 0; i < this.totalNumberOfItems; i++){
Random rand = new Random();
float x = rand.nextFloat();
if(x > 0.5){
k.knapsackItems[i].setPresent(true);
}
}
}
public void setItemAtIndex(int i, boolean b){
this.knapsackItems[i].setPresent(b);
}
public void setItems(Item[] i){
this.knapsackItems = i;
}
public Item getItemAtIndex(int i){
return this.knapsackItems[i];
}
public int getNumberOfItems(){
return this.totalNumberOfItems;
}
public float getCapacity(){
return this.knapSackCapacity;
}
public Item[] getItemsArray(){
Item[] copy = this.knapsackItems;
return copy;
}
public float getScore(){
return this.knapsackScore;
}
public void setScore(float f){
this.knapsackScore = f;
}
public Knapsack copyKnapsack(Knapsack k){
Knapsack kNew = new Knapsack();
kNew.totalNumberOfItems = k.totalNumberOfItems;
kNew.knapSackCapacity = k.knapSackCapacity;
for(int i = 0; i < k.totalNumberOfItems;i++){
kNew.knapsackItems[i] = k.knapsackItems[i].returnCopyOfItem();
}
kNew.knapsackScore = k.knapsackScore;
kNew.printKnapsack();
return kNew;
}
public void printKnapsack(){
for(int i = 0; i < this.totalNumberOfItems;i++){
this.knapsackItems[i].printItem();
}
System.out.println("Score: " + this.knapsackScore);
}
}
If you follow the code in the main method. You see a called where ksim(responsible for added the knapsack object) to an arraylist that ksim has as a member. This should retain the random knapsacks added to the arraylist in the function addStartPop() But when I print the population after this in main, the values are wrong
I have been trying to figure this out for a while now. Please help and I can should more code if need be. Thanks
It seems that kgen keeps a copy of a knapsack (baseKnapsack), and then you use this knapsack’s array everywhere. If you pass the list from baseKnapsack to each new Knapsack item you create, they’ll all be using the same list. Instead of
Try something like this: