giacomelli / GeneticSharp

GeneticSharp is a fast, extensible, multi-platform and multithreading C# Genetic Algorithm library that simplifies the development of applications using Genetic Algorithms (GAs).
MIT License
1.26k stars 330 forks source link

I can't get a better result, please help me #81

Closed longbiscuit closed 3 years ago

longbiscuit commented 3 years ago

I downloaded version 2.6 of GeneticSharp.Domain on Nuget, then I add a file named Program.cs. This is my Program.cs code: ` using GeneticSharp.Domain; using GeneticSharp.Domain.Chromosomes; using GeneticSharp.Domain.Crossovers; using GeneticSharp.Domain.Fitnesses; using GeneticSharp.Domain.Mutations; using GeneticSharp.Domain.Populations; using GeneticSharp.Domain.Selections; using GeneticSharp.Domain.Terminations; using GeneticSharp.Infrastructure.Framework.Threading; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //https://diegogiacomelli.com.br/function-optimization-with-geneticsharp/ //多线程 https://github.com/giacomelli/GeneticSharp/wiki/multithreading namespace ConsoleApp1GeneticSharp { class Program {

    static void Main(string[] args)
    {
        #region example 1
        // https://www.nuget.org/packages/GeneticSharp/
        //https://stackoverflow.com/questions/59191025/optimization-of-an-equation-parameters-using-genetic-sharp-genetic-algorithm
        //x = 1, 2, 3, 4, 5
        //y = 5, 4, 3, 2, 1
        //z = 1, 2, 1, 1, 3
        //t = 9, 12, 9, 9, 15.
        // t=ax+by+c*z. here i know a=1,b=1 and c=3
        double[] x = new double[] { 1, 2, 3, 4, 5 };
        double[] y = new double[] { 5, 4, 3, 2, 1 };
        double[] z = new double[] { 1, 2, 1, 1, 3 };
        double[] t = new double[] { 9, 12, 9, 9, 15 };

        var chromosome = new FloatingPointChromosome(
        new double[] { 0.0, 0.0, 0.0 },//各参数最小值
        new double[] { 10.0, 10.0, 10.0 },//各参数最大值
        //new double[] { 1, 1, 3 },//各参数最小值
        //new double[] { 1, 1, 3 },//各参数最大值
        new int[] { 64, 64, 64 },//用于表示上述参数值的2进制位数
        new int[] { 3, 3, 3 });//参数的十进制形式小数位数

        //https://github.com/giacomelli/GeneticSharp/issues/4
        var population = new Population(100, 100, chromosome);//select the % of individuals who will survive in each generation

        var fitness = new FuncFitness((c) =>
        {
            var fc = c as FloatingPointChromosome;
            double err = 0;
            var values = fc.ToFloatingPoints();
            var pa = values[0];
            var pb = values[1];
            var pc = values[2];
            for (int i = 0; i < x.Count(); i++)
            {
                err += Math.Pow((t[i] - (pa * x[i] + pb * y[i] + pc * z[i])), 2);
            }
            return -err;
        });

        //给定三大算子
        var selection = new TournamentSelection();// Elite, Roulete Wheel, Stochastic Universal Sampling and Tournament. //https://diegogiacomelli.com.br/function-optimization-with-geneticsharp/
        var crossover = new TwoPointCrossover();//https://github.com/giacomelli/GeneticSharp/wiki/crossovers
        var mutation = new FlipBitMutation();//https://github.com/giacomelli/GeneticSharp/wiki/mutations

        //多线程
        var taskExecutor = new ParallelTaskExecutor();//多线程
        taskExecutor.MinThreads = 2;//多线程
        taskExecutor.MaxThreads = 2;//多线程
        var ga = new GeneticAlgorithm(population, fitness, selection, crossover, mutation);
        ga.TaskExecutor = taskExecutor;//多线程

        //var termination = new FitnessStagnationTermination(1000);
        //ga.Termination = termination;

        //ga.Termination = new GenerationNumberTermination(3000);

        ga.Termination = new OrTermination(
           new GenerationNumberTermination(5000), //执行到多少代必须停止
           new FitnessStagnationTermination(2000));//目标函数多少代不再变化就停止

        ga.MutationProbability = 0.05f;
        ga.CrossoverProbability = 0.85f;

        Console.WriteLine("GA running...");

        var latestFitness = 0.0;

        ga.GenerationRan += (sender, e) =>
        {
            var bestChromosome = ga.BestChromosome as FloatingPointChromosome;
            var bestFitness = bestChromosome.Fitness.Value;

            if (bestFitness != latestFitness)
            {
                latestFitness = bestFitness;
                var phenotype = bestChromosome.ToFloatingPoints();

                Console.WriteLine(
                    "Generation {0}:  {1},{2},{3} = {4}",
                    ga.GenerationsNumber,
                    phenotype[0],
                    phenotype[1],
                    phenotype[2],
                    bestFitness
                );
            }
        };

        ga.Start();

        Console.WriteLine("GA ending...");

        Console.ReadKey();

        #endregion example 1

        //#region example 2

        //float maxWidth = 998f;
        //float maxHeight = 680f;

        //var chromosome = new FloatingPointChromosome(
        //    new double[] { 0, 0, 0, 0 },
        //    new double[] { maxWidth, maxHeight, maxWidth, maxHeight },
        //    new int[] { 10, 10, 10, 10 },
        //    new int[] { 0, 0, 0, 0 });

        //var population = new Population(100, 100, chromosome);

        //var fitness = new FuncFitness((c) =>
        //{
        //    var fc = c as FloatingPointChromosome;

        //    var values = fc.ToFloatingPoints();
        //    var x1 = values[0];
        //    var y1 = values[1];
        //    var x2 = values[2];
        //    var y2 = values[3];

        //    return Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
        //});

        //var selection = new EliteSelection();
        //var crossover = new UniformCrossover(0.5f);
        //var mutation = new FlipBitMutation();
        //var termination = new FitnessStagnationTermination(100);

        //var ga = new GeneticAlgorithm(
        //    population,
        //    fitness,
        //    selection,
        //    crossover,
        //    mutation);

        //ga.Termination = termination;

        //Console.WriteLine("Generation: (x1, y1), (x2, y2) = distance");

        //var latestFitness = 0.0;

        //ga.GenerationRan += (sender, e) =>
        //{
        //    var bestChromosome = ga.BestChromosome as FloatingPointChromosome;
        //    var bestFitness = bestChromosome.Fitness.Value;

        //    if (bestFitness != latestFitness)
        //    {
        //        latestFitness = bestFitness;
        //        var phenotype = bestChromosome.ToFloatingPoints();

        //        Console.WriteLine(
        //            "Generation {0,2}: ({1},{2}),({3},{4}) = {5}",
        //            ga.GenerationsNumber,
        //            phenotype[0],
        //            phenotype[1],
        //            phenotype[2],
        //            phenotype[3],
        //            bestFitness
        //        );
        //    }
        //};

        //ga.Start();

        //Console.ReadKey();

        //#endregion example 2

    }
}

}

` but i can‘t get the right values of a, b and c, why ?

giacomelli commented 3 years ago

Please remove the commented code and correctly format your sample code.

Other than that, what fitness did you get by running your code and in how many generations?

longbiscuit commented 3 years ago

thank you for your reply. (1) Question the fitness of this code is the least squares result of Curve fitting problem: I know the variable's value of x, y, z and t as bellow:

x = 1, 2, 3, 4, 5;
y = 5, 4, 3, 2, 1;
z = 1, 2, 1, 1, 3;
t = 9, 12, 9, 9, 15;

, and also know their relationship: t=ax+by+c*z;

I should get the double parameters value of a, b and c. PS. I also know the right result : a=1.0,b=1.0 and c=3.0 .

(2) The implementation process I build a new solution and a project named ReplyGSharpConsoleApp1 , and GeneticSharp was searched and installed on the Nuget platform in this project. Then i add the Program.cs file in the ReplyGSharpConsoleApp1 project.

(3)stop condition code:

//stop condition
ga.Termination = new OrTermination(
new GenerationNumberTermination(5000), //执行到多少代必须停止
new FitnessStagnationTermination(2000));//目标函数多少代不再变化就停止

and one result is : GA running... Generation 1: -1.626,2.638,4.232 = -160.08276799999996 Generation 5: -1.626,2.126,4.232 = -149.87143999999998 Generation 10: -1.626,2.126,4.488 = -136.81748799999997 Generation 11: -0.602,2.126,4.232 = -60.58683199999996 Generation 32: -0.602,2.124,4.232 = -60.460123999999986 Generation 35: -0.586,2.124,4.232 = -59.978012 Generation 47: -0.585,2.124,4.232 = -59.94881499999999 Generation 48: -0.586,2.116,4.232 = -59.46661999999998 Generation 68: -0.586,2.116,4.224 = -59.46242800000002 Generation 73: -0.578,2.116,4.224 = -59.223996 Generation 82: -0.066,2.116,4.224 = -58.60754800000001 Generation 90: -0.066,2.112,4.224 = -58.21023600000002 Generation 92: -0.098,2.116,4.224 = -57.801276 Generation 96: -0.1,2.116,4.224 = -57.754624000000035 Generation 103: -0.1,2.052,4.224 = -51.76115200000004 Generation 104: -0.1,2.116,4.224 = -57.754624000000035 Generation 107: -0.1,2.116,4.096 = -54.60684800000004 Generation 111: -0.108,2.116,4.096 = -54.47993600000001 Generation 116: -0.364,2.116,4.096 = -54.13587200000001 Generation 119: -0.108,2.052,4.096 = -48.866367999999994 Generation 139: -0.112,2.052,4.096 = -48.82347200000002 Generation 145: -0.24,2.052,4.096 = -48.38007999999999 Generation 154: -0.239,2.052,4.096 = -48.376559 Generation 157: -0.208,2.052,4.096 = -48.321968 Generation 182: -0.208,2.048,4.096 = -48.01407999999999 Generation 183: -0.208,2.052,4.096 = -48.321968 Generation 249: -0.207,2.052,4.096 = -48.321967 Generation 346: -0.207,2.048,4.096 = -48.013799 Generation 409: -0.205,2.048,4.096 = -48.01356700000001 GA ending...

I don't know how should the three operators be chosen to get a better result, would you like to help me, Thank you in advance.

This is the Program.cs code after removing the commented code :

using GeneticSharp.Domain;
using GeneticSharp.Domain.Chromosomes;
using GeneticSharp.Domain.Crossovers;
using GeneticSharp.Domain.Fitnesses;
using GeneticSharp.Domain.Mutations;
using GeneticSharp.Domain.Populations;
using GeneticSharp.Domain.Selections;
using GeneticSharp.Domain.Terminations;
using GeneticSharp.Infrastructure.Framework.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ReplyGSharpConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //x = 1, 2, 3, 4, 5
            //y = 5, 4, 3, 2, 1
            //z = 1, 2, 1, 1, 3
            //t = 9, 12, 9, 9, 15.
            // t=ax+by+c*z. here i know a=1,b=1 and c=3
            double[] x = new double[] { 1, 2, 3, 4, 5 };
            double[] y = new double[] { 5, 4, 3, 2, 1 };
            double[] z = new double[] { 1, 2, 1, 1, 3 };
            double[] t = new double[] { 9, 12, 9, 9, 15 };

            var chromosome = new FloatingPointChromosome(
            new double[] { -10.0, -10.0, -10.0 },//Minimum value of each parameter 各参数最小值
            new double[] { 10.0, 10.0, 10.0 },//Maximum value of each parameter 各参数最大值
            new int[] { 64, 64, 64 },//用于表示上述参数值的2进制位数
            new int[] { 3, 3, 3 });//参数的十进制形式小数位数

            //https://github.com/giacomelli/GeneticSharp/issues/4
            var population = new Population(100, 100, chromosome);//select the % of individuals who will survive in each generation

            var fitness = new FuncFitness((c) =>
            {
                var fc = c as FloatingPointChromosome;
                double err = 0;
                var values = fc.ToFloatingPoints();
                var pa = values[0];
                var pb = values[1];
                var pc = values[2];
                for (int i = 0; i < x.Count(); i++)
                {
                    err += Math.Pow((t[i] - (pa * x[i] + pb * y[i] + pc * z[i])), 2);
                }
                return -err;
            });

            //给定三大算子
            var selection = new TournamentSelection();// Elite, Roulete Wheel, Stochastic Universal Sampling and Tournament. //https://diegogiacomelli.com.br/function-optimization-with-geneticsharp/
            var crossover = new TwoPointCrossover();//https://github.com/giacomelli/GeneticSharp/wiki/crossovers
            var mutation = new FlipBitMutation();//https://github.com/giacomelli/GeneticSharp/wiki/mutations

            //多线程
            var taskExecutor = new ParallelTaskExecutor();//多线程
            taskExecutor.MinThreads = 2;//多线程
            taskExecutor.MaxThreads = 2;//多线程
            var ga = new GeneticAlgorithm(population, fitness, selection, crossover, mutation);
            ga.TaskExecutor = taskExecutor;//多线程

            //stop condition
            ga.Termination = new OrTermination(
               new GenerationNumberTermination(5000), //执行到多少代必须停止
               new FitnessStagnationTermination(2000));//目标函数多少代不再变化就停止

            ga.MutationProbability = 0.05f;
            ga.CrossoverProbability = 0.85f;

            Console.WriteLine("GA running...");

            var latestFitness = 0.0;

            ga.GenerationRan += (sender, e) =>
            {
                var bestChromosome = ga.BestChromosome as FloatingPointChromosome;
                var bestFitness = bestChromosome.Fitness.Value;

                if (bestFitness != latestFitness)
                {
                    latestFitness = bestFitness;
                    var phenotype = bestChromosome.ToFloatingPoints();

                    Console.WriteLine(
                        "Generation {0}:  {1},{2},{3} = {4}",
                        ga.GenerationsNumber,
                        phenotype[0],
                        phenotype[1],
                        phenotype[2],
                        bestFitness
                    );
                }
            };

            ga.Start();

            Console.WriteLine("GA ending...");

            Console.ReadKey();
        }
    } }

ReplyGSharpConsoleApp1.zip

giacomelli commented 3 years ago

From what I saw in the logs, your code is getting a better result, as it starts with fitness of -160 and ends with a -48.

On the question of which operators (selection, crossover, mutation) to use, it really depends a lot on each problem being solved by the genetic algorithm, so you will have to try some combinations and see which one gives the best result in a long time.

longbiscuit commented 3 years ago

thanks for your reply. It works well when the fitness become 0.0 ( in the case of parameters a=1.0, b=1.0 and c=3.0). Although the results are getting better and better, the best results are not found. I feel that this problem is very easy for a genetic algorithm to solve. Can you improve my code to get the best solution ? This problem has been bothering me for a long time and I can't improve it. Thank you very much!

giacomelli commented 3 years ago

Sorry, but I don't have time now.

I'll leave the issue open for a while maybe someone from the community can help.

longbiscuit commented 3 years ago

Ok, thank you. Anybody help me? Thank you

giacomelli commented 3 years ago

Closed for inactivity. Feel free to reopen it if necessary.