我有一个名为Operators
的类,它包含三个静态方法:crossover
,mutate
,bestOffSpring
。我在另一个类中调用这些方法,例如:
List<Cell> offSpring = Operators.crossover(parent1, parent2);
Cell bestOffSpring = Operators.bestOffSpring(offSpring);
Cell mutatedChild = Operators.mutate(bestOffSpring);
我遇到的问题是,当我拨打crossover
和bestOffSpring
时,他们的结果会正确生成。但是,当我调用mutate
方法时,其他两个方法的结果不正确。换句话说,调用crossover
方法会影响bestOffSpring
和mutate
的结果。我检查了三种方法的逻辑,但没有发现任何错误。
我的问题是从一个类调用许多静态方法会影响它们的结果吗?
以下是三种方法的代码:
public class Operators {
public static List<Cell> crossover(Cell parenta_,Cell parentb_)
{
BitSet parenta = parenta_.getChrom();
BitSet parentb = parentb_.getChrom();
Random rand = new Random();
int setLength = parenta.length();
//System.out.println("<"+setLength+">");
BitSet child1 = new BitSet(setLength);
BitSet child2 = new BitSet(setLength);
//One point splicing
int slicePoint = rand.nextInt(setLength); //rnd num between 0-70
System.out.print("<"+slicePoint+">");
BitSet a = (BitSet)parenta.clone();
a.clear(slicePoint,setLength);
BitSet b = (BitSet)parenta.clone();
b.clear(0,slicePoint);
BitSet c = (BitSet)parentb.clone();
c.clear(slicePoint,setLength);
BitSet d = (BitSet)parentb.clone();
d.clear(0,slicePoint);
//Combine start of p1 with end of p2
child1.or(a);
child1.or(d);
//Combine start of p2 with end of p1
child2.or(c);
child2.or(b);
//Return the children
//BitSet[] offspring = {child1, child2};
Cell child1_ = new Cell(child1);
Cell child2_ = new Cell(child2);
System.out.print("C1 = " + child1_.printBit());
System.out.print(", C2 = " + child2_.printBit() + " ");
List<Cell> offSpring = new ArrayList<>();
offSpring.add(child1_);
offSpring.add(child2_);
return offSpring;
}
public static Cell mutate(Cell original_){
BitSet original = original_.getChrom();
Double mProb = 0.4;
Random rand = new Random();
for(int m = 0; m < original.length(); m++)
{
//Small possibility a bit copied from parent to child is mutated
if(rand.nextDouble() <= mProb)
original.flip(m);
}
//Return the (possibly) strategy
Cell mutated = new Cell(original);
return mutated;
}
public static Cell bestOffSpring(List<Cell> offSpring){
int offSpringFit1 = offSpring.get(0).getFitness();
int offSpringFit2 = offSpring.get(1).getFitness();
if (offSpringFit1 > offSpringFit2)
return offSpring.get(0);
else
return offSpring.get(1);
}
}
以下是一个例子,调用crossover和bestOffSpring的正确结果是:
OffSpring are 100111 <4> and 111101 <5>, best is 111101
OffSpring are 101010 <3> and 111101 <5>, best is 111101
OffSpring are 101111 <5> and 110101 <4>, best is 101111
OffSpring are 110111 <5> and 110111 <5>, best is 110111
OffSpring are 101101 <4> and 110111 <5>, best is 110111
OffSpring are 101010 <3> and 111010 <4>, best is 111010
当调用mutate方法时,结果为:
OffSpring are 101101 <4> and 100110 <5>, best is 100110
OffSpring are 101010 <3> and 1100 <5>, best is 1100
OffSpring are 100111 <4> and 10101 <5>, best is 10101
OffSpring are 110111 <5> and 111100 <5>, best is 111100
OffSpring are 101100 <5> and 110101 <4>, best is 101100
OffSpring are 11101 <4> and 101010 <3>, best is 11101
两个结果之间的差异在于正确结果中的两个后代具有正确的长度(在每个后代中有多少1个)并且其中最好的是正确选择的。虽然后者没有给出正确的长度然后产生错误的最佳后代。
答案 0 :(得分:1)
副作用 ...
if(rand.nextDouble() <= mProb)
original.flip(m);
...
可以假设original_.getChrom()
直接返回基础BitSet,因此您最终会翻转bestOffSpring
的叮咬,这会在您运行mutate()
后影响健身功能得分。
要避免副作用,只需创建原始Bitset的副本
Bitset original = new Bitset(original_.getChrom().size());
original.or(original_.getChrom().size())