I'm using Jenetics to nest a list of polygons using NoFitPolygon
I have a function that gived a list of polygon nests them following the order in the list.
I adapted the TravellingSalesman problem in order to have a genotype that represent the list of polygons, and during evolution the order change.
Now I want to add the rotation to the genotype, in order to get better results, but I don't know how to add it to my code.
Currently the order of the nestpaths determines the fitness, what i want to do is add, for every nestpath, a double value (doubleChromosome?) to the genotype that represent the rotation of the nestpath.
Nestpath is the class that represent the polygon
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);
}
Main:
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);
}