-1

我现在应该真的知道问题出在哪里,但我遇到了麻烦。我的问题是Java Arraylist。我正在尝试通过类方法(kgenetics 类中的 addStartingPop)将对象添加到数组列表中。这个方法在 main 中被调用,它应该更新 kgenetics 的类成员,它是一个 arrayList。在 main 中调用 addStartPop() 后,我尝试在 main 中打印出新的人口。但是,如果您注意到,Item 数组并不是我期望的那样。问题:问题是这些值确实被添加到了数组列表中,但似乎它们并没有完全修改我想要的样子。

这是运行程序的输出:

这是调用 addStartPop() 之后 Arraylist 中应该包含的内容

我在将每个背包添加到 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

当我在 main 方法中打印样本时,这就是打印出来的。分数(根据构成项目的两个数字计算)是正确的,但数组是最后添加的数组)

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

我真的不确定,但我相信这可能是 Java 如何隐式使用引用的问题。谁能帮我吗?

这是我的代码,我将概述问题所在:

在主要方法中,在创建开始人口后,我用随机创建的样本打印出新人口应该是什么,但 ksim.printPopulation() 打印出的内容不正确。问题一定是如何在第二个代码块中创建和保存新样本。

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);
        }
    }
}

}

根据要求的背包对象:

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);
}
}

如果您遵循 main 方法中的代码。您会看到一个名为 where ksim(负责添加背包对象)到 ksim 作为成员的数组列表。这应该保留在函数 addStartPop() 中添加到数组列表中的随机背包但是当我在 main 中打印此之后的人口时,值是错误的

我一直试图弄清楚这一点。请帮助,如果需要,我可以提供更多代码。谢谢

4

1 回答 1

1

看来kgen保留了一个背包(baseKnapsack)的副本,然后你到处使用这个背包的数组。如果您将列表从 baseKnapsack 传递到您创建的每个新背包项目,它们都将使用相同的列表。代替

    newKnapsack = new Knapsack(this.baseKnapsack.getNumberOfItems(),this.baseKnapsack.getCapacity(),**this.baseKnapsack.getItemsArray()**,this.baseKnapsack.getScore());

尝试这样的事情:

    newKnapsack = new Knapsack(this.baseKnapsack.getNumberOfItems(),this.baseKnapsack.getCapacity(),**new Item[baseKnapsack.totalNunberOfItems]**,this.baseKnapsack.getScore());
于 2012-10-17T13:48:14.670 回答