0

I practice using this library, Jenetics.io. In their manual they have an example, Traveling salesman. The example only shows the minimum path found, but does not show the point set or point order of the solution. How do I get the set of points of the solution?

the manual.. page 129 enter link description here

to run the code, the result:

[[D@79fc0f2f|[D@37a71e93|[D@4783da3f|[D@6e2c634b|[D@49097b5d|[D@378fd1ac|[D@5e9f23b4|[D@2dda6444|[D@50040f0c] -> 16.46284073991415

the code that I use:

public class EncotrarRuta implements Problem<ISeq<double[]>,EnumGene<double[]>,Double>{

private final ISeq<double[]> _points;
private ArrayList<Double> puntosX = new ArrayList<>();
private ArrayList<Double> puntosY = new ArrayList<>();


public EncotrarRuta(ArrayList<Double> puntosX, ArrayList<Double> puntosY) {
    this._points = null;
    this.puntosX = puntosX;
    this.puntosY = puntosY;
}


public EncotrarRuta(ISeq<double[]> points) {
    this._points = requireNonNull(points);
}

@Override
public Function<ISeq<double[]>, Double> fitness() {
    return p -> IntStream.range(0, p.length())
        .mapToDouble(i -> {
            final double[] p1 = p.get(i);
            final double[] p2 = p.get((i+1)%p.size());
            return hypot(p1[0]-p2[0],p1[1]-p2[1]);
        }).sum();
}

@Override
public Codec<ISeq<double[]>, EnumGene<double[]>> codec() {
    return Codecs.ofPermutation(_points);
}

public static EncotrarRuta of(ArrayList<Double> puntosX, ArrayList<Double> puntosY){
    final MSeq<double[]> points = MSeq.ofLength(puntosX.size());
    
    for (int i = 0; i < puntosX.size(); i++) {
        points.set(i, new double[]{puntosX.get(i),puntosY.get(i)});
    }

    return new EncotrarRuta(points.asISeq());
}

public void run() {

    EncotrarRuta encotrarRuta = EncotrarRuta.of(puntosX, puntosY);

    Engine<EnumGene<double[]>,Double> engine = Engine
        .builder(encotrarRuta)
        .optimize(Optimize.MINIMUM)
        .maximalPhenotypeAge(11)
        .populationSize(500)
        .alterers(
            new SwapMutator<>(0.2),
            new PartiallyMatchedCrossover<>(0.35))
        .build();

    EvolutionStatistics<Double, ?> statistics = EvolutionStatistics.ofNumber();

    Phenotype<EnumGene<double[]>,Double> best = engine.stream()
        .limit(bySteadyFitness(25))
        .limit(250)
        .peek(statistics)
        .collect(toBestPhenotype());


    System.out.println(best);
   

}

}

2 Answers2

0

For converting the best Phenotype in an actual route, you can use the Codec. In your example it will look like this:

final Phenotype<EnumGene<double[]>, Double> best = ...;
final ISeq<double[]> route = encotrarRuta.codec().decode(best.genotype());

You can find another TSP example in the example module: TravelingSalesman.java. This examples uses real GPS WayPoints from the JPX library.

  • That just shows me the same result. – leon kennedy Sep 25 '21 at 00:43
  • That's because of your point representation as `double[]`. Using a own data type for your point, e.g. `record Point(double x, double y){}`, would print it correctly and also would make the code more readable. The a route would be _just_ a sequence of points: `ISeq route = ...;`, which can be printed in the way you expect. – Franz Wilhelmstötter Sep 25 '21 at 06:23
0

I found the solution, or what I wanted to obtain,

best.genotype().chromosome().iterator().forEachRemaining(i -> {
        for (double ds : i.allele()) {
            System.out.println(ds);
        }
    });

with that I get the list of points of the solution

[[D@7cd84586|[D@30dae81|[D@1b2c6ec2|[D@4769b07b|[D@4edde6e5|[D@66a29884|[D@1e80bfe8|[D@70177ecd] -> 12.65685424949238
1.0
1.0
2.0
2.0
3.0
3.0
3.0
1.0
4.0
1.0
6.0
1.0
6.0
3.0
5.0
4.0