question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

fitness function with more than one parameters

See original GitHub issue

Does Jenetics even support fitness function with multiple parameters??

I have the following fitness function

public static double func(double a, double b, double c) {
        // f(a, b, c) = 3 * cos(a)^4 + 4 * cos(b)^3 + 2 sin(c)^2 * cos(c)^2 + 5 
        return 3 * Math.pow(Math.cos(a), 4) + 4 * Math.pow(Math.cos(b), 3) +
                2 * Math.pow(Math.sin(c), 2) * Math.pow(Math.cos(c), 2) + 5;
}

Is the following use of Codec.of correct???

final Codec<Double, DoubleGene> PARAM = Codecs.ofScalar(DoubleRange.of(1, Math.PI));

        final Codec<Double, DoubleGene> CODEC = Codec.of(
                ISeq.of(PARAM, PARAM, PARAM),
                params -> {
                    final double param1 = (double) params[0];
                    final double param2 = (double) params[1];
                    final double param3 = (double) params[2];

                    return 0.0;
                }
        );      

        final Engine<DoubleGene, Double> engine = Engine
                .builder(JeneticsDemo6::func, CODEC)
                    .populationSize(500)
                    .optimize(Optimize.MAXIMUM)
                    .offspringSelector(new StochasticUniversalSelector<>())
                    .alterers(new Mutator<>(0.03), new MeanAlterer<>(0.5))
                    .build();

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
jeneticscommented, Jul 2, 2019

Hi @zollen, your fitness function can’t have more than one parameter. If you need three double values, you have to wrap it into an array. There are predefined factory methods for doing this:

private static double func(final double[] x) {
    final double a = x[0];
    final double b = x[1];
    final double c = x[2];
    return 0; // Implement your fitness function.
}

public static void main(final String args) {
    final Codec<double[], DoubleGene> codec = Codecs
        .ofVector(DoubleRange.of(1, Math.PI), 3);

    final Engine<DoubleGene, Double> engine = Engine.builder(Main::func, codec)
        .populationSize(500)
        // other Engine config
        .build();
}

The example above will do the trick.

1reaction
jeneticscommented, Jul 3, 2019

You have two possibilities in this situation. 1) you can only create valid values, the simpler one, or 2) you can use the Constraint interface.

Ad 1)

public class Main {

    void normalizedVersion() {
        final Codec<double[], DoubleGene> codec = Codecs
            .ofVector(DoubleRange.of(0, 1), 4)
            .map(Main::normalize);
    }

    private static double[] normalize(final double[] x) {
        double[] r = x;
        final double sum = r[0] + r[1] + r[2];
        if (sum != 1) {
            r[0] /= sum;
            r[1] /= sum;
            r[2] /= sum;
        }
        if (r[3] > 0.8) {
            r[3] = 0.8;
        }
        return r;
    }
}

Ad 2)

public class Main {

    void constrainedVersion() {
        final Codec<double[], DoubleGene> codec = Codecs
            .ofVector(DoubleRange.of(0, 1), 4);

        final Constraint<DoubleGene, Double> constraint = Constraint.of(
            pt -> isValid(codec.decode(pt.getGenotype())),
            (pt, g) -> {
                final double[] r = normalize(codec.decode(pt.getGenotype()));
                return newPT(r, g);
            }
        );
    }

    private static Phenotype<DoubleGene, Double> newPT(final double[] r, final long gen) {
        final Genotype<DoubleGene> gt = Genotype.of(
            DoubleChromosome.of(
                DoubleStream.of(r).boxed()
                    .map(v -> DoubleGene.of(v, DoubleRange.of(0, 1)))
                    .collect(ISeq.toISeq())
            )
        );
        return Phenotype.of(gt, gen);
    }

    private static boolean isValid(final double[] x) {
        return x[0] + x[1] + x[2] == 1 && x[3] > 0.8;
    }
}

I would prefer the first version, since it doesn’t create invalid values. In version 2) you have to add the Constraint to the engine builder.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Passing multiple parameters to the fitness function
I'm trying to pass one more argument to my fitness function: def eval_fitness(individual, mode):. When I call "toolbox.evaluate(individual, mode)" it works, ...
Read more >
How to define a Fitness Function in a Genetic Algorithm?
Given a set of 5 genes, which can hold one of the binary values 0 and 1, we have to come up with...
Read more >
Coding and minimizing a fitness function using the Genetic ...
This is a demonstration of how to create and minimize a fitness function using the Genetic Algorithm in the Genetic Algorithm and Direct...
Read more >
returning additional values from a fitness function for genetic ...
Is there a simple way to return additional values from a fitness function (in addition to the objective value) when using an optimisation...
Read more >
Should all the variables in a fitness function be the same in ...
Let's say my fitness function will be cost(a) + cost(b) + cost(c) + cost(d), where the unit for cost(a) and cost(b) is in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found