我想修改与ArrayList中其他对象具有相似值的ArrayList对象(我们称其为myObject)。
问题在于,当我修改myObject时,事实证明其他具有相似值的对象也将被修改。
此问题可能是什么原因? 您的回答将对我有很大帮助。
哦,我正在研究遗传算法,该算法由3类{Genetic_Controller,Chromosome,Fitness_Function}组成。我认为此问题发生在Genetic_Controller的“ MutateAtPopulationScale”过程中。
这是我的源代码:
Genetic_Controller
package AG;
import java.text.DecimalFormat;
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
public class Genetic_Controller {
public ArrayList<Chromosome> ChromosomeArray; //arraylist containing some Chromosome
private int popSize; // starting number of antibodies
private double pc; // crossover probability
private double pm; // mutation probability
private int maxGen; // maximal reach of generation
private double optimumPrice;
Random r = new Random();
DecimalFormat df = new DecimalFormat("#,###,###,##0");
public Genetic_Controller(int popSize,double pm, int maxGen) {
this.ChromosomeArray = new ArrayList();
this.popSize = popSize;
this.pm = pm;
this.maxGen = maxGen;
}
public double getOptimumPrice() {
return optimumPrice;
}
private double[][] pricesData;
private int genLength;
public void goOptimise(double[][] pricesData, int dataSize) {
this.pricesData = pricesData;
this.genLength = dataSize;
GeneratePopulation();
System.out.println();
for (int g = 0; g < maxGen; g++) {
System.out.println("Generation : " + (g + 1));
ChromosomeSelection();
MutateAtPopulationScale();
ReplacedPopulation();
EvaluateAllChromosome();
System.out.println();
}
}
public void GeneratePopulation() {
Chromosome c;
for (int i = 0; i < popSize; i++) {
c = new Chromosome(genLength);
c.evaluate(pricesData);
ChromosomeArray.add(c);
}
}
public void printPopulation(ArrayList ChromosomeArray) {
int count = 0;
for (Iterator<Chromosome> it = ChromosomeArray.iterator(); it.hasNext();) {
Chromosome c = it.next();
System.out.print((count+1)+". ");
for (int i = 0; i < genLength; i++) {
System.out.print(c.gen.get(i) + " ");
}
System.out.print("__ Price : " + (int) (1000000 / c.getFitness()) + " __ Fitness : " + df.format(c.getFitness()));
System.out.println();
count++;
}
}
public void EvaluateAllChromosome() {
for (Iterator<Chromosome> it = this.ChromosomeArray.iterator(); it.hasNext();) {
Chromosome c = it.next();
c.evaluate(pricesData);
}
}
// Chromosome Selection use Roulette Wheel Selection
public void ChromosomeSelection() {
double totFitness = 0;
double[] RelativeFit = new double[popSize];
double[] CumulativeFit = new double[popSize];
double CumulativeMemory = 0;
ArrayList<Chromosome> NewChromosomeArray = new ArrayList();
for (Iterator<Chromosome> it = this.ChromosomeArray.iterator(); it.hasNext();) {
Chromosome c = it.next();
totFitness = totFitness + c.getFitness();
}
int count = 0;
for (Iterator<Chromosome> it = this.ChromosomeArray.iterator(); it.hasNext();) {
Chromosome c = it.next();
RelativeFit[count] = c.getFitness() / totFitness;
CumulativeFit[count] = CumulativeMemory + RelativeFit[count];
CumulativeMemory = CumulativeFit[count];
count++;
}
double[] rand = new double[popSize];
int temp;
for (int i = 0; i < popSize; i++) {
temp = r.nextInt(1 * 100) + (0);
rand[i] = (double) temp / 100;
for (int j = 0; j < popSize; j++) {
if (CumulativeFit[j] <= rand[i] && CumulativeFit[j + 1] > rand[i]) {
NewChromosomeArray.add(i, ChromosomeArray.get(j + 1));
break;
} else if (rand[i] < CumulativeFit[0]) {
NewChromosomeArray.add(i, ChromosomeArray.get(0));
break;
}
}
}
ChromosomeArray.clear();
ChromosomeArray.addAll(NewChromosomeArray);
}
// Function to add new chromosome to population directly proportional to their fitness values.
public void ReplacedPopulation() {
Collections.sort(ChromosomeArray);
// for (int i = ChromosomeArray.size() - 1; i >= popSize; i--) {
// ChromosomeArray.remove(i);
// }
// System.out.println();
System.out.println("Result Of Replaced Population");
printPopulation(ChromosomeArray);
}
public void MutateAtPopulationScale() {
ArrayList<Integer> mutation_index = new ArrayList();
double[] rand = new double[popSize];
int temp;
System.out.println();
System.out.println("Randomize Result for Mutation");
for (int i = 0; i < popSize; i++) {
temp = r.nextInt(1 * 100) + (0);
rand[i] = (double) temp / 100;
System.out.print(rand[i]+" ");
if (rand[i] < pm) {
mutation_index.add(i);
}
}
System.out.println();
System.out.println("Parent Index that occured mutation");
for (int i = 0; i < mutation_index.size(); i++) {
System.out.println(mutation_index.get(i));
}
int gen1, gen2 = -1;
int gen_temp;
System.out.println("Selected Position of Allels");
for (int i = 0; i < mutation_index.size(); i++) {
// Randomly choose 2 allels position
gen1 = r.nextInt(genLength) + (0);
gen2 = r.nextInt(genLength) + (0);
while (gen2 == gen1) {
gen2 = r.nextInt(genLength) + (0);
}
System.out.println("C"+(i+1)+" : "+gen1+" dan "+gen2);
System.out.println("Index : "+i);
ChromosomeArray.get(mutation_index.get(i)).Mutate(gen1, gen2);
}
System.out.println();
EvaluateAllChromosome();
System.out.println("Mutation Results");
printPopulation(ChromosomeArray);
}
}
染色体
package AG;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class Chromosome implements Comparable<Chromosome>{
ArrayList<Integer> gen; // xValues
private double fitness;
private static Random rand = new Random();
public ArrayList<Integer> getGen() {
return gen;
}
public double getFitness() {
return fitness;
}
public Chromosome(int size) {
this.gen = new ArrayList<>(size);
RandomizeGen(size);
}
public Chromosome(int size, int nil){
this.gen = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
gen.add(nil);
}
}
public void RandomizeGen(int size) {
for (int i = 1; i <= size; i++) {
gen.add(i);
}
Collections.shuffle(gen);
}
public void evaluate(double[][] prices) {
fitness = AG.Fitness_Function.evaluateFunction(gen,prices);
}
public void Mutate(int genPos1, int genPos2){
int temp;
temp = gen.get(genPos1);
gen.set(genPos1, gen.get(genPos2));
gen.set(genPos2, temp);
}
@Override
public int compareTo(Chromosome c) {
int compareFitness = (int)((Chromosome) c).getFitness();
return compareFitness-(int)this.fitness;
}
}
健身功能
public class Fitness_Function {
public Fitness_Function() {
} //empty constructor
public static double evaluateFunction(ArrayList<Integer> gen, double[][] prices) {
double totalHarga = 0;
double fitness;
for (int j = 0; j < prices.length; j++) {
totalHarga = totalHarga + prices[j][gen.get(j) - 1];
}
fitness = (1 / totalHarga) * 1000000;
return fitness;
}
}
让我给你一个简单的例子,说明实际发生的情况:
chromosome-1:1234
2号染色体:3421(2和4具有相似的值)
3号染色体:1324
4号染色体:3421(2和4具有相似的值)
选择2号染色体进行突变...
阿勒尔号选择1和2进行突变...
突变结果-> Chromosome-2:4321
更新人口...
1号染色体:1234
第2号染色体:4321
3号染色体:1324
4号染色体:4321(也对4号染色体进行了修饰)
答案 0 :(得分:0)
我认为可能正在发生的事情是,您实际上并没有创建新的染色体,而是两次添加相同的染色体对象。 Java中的对象是通过引用创建的,因此创建类似
的对象NewChromosomeArray.add(0, ChromosomeArray.get(0))
NewChromosomeArray.add(1, ChromosomeArray.get(0))
不会创建新对象,而是将来自ChromosomeArray索引0的引用添加到NewChromosomeArray的两个位置,因此NewChromosomeArray索引0的染色体也将出现在NewChromosomeArray索引1的染色体中,因为它们只是同一条染色体被引用两次。
确保不会再次发生这种情况的一种方法是使染色体和不可变的对象像本机字符串类。
public class Chromosome implements Comparable<Chromosome>{
ArrayList<Integer> gen; // xValues
private double fitness;
private static Random rand = new Random();
public ArrayList<Integer> getGen() {
return new ArrayList<>(gen);
}
public double getFitness() {
return fitness;
}
public Chromosome(ArrayList<String> gen) {
this.gen = new ArrayList<>(gen);
}
public Chromosome(int size) {
this.gen = new ArrayList<>(size);
RandomizeGen(size);
}
public Chromosome(int size, int nil){
this.gen = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
gen.add(nil);
}
}
public void RandomizeGen(int size) {
for (int i = 1; i <= size; i++) {
gen.add(i);
}
Collections.shuffle(gen);
}
public void evaluate(double[][] prices) {
fitness = AG.Fitness_Function.evaluateFunction(gen,prices);
}
public Chromosome Mutate(int genPos1, int genPos2){
int temp;
ArrayList<Integer> newGen = new ArrayList<>(gen);
temp = newGen.get(genPos1);
newGen.set(genPos1, gen.get(genPos2));
newGen.set(genPos2, temp);
return new Chromosome(newGen)
}
@Override
public int compareTo(Chromosome c) {
int compareFitness = (int)((Chromosome) c).getFitness();
return compareFitness-(int)this.fitness;
}
}
这样,您每次更改基因组时都会创建一条新染色体。