自定义基因型遗传学筑巢



我使用遗传学嵌套一个多边形列表使用NoFitPolygon

我有一个函数,它给出了一个多边形巢的列表,它们按照列表中的顺序排列。

我调整了TravellingSalesman问题,以便有一个表示多边形列表的基因型,并且在进化过程中顺序发生了变化。

现在我想在基因型中添加旋转,以获得更好的结果,但我不知道如何将其添加到我的代码中。

目前巢路径的顺序决定了适合度,我想做的是为每个巢路径添加一个双值(doublechromsome ?)到代表巢路径旋转的基因型。

Nestpath是表示多边形

的类。
public class NFP_Nesting implements Problem<ISeq<NestPath>, EnumGene<NestPath>, Double>{
static Phenotype<EnumGene<NestPath>,Double> tmpBest = null;
static Result tmpBestResult =null;
private NestPath _binPolygon;
Map<String,List<NestPath>> nfpCache=new HashMap<>();
private final ISeq<NestPath> _list;
public NFP_Nesting(ISeq<NestPath> lista,NestPath binpolygon ,double binw, double binh) 
{
_binPolygon = binpolygon;
_list=Objects.requireNonNull(lista);
}
@Override
public Codec<ISeq<NestPath>, EnumGene<NestPath>> codec() {
return Codecs.ofPermutation(_list);
}
@Override
public Function<ISeq<NestPath>, Double> fitness() {
return this::scalar_fitness;
}

/**
* @param seq_nestpath
* @return Fitness of the model
*/
Double scalar_fitness(final ISeq<NestPath> seq_nestpath) {
List<NestPath> paths = seq_nestpath.asList();
final Random random = RandomRegistry.random();

//TODO NOT RANDOM ROTATION
List<Integer> ids = new ArrayList<>();  
for(int i = 0 ; i < paths.size(); i ++){
ids.add(paths.get(i).getId());
NestPath n = paths.get(i);
if(n.getPossibleRotations()!= null)
{
n.setRotation(n.getPossibleRotations()[random.nextInt(n.getPossibleRotations().length)]);
}
}

///complicated function here

return fitness;
}

private static NFP_Nesting of (List<NestPath> l, NestPath binpol, double binw, double binh)
{
final MSeq<NestPath> paths = MSeq.ofLength(l.size());
final Random random = RandomRegistry.random();
for ( int i = 0 ; i < l.size(); ++i ) {         
paths.set(i, l.get(i));
}
//initial shuffle list of polygons
for(int j=paths.length()-1; j>0;--j)
{
final int i = random.nextInt(j+1);
final NestPath tmp=paths.get(i);
paths.set(i, paths.get(j));
paths.set(j, tmp);
}
return new NFP_Nesting(paths.toISeq(),binpol,binw,binh);
}

主:

public static void main(String[] args) {


ExecutorService executor = Executors.newFixedThreadPool(1);
NFP_Nesting nst = NFP_Nesting.of(tree,binPolygon,binWidth,binHeight);
Engine<EnumGene<NestPath>,Double> engine = Engine
.builder(nst)
.optimize(Optimize.MINIMUM)
.populationSize(config.POPULATION_SIZE)
.executor(executor)
.alterers(
new SwapMutator<>(0.25),
new PartiallyMatchedCrossover<>(0.35)
)
.build();

final EvolutionStatistics<Double, ?> statistics = EvolutionStatistics.ofNumber();   
Phenotype<EnumGene<NestPath>,Double> best=
engine.stream()
.limit(Limits.bySteadyFitness(5))
.limit(Limits.byExecutionTime(Duration.ofSeconds(MAX_SEC_DURATION)))
//.limit(10)
.peek(NFP_Nesting::update)
.peek(statistics)
.collect(toBestPhenotype());
System.out.println(statistics);
//System.out.println(best);

}

我想我现在明白你的问题了。你要做的是在基因型中编码一个额外的旋转。但是遗传学只允许一个基因型有一个基因型。使用排列编解码器,您将基因类型固定为EnumGene,并且对于您的旋转,您将需要DoubleGene。用一个简单的技巧,我们可以用染色体内基因的顺序来表达路径排列,也可以表达DoubleGene

下面的代码将告诉您如何做到这一点。

import static java.util.Objects.requireNonNull;
import java.util.function.Function;
import java.util.stream.IntStream;
import io.jenetics.DoubleChromosome;
import io.jenetics.DoubleGene;
import io.jenetics.Genotype;
import io.jenetics.MeanAlterer;
import io.jenetics.Phenotype;
import io.jenetics.SwapMutator;
import io.jenetics.engine.Codec;
import io.jenetics.engine.Engine;
import io.jenetics.engine.EvolutionResult;
import io.jenetics.engine.Limits;
import io.jenetics.engine.Problem;
import io.jenetics.example.NfpNesting.Solution;
import io.jenetics.util.DoubleRange;
import io.jenetics.util.ISeq;
import io.jenetics.util.ProxySorter;
public class NfpNesting implements Problem<Solution, DoubleGene, Double> {
record NestPath() {}
record Solution(ISeq<NestPath> paths, double[] rotations) {
Solution {
assert paths.length() == rotations.length;
}
}
private final Codec<Solution, DoubleGene> code;

public NfpNesting(final ISeq<NestPath> paths) {
requireNonNull(paths);
code = Codec.of(
Genotype.of(
// Encoding the order of the `NestPath` as double chromosome.
// The order is given by the sorted gene values.
DoubleChromosome.of(DoubleRange.of(0, 1), paths.length()),
// Encoding the rotation of each `NestPath`.
DoubleChromosome.of(DoubleRange.of(0, 2*Math.PI), paths.length())
),
gt -> {
/*
The `order` array contains the sorted indexes.
This for-loop will print the genes in ascending order.
for (var index : order) {
System.out.println(gt.get(0).get(index));
}
*/
final int[] order = ProxySorter.sort(gt.get(0));
// Use the `order` indexes to "permute" your path elements.
final ISeq<NestPath> pseq = IntStream.of(order)
.mapToObj(paths::get)
.collect(ISeq.toISeq());
// The second chromosome just contains your rotation values.
final double[] rotations = gt.get(1)
.as(DoubleChromosome.class)
.toArray();
return new Solution(pseq, rotations);
}
);
}
@Override
public Codec<Solution, DoubleGene> codec() {
return code;
}
@Override
public Function<Solution, Double> fitness() {
return solution -> {
final ISeq<NestPath> paths = solution.paths();
final double[] rotations = solution.rotations();
// Do your fitness calculation.
return 0.0;
};
}
public static void main(final String[] args) {
final var paths = ISeq.<NestPath>of();
final var nesting = new NfpNesting(paths);
final Engine<DoubleGene, Double> engine = Engine.builder(nesting)
.alterers(
new MeanAlterer<>(),
new SwapMutator<>())
.build();
final Phenotype<DoubleGene, Double> best = engine.stream()
.limit(Limits.bySteadyFitness(5))
.collect(EvolutionResult.toBestPhenotype());
System.out.println("Best Fitness: " + best.fitness());
System.out.println("Best paths: " + nesting.decode(best.genotype()).paths());
}
}

我不确定我是否完全理解你想要解决的问题,但是排列编解码器(Codecs.ofPermutation(Seq))用于给定对象序列的顺序决定其适应性的问题。所以,只有NestPath元素在ISeq<NestPath>中的顺序才能定义适应度,对吧?适应度函数不负责通过副作用改变对象。

我也不明白你说的旋转基因型是什么意思。遗传学中的Genotype只是一个染色体序列。也许你可以更详细地解释你的优化问题。

对代码本身的一些注释

  • NFP_Nesting::of对给定的List<NestPath>进行洗牌。这是不必要的。
  • .peek(NFP_Nesting::update)做一些更新看起来也很可疑。如果需要更新NestPath对象,则不再需要进行排列优化。NestPath应该是不可变的。
  • 不要在Problem实现中存储任何静态变量。Problem接口只是结合了Codec和适应度函数,应该是不可变的。

所以,如果你能更清楚地解释你的问题,我可以试着帮助找到一个合适的编码。

相关内容

  • 没有找到相关文章

最新更新