0

I have a problem understanding the process for genetic algorithms. I found examples of maximizing a function over an interval, and I think I understand them, but how can a genetic algorithm be used to solve, for example, a quadratic equation?

Assuming that we want to find a solution up to 4 digits, what is a proper representation to encode the numbers? What can be used as the fitness function to evaluate each number?

Any help is appreciated

Farzad
  • 1,770
  • 4
  • 26
  • 48

3 Answers3

1

If you want to solve a quadratic equation

a * x^2 + b * x + c = 0

then you need only one variable x as representation. You can use

f(x) = abs(a * x^2 + b * x + c)

as fitness function, which is the same as the precision then, so it needs to be minimized.

But with only one variable it's hard to do crossovers, you can use 10 numbers per individual and then take the average to get x, or just take the average of the two numbers when doing crossovers. Also for mutation instead of completely overriding x, you could multiply it by a random number between 0.5 and 2 for example.

maraca
  • 8,468
  • 3
  • 23
  • 45
  • Thank you for your answer, so what happens with the requirement that we need to find a solution with 4 digits? How can I integrate that into the problem? – Farzad Dec 08 '16 at 22:23
  • @Farzad you can use floating point numbers and if f(x) < 0.0001*x then you can round to 4 digits. – maraca Dec 08 '16 at 23:10
1

First step is choose a representation of solutions. The most widely used is binary encoding. For example your x may looks:

1 0 0 1 1 1 1 0 | 0 0 0 0 0 0 0 0 0 0 1 1 1

First 8 bits coded an integer part of number, residual 13 bits coded part of number after dot. In this example the binary string coding a number 158.0007.

Crrossover may looks

1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 - 158.0007

1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 - 225.0008

The most simple crossover operator is one divide point. You generate one number from 1 to length of string - 1. And to this point you get a bits from one string and from that point from second string. In this example we choose for divide point 4 position. The offspring will looks like:

1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 - 145.0008

Mutation change with chosen probability some bits.

Fitness function may be a function value of quadratic equation(in case you try found an maximum) in x and x is obtained as decoding of bits string.

And some theory on the end. You have a two sets. One set is search space(space with binary strings) and second set is space with solution. Individual from search space is decoded into the solution in the solution space(in our case value of x coded by binary string). Search space represent genotype and decoded solution is phenotype. Genetics operators work with search space individual(binary string in this case) and fitness function using a decoded solution.

viceriel
  • 835
  • 12
  • 18
  • Thank you for your detailed explanation. Can you elaborate a bit more about the fitness function in our case, which is finding a solution to the quadratic equation – Farzad Dec 12 '16 at 22:33
  • Ok, you for example try found a maximum of quadratic function on interval 0-256.xxxx. The quadratic equation may looks like: 2*x^2 - 5x + 3. You decode a binary string and you get for example 5. fitness_of_binary_string = 2*5^2-25+3 =28. So fitness of this string is 43. You decode another string and get value 10. So fitness of this string will be 2*10^2-50+3= 153. And string which decodes value 10 has greater fitness :) – viceriel Dec 12 '16 at 23:35
  • I'm sorry, fitness of first string will be 28. – viceriel Dec 12 '16 at 23:38
0

I've got one that solves the equation: a(x1*x1+x2*x2)+b(x1+x2)+2*c = 0 which is the addition of: ax1x1+bx1+c=0 and ax2x2+bx2+c=0 since x1 and x2 are both the solutions of the equation the addition can be made. The code gives for aa=1, bb=-1 and cc=-30 the following output:

best solutions at generation 0 :: fitness = 1
chromosome 13 : x1 = -5 , x2 = 6
chromosome 269 : x1 = 6 , x2 = 6
chromosome 340 : x1 = 6 , x2 = -5
chromosome 440 : x1 = -5 , x2 = 6
chromosome 452 : x1 = 6 , x2 = -5
chromosome 549 : x1 = -5 , x2 = -5
chromosome 550 : x1 = 6 , x2 = -5
chromosome 603 : x1 = -5 , x2 = -5
chromosome 826 : x1 = 6 , x2 = -5
chromosome 827 : x1 = -5 , x2 = 6
chromosome 842 : x1 = -5 , x2 = -5
chromosome 952 : x1 = 6 , x2 = 6
chromosome 986 : x1 = 6 , x2 = -5

which is, I believe a good start, I only doesn't know yet how to filter the good from the less good solutions.

this is the code partially:

void objective(Chromosome* c){
    // the problem here is when one root is found the fitness
    // will be 1 :
    // resulting in the second value is a non-root or the same 
    // value as the first root
    //so probably I need to rewrite the fitness function
    c->result = aa * ((c->gene[0].geneticcode * c->gene[0].geneticcode) + (c->gene[1].geneticcode * c->gene[1].geneticcode)) /
              + bb * (c->gene[0].geneticcode + c->gene[1].geneticcode) /
              + 2 * cc;
}

void fitness(Chromosome* c){
    //rewrite of fitness function for this example
    c->fitness = 1.0 / (1.0 + fabs(c->result));
}

If anyone can improve and I'm sure there are please share.

Agguro
  • 348
  • 3
  • 11