Giter VIP home page Giter VIP logo

giacomelli / geneticsharp Goto Github PK

View Code? Open in Web Editor NEW
1.2K 74.0 321.0 188.17 MB

GeneticSharp is a fast, extensible, multi-platform and multithreading C# Genetic Algorithm library that simplifies the development of applications using Genetic Algorithms (GAs).

License: MIT License

C# 78.23% Batchfile 0.11% Shell 0.04% ShaderLab 14.68% HLSL 0.62% HTML 1.18% CSS 1.15% JavaScript 0.11% GLSL 3.86% PowerShell 0.03%
genetic-algorithms artificial-intelligence c-sharp dotnet dotnet-core dotnet-standard genetic-algorithm unity3d dotnet6

geneticsharp's Introduction

Build status Quality status Coverage Status License Nuget Stack Overflow

GeneticSharp is a fast, extensible, multi-platform, and multithreading C# Genetic Algorithm library that simplifies the development of applications using Genetic Algorithms (GAs).

It can be used in any kind of .NET 6, .NET Standard, and .NET Framework apps, like ASP .NET MVC, ASP .NET Core, Blazor, Web Forms, UWP, Windows Forms, GTK#, Xamarin, MAUI and Unity3D games.


Projects, papers, journals, books, tutorials, courses, and apps using GeneticSharp

Features

Add your own fitness evaluation, implementing IFitness interface.

Samples

  • AutoConfig
  • Bitmap equality
  • Equality equation
  • Equation solver
  • Function builder
  • Ghostwriter
  • TSP (Travelling Salesman Problem)

  • Bitmap equality
  • Function optimization
  • Sudoku
  • TSP (Travelling Salesman Problem)

  • Car2D
  • TSP (Travelling Salesman Problem)
  • Wall Builder

Multi-platform

  • .NET 6, .NET Standard 2.0, Mono and .NET Framework 4.6.2 support
  • Fully tested on Windows and MacOS

Code quality


Setup

.NET 6

Only GeneticSharp:

install-package GeneticSharp

GeneticSharp and extensions (TSP, AutoConfig, Bitmap equality, Equality equation, Equation solver, Function builder, etc):

install-package GeneticSharp.Extensions

Unity3D

You should use the UnityNuGet to install GeneticSharp directly from NuGet.

Or you can use the latest GeneticSharp.unitypackage available on our release page.

.NET Standard 2.0 and .NET Framework 4.6.2

To install previous version that support .NET Standard 2.0 and .NET Framework 4.6.2:

install-package GeneticSharp -Version 2.6.0

Mono and .NET Framework 3.5

To install previous version that support .NET Framework 3.5:

install-package GeneticSharp -Version 1.2.0

Running samples

If you want to run the console, GTK# and Unity samples, just fork this repository and follow the instruction from our setup page wiki.

An easy way to run the Unity Samples, if you have a Android device, is download it from Google Play.

Usage

Creating your own fitness evaluation

public class MyProblemFitness : IFitness
{  
	public double Evaluate (IChromosome chromosome)
	{
		// Evaluate the fitness of chromosome.
	}
}

Creating your own chromosome

public class MyProblemChromosome : ChromosomeBase
{
	// Change the argument value passed to base constructor to change the length 
	// of your chromosome.
	public MyProblemChromosome() : base(10) 
	{
		CreateGenes();
	}

	public override Gene GenerateGene (int geneIndex)
	{
		// Generate a gene base on my problem chromosome representation.
	}

	public override IChromosome CreateNew ()
	{
		return new MyProblemChromosome();
	}
}

Running your GA

var selection = new EliteSelection();
var crossover = new OrderedCrossover();
var mutation = new ReverseSequenceMutation();
var fitness = new MyProblemFitness();
var chromosome = new MyProblemChromosome();
var population = new Population (50, 70, chromosome);

var ga = new GeneticAlgorithm(population, fitness, selection, crossover, mutation);
ga.Termination = new GenerationNumberTermination(100);

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

Console.WriteLine("Best solution found has {0} fitness.", ga.BestChromosome.Fitness);

Templates for dotnet new

If you're using .NET 6 or .NET Core, you can install GeneticSharp.Templates:

dotnet new -i GeneticSharp.Templates

There are 4 templates in GeneticSharp.Templates:

TSP Blazor application

A Blazor client application template with GeneticSharp ready to run a Travelling Salesman Problem (TSP).

dotnet new GeneticSharpTspBlazorApp -n MyNamespace -o MyOutoputFolder

Console application

A console application template with GeneticSharp, you just need to implement the chromosome and fitness function.

dotnet new GeneticSharpConsoleApp -n MyNamespace -o MyOutoputFolder

TSP Console application

A console application template with GeneticSharp ready to run a Travelling Salesman Problem (TSP).

dotnet new GeneticSharpTspConsoleApp -n MyNamespace -o MyOutoputFolder

TSP Unity3D

A Unity3D template with GeneticSharp ready to run a Travelling Salesman Problem (TSP).

dotnet new GeneticSharpTspUnity3d -n MyNamespace -o MyOutoputFolder

FAQ

Having troubles?


How to improve it?

Create a fork of GeneticSharp.

Did you change it? Submit a pull request.

License

Licensed under the The MIT License (MIT). In others words, you can use this library for developement any kind of software: open source, commercial, proprietary, etc.

Thanks to

  • AppVeyor: open source license for continuous integration.
  • JetBrains: open source license for all products pack.
  • SMASHINGLOGO: GeneticSharp's logo.
  • SonarCloud: open source license for online inspection.

geneticsharp's People

Contributors

antonycorbett avatar bryant1410 avatar darcara avatar discosultan avatar elpht avatar fredikats avatar giacomelli avatar gitter-badger avatar jsboige avatar melnikovig avatar mersadk avatar rsmithsa avatar treeoflearning avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geneticsharp's Issues

NuGet Package Installation for Unity Project Failure

Hello,

While trying to install the NuGet package inside a Unity3D project version 5.6.0f3 the package installation fails because of NuGet trying to install another package HelperSharp which is not compatible with Unity3D .NET Profile.

Screen shot below for more clarification.

image

What steps should I take ? Possibly removing dependencies of both packages so that the GeneticSharp package can be installed alone.

FlipBitMutation with IntegerChromosome

Describe the bug
Using FlipBitMutation with IntegerChromosome throws System.InvalidCastException

To Reproduce
Please see the attached sample project
Ex2.zip

Expected behavior
As IntegerChromosome implements BinaryChromsome, I am expected that it should work

Version:
version 2.2.0

Runtime exception on .NET 4.6.2

I'm running Visual Studio 2013 targeting .NET 4.6.2 with GeneticSharp 2.4.0, and get the following runtime exception when attempting to instantiate a GeneticAlgorithm instance (specifically, when the task executor is set):

Could not load file or assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies.

Is .NET Framework 4.6.2 still supported, or is .NET standard 2.0.0+ now required?

Change only one variable at a time freezing all others in GA

I am trying to mimic large jumps (within the search space)
and small jumps in the neighborhood changing only one parameter at a time
(instead of allowing all variables to change at once). Is it possible to do
this in GA using the available( mutation) operators where I can define different probability for the small and large changes or do I need to write my own implementation to achieve this ?

New NuGet version

Hi,

Can you create new NuGet version (just a minor bump), as current is 6 months old. I need feature from pull request #34, but it' still not available in NuGet.

Thanks

GeneticAlgorithm.BestChromosome.Fitness decrease over time when using EliteSelection

Describe the bug

Initializing and executing the Genetic Algorithm implementation with an EliteSelection seems in some cases to produce Chromosomes with decreasing fitness over time.

To Reproduce

An FsCheck project was created which generates instances of the Traveling Salesman Problem. FsCheck is an F# QuickCheck port which enables randomized testing of certain properties.

The property under test is specific to an elite selection mechanism and is informally described as

  • "The n'th+ 1 generation’s best fitness is greater than or equal to the n'th generation’s best fitness."

or equally

  • "The best solution must never be worse that its predecessor."

The FsCheck project is available on Github. Follow the instructions in the README to reproduce the bug. https://github.com/Vedsted/Functional-Project/tree/master/GeneticSharpIssue

It is recommended to read the README file. These lines should provide the output immediately:

git clone https://github.com/Vedsted/Functional-Project.git
cd Functional-Project
dotnet run -p GeneticSharpIssue

Expected behavior

It is expected that the Genetic Algorithm never outputs a BestChromosome which is worse than its predecessor when using EliteSelection.

Version:

NuGet package GeneticSharp v. 2.6.0

Nuget package FsCheck v. 3.0.0 Alpha 4

Sample output:
It is shown from the sample below that the BestChromosome.Fitness for the TSP is decreasing in the 7th generation, when seed=781433289.

Checking GeneticAlgorithmResult:
{
         HashCode: 58225482,
         Initial: { Seed: 781433289, Termination: 500},
         Result: { Actual termination: 799, Best Chromosome: (Distance: 4288,691172664607 Fitness: 0,7855654413667696)}
}

FsCheck Trace:
Falsifiable, after 1 test (0 shrinks) (484766587145030488,7199734823952781115)
Last step was invoked with size of 2 and seed of (14439125655389665598,3384482638261145923):
Label of failing property: Fitness decreased at index: 6
For generations 1-7:
 [(Distance: 7912,566119106175 Fitness: 0,6043716940446913);
 (Distance: 7912,566119106175 Fitness: 0,6043716940446913);
 (Distance: 7912,566119106175 Fitness: 0,6043716940446913);
 (Distance: 7912,566119106175 Fitness: 0,6043716940446913);
 (Distance: 7912,566119106175 Fitness: 0,6043716940446913);
 (Distance: 7912,566119106175 Fitness: 0,6043716940446913);
 (Distance: 8262,453814942292 Fitness: 0,5868773092528854)]
Original:

with exception:
System.Exception: Expected true, got false.

Additional context

This bug was found as a part of a mini-project in the course Functional Programming and Property-based Testing, at University of Southern Denmark. The report for this project contains more information. The report can be provided if requested.

Other consequences of this unexpected behavior

If the Genetic Algorithm has a termination criteria of the n'th run where this property is violated, the output is worse that a previous best solution.

Population.BestChromosomeChanged fires every generation with the same chromosome

Describe the bug
IChromosome is being compared with != in Population.EndCurrentGeneration.
I haven't checked other places yet.

To Reproduce
Any Population that has multiple chromosomes with the same fitness. I assume this happens to me because I use ElitistReinsertion.

Expected behavior
The problem occurs when subscribing to Population.BestChromosomeChanged since != and == on interfaces will always default to reference equality the overridden/implemented equals and compareTo methods are never called. See: https://stackoverflow.com/a/5066300
Since the ordering in Generation.End cannot be stable a random chromosome is selected, reference equality fails and a different instance but the same chromosome is now the best in every generation. Calling Object.Equals(chromosome1, chromosome2) would solve this problem since this will safely call the overridden methods.

Slightly related: I would assume that for most cases a gene-based equality should be superior to a pure fitness based one.

Screenshots
If applicable, add screenshots to help explain your problem.

Version:
2.6.0

GA function optimisation func(int x, int y) sample

Hi i wanted to ask you about sample
Howto solve this task using GeneticSharp. Can you provide code sample please?
Where X have Range (0....7) Y have Range (0 ....100) Step 5 (for calclulatiion for brute force)


So problem i dont know how many cromosomes should i use? In my mind there are idea
In each chromosome should be only 2 genes GeneX have range (0 ..7) and GeneY(0..100)
How i can implement this with GeneticSharp? Which method should be for GeneratePopulationm, CrossOver,Mutation?
public void FillPopulation(){
var population = new Population(50);
Random randpar1 = new Random();
randpar1.Next(1, 20);
//create the chromosomes
for (var p = 0; p < 50; p++)
{
var chromosome = new Chromosome();
for (var g = 0; g < 2; g++)
{
chromosome.Genes.Add(new Gene(randpar1.Next(-100, 200)));
}
//chromosome.Genes.Shuffle();
population.Solutions.Add(chromosome);
}
}


public static double CalculateFitness(Chromosome chromosome)
{
double n = 9;
var x = chromosome.Genes[0].RealValue;
var y = chromosome.Genes[1].RealValue;
double f1 = System.Math.Pow(15 * x * y * (1 - x) * (1 - y) *
System.Math.Sin(n * System.Math.PI * x) * System.Math.Sin(n * System.Math.PI * y), 2);

        return f1;
    }

Performance Tweaks (PLINQ/TPL) to Genetic Algorithm

FEATURE REQUEST (Optimization)
I've completed a bunch of performance tests on a scheduling algorithm implemented with GeneticSharp. Following are my findings.

I've used PLINQ/TPL to try to improve performance here and there.
Following are my results:

  • ParallelTaskExecutor.Start, changed loop to Parallel.For, removing the Task.Run RESULT: +2%
  • GeneticAlgorithm.Cross, GeneticAlgorithm.Mutate, changed loop to Parallel.ForEach (see PR) and used ConcurrentBag RESULT: +80% +110%

Additional context
I didn't like too much the actual implementation of ParallelTaskExecutor due to the need of sizing the min and max threads manually. If I understand well, Parallel class use a default (automatic) partitioner which can be customized if required (maybe even through the external interface?).

Let me know what you think.
Kind Regards,

References
MSDN Parallel Class
MSDN Custom Partitioners for PLINQ and TPL

Generic Feature

Sorry for bringing back the closed issue #48

The type safety is pretty important feature for careless coders like me, and I believe some people will benefit from the change. In your samples, I see Genes contains indices and index calculus to solve certain problems. Obviously you can assign custom classes to Gene's object whatever you like, but this makes me feel unsafe when I recast it back to original class type.

Making it generic is truly possible, but will be very tedious; but once done right, we may benefit from compile time check for type casting, and a slight performance gain by avoiding boxing and unboxing
(but yes, gene populations will not be that much and as long as you use reference types or small structs, it will not be the performance bottleneck)

Describe the solution you'd like
I actually did it for my personal use and you can see how it works in my fork https://github.com/seminumber/GeneticSharp/tree/feature/generic and the sample https://github.com/seminumber/GeneticSharp/tree/feature/generic/src/TspWpf
This is a proof-of-concept only. It's not polished and tested and doesn't meant to be pulled into your project. It can only show how it would look like when generics are implemented. The code runs exactly in the same way as your Blazor sample.
(I'm a windows users and I can work well with Wpf, so my sample was Wpf only. sorry if you're not using Windows, but you'll see the code and how it goes)

Describe alternatives you've considered
I first thought changing Gene to Gene<T> is the way to go, but later changed mind as Gene<T> took place for every location, so I changed Gene altogether with T. You can rename it TGene of course, or assign some interfaces for that, but T seems good enough for me.
Obviously, in more generic setup making <T, U> : U is IGene<T>, and <T> as a synonym for <T, Gene<T>> is another solution with genericity, but it would be too complicated to change so I took a simple path. But you may consider this is the better solution.

Additional context

In case you're interested, here's the procedure I took:

  1. Copy the entire Domain folder to Domain.Generic Folder
  2. In VS, rename (F2-refactor) IChromosome to IChromosome_ (so that it does not interfere with other names)
  3. Search and Replace within the whole project and change IChromosome_ to IChromosome<T>
  4. For every error in the intellisense, change the class containing errors to (mindlessly) adding type parameter <T>
    by repeating procedure 2 and 3 (meaning MyClass to MyClass_ and then MyClass<T>
  5. Search and Replace all namespaces .Domain.* into .Domain.*.Generic
  6. Repeat 2 to 5 until no errors are left
  7. Fix codes using the following rules..
    - Gene is now all T
    - Gene[] is now all IList<T>
    - Gene Equality (== or != or Equals) is checked by EqualityComparer<T>.Default.Compare
    - static classes will give type argument <T> for their methods
    - search all constructors and remove <T> for them (this is the consequence of mindless search-and-replace)

If you think this feature is valid, here's a few more things to consider (which I didn't implement - it was a test code after all)

  • making all generics implement nongeneric interfaces when possible (like, collections implements both IEnumerable<T> and IEnumerable)
  • making IChromosome<T> covariant so that IChromosome<Apple> is IChromosome<Fruit> whenever Apple is Fruit.
  • remove unnecessary generic counterparts (ITermination doesn't really needs to be Generic all the way, but I just mindlessly
    change all the way to avoid compile errors. In production, a good design will be necessary)
  • if Gene is a must for the design, create IGene<T> and restrcit IChromosome<TType, TGene> where TGene: IGene<TType>
  • provide static factory methods to benefit from type inferencing
    (like, Tuple<T1, T2, T3> can benefit from static Tuple<T1,T2,T3> Create<T1,T2,T3>(T1, T2, T3), so that
    compiler deduces the correct method when we use var tuple = Tuple.Create(3, "three", new Foo()) )

There can be some other changes I made which I'm not sure that was intended
-- like integer chromosome which I believe will be broken if you upcast IntegerChromosome
to BinaryChromosomeBase or ChromosomeBase.. well that's separate issue and I'll not go deep into this.

GeneticAlgorithm.Resume() not working

Hi, I try to resume the genetic algorithm but after it is stopped it is not running again.
Any idea?

P.S.: your program rocks by the way. I'm doing the knapsack problem

External loop control

Hi,

We made feasibility of GeneticSharp and now we investigate how GeneticSharp can be integrated with our system and found a next issue: our system manages external loop and requires to get population to calculate Fitness and set calcualted Fitness values to algorithm. So, I cannot calculate fitness in CreateNewGeneration (as suggested in #45).

sample of pseudo code:

while (geneticAlgoritm.InProgress){
    population = geneticAlgoritm.GetPopulation();
    CalculateFitness(population) // [our code] calculate and set Fitness value to each chromosome
    geneticAlgoritm.SetFitness(population)
}

Looks, I need find loop inside GeneticSharp and, somehow, to re-implement for our control.
Please, could you help me to understand what is the easiest way to implement the feature and I'll try to do it.

thank you,
Igor.

Compilation tutorial

Hi, I will use your awesome project for my masters thesis.

I will need to add few things, like mutation that firstly gets random number and determines which child mutation to use later.

Usage:
new RandomizedMutation({ {new UniformMutation(), 0.2}, // this are chances for that mutation {new AnotherMutation(), 0.8}, // this are chances for that mutation });

So I created fork, cloned repo, opened VS2017 aaaaand... Nothing. I can't get to compile. Are there some magick steps in order to do that?

I really wanted to be involved in OpenSource project for the first time.

Is it possible to know the number of iterations in advance?

Hi giacomelli,

On the platform I am using(based on .Net 4.5), it is required to setup the Number of Iterations in advance. Sounds ridiculous, but nothing I can do about it.

Is it possible to know that before the program is running?

I just successfully managed to run GeneticSharp 1.20 (latest version available for .Net 4.5) on my platform. And this seems to be the last obstacle.

Thank you in advance.

Warren

Make struct Gene Generic

Struct Gene isn't generic. It's probably not type-safed.

First solution

class Gene<T>
{ 
        public T Value => m_value;
        public Gene<T>(T value)
        {
                m_value = value;
        }
}

Suggestion: Add an ability to set PRNG's initial seed

Is your feature request related to a problem? Please describe.
Sometimes I need to generate the same result with the same parameter, so the fixed PRNG seed will be one of the ways to do this.

Describe the solution you'd like
Add a constructor to RandomizationBase, and implement in all Randomization class

public abstract class RandomizationBase : IRandomization
{
    protected readonly int seed;
    public RandomizationBase() : this((int)DateTime.Now.Ticks) { }
    public RandomizationBase(int seed) { this. seed = seed; }
}

RouletteWheelSelection.SelectFromWheel throws NullReferenceException when first generation is "invalid"

To Reproduce
RouletteWheelSelection.SelectFromWheel throws NullReferenceException when first generation is "invalid" (all chromosome have zero fitness).

Expected behavior
A better exception should be thrown. NullReferenceException is confusing and require to debug GeneticSharp.

Version:
2.2.0

Fix Proposal (probably naive)

Let me know if you like it and if you want me to make a PR.

protected static IList<IChromosome> SelectFromWheel(int number, IList<IChromosome> chromosomes, IList<double> rouletteWheel, Func<double> getPointer)
{
    var selected = new List<IChromosome>();

    for (int i = 0; i < number; i++)
    {
        var pointer = getPointer();

        var chromosomeIndex = rouletteWheel.Select((value, index) => new { Value = value, Index = index }).FirstOrDefault(r => r.Value >= pointer)?.Index;
        if (chromosomeIndex == null)
            throw new SelectionException("Generation doesn't contains any chromosome with fitness greater than 0");

        selected.Add(chromosomes[chromosomeIndex.Value]);
    }

    return selected;
}

Pull Request failed

My pull request failed because AppVeyor was attempting to download a resource from codeplex that was not found.

How to set Fitness function

have a problem figuring out how to set my function. It should be pretty easy but i am new to GA and espectially to GeneticSharp. So i need to set and optimize this function: -(16 * x * x - 24 * x + 5) * Math.Exp(-x) with scope from 1.9 to 3.9, thats all. But right now it runs only once and i think i did something wrong. Thank you in advance!
`namespace ConsoleApp1
{
class MainClass
{
public static void Main(string[] args)
{

        var chromosome = new FloatingPointChromosome(1.9, 3.9, 3);


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

        var fitness = new FuncFitness((c) =>
        {
            var fc = c as FloatingPointChromosome;
            var values = fc.ToFloatingPoints();
            var x = values[0];
            return -(16 * x * x - 24 * x + 5) * Math.Exp(-x);
        });

        var selection = new TournamentSelection();
        var crossover = new UniformCrossover();
        var mutation = new TworsMutation();
        var termination = new GenerationNumberTermination(100);

        var ga = new GeneticAlgorithm(
            population,
            fitness,
            selection,
            crossover,
            mutation)
        {
            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(phenotype[0]); Console.WriteLine(bestFitness);

            }
        };

        ga.Start();

        Console.ReadKey();
    }
}

}`

Suggestion: Replace FastRandom with ref to Redzen.Random.

Hi,

Just noticed there is a copy of FastRandom in this project. I would recommend replacing that with a ref to this project:

https://github.com/colgreen/Redzen
https://www.nuget.org/packages/Redzen/

That contains a maintained version of FastRandom (now called XorShiftandom) and newer/better RNG classes, and also interfaces IRandomSource, IRandomSourceFactory.

Eventually I may refactor further and move the RNG related code into its own nuget (e.g. Redzen.Random), but for now I recommend using the code in its current home.

Regards,

Colin

How is the number of totalBits, required, computed?

Using GeneticSharp, I started working on some optimizations in order to lower the computational power, required. For that purpose I try to lower the totalBits but it does not seem apparent how the required number bits is computed given

  • precision
  • of input variable and possible variable range.

Can someone please comment on how the total number bits, required, are computed. Ideally I want to set the totalBits parameter as function of chosen precision and value range.

Thanks

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

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 ?

Interface on Population

Would be possible to have an interface IPopulation?
I would like to implement my own population method (EndCurrentGeneration).

What is the best way to save the current generation data to a file so that it can be reused later.

I am a bit confused on the difference between resumming and starting the GA, but when I try to load in the genes that I've saved it seems as though the data is always overwritten.

Currently my gene "Value" is an int[] and I am serializing all of those to a binary file.

I am then trying to load the saved data like this:

    List<Gene[]> list = bf.Deserialize(inStr) as List<Gene[]>;
    var ind = 0;
    foreach(Gene[] g in list)
    {
      if(ind < this.ga.Population.CurrentGeneration.Chromosomes.Count())
      {
          this.ga.Population.CurrentGeneration.Chromosomes[ind].ReplaceGenes(0, g);
       }
    }

However, as soon as I call ga.resume it appears as though my data get overwritten.

Thanks for any help.

Group fitness

Hi, I'd like to implement a type of Tournament selection where I can run the fitness of them together in the same simulation. I'm doing an AI for a game and I'd like to run a group of AIs at the same time and select the one that ends up performing better. In my game AIs can't run alone, that's why I need them to run in group. Basically their performance depends a bit on the other ones as well.
Is there any easy way to do so? I feel I'll have to implement my own GeneticAlgorithm because everything is quite hardcoded to check the fitness individually.

Bug/Error when using ParallelTaskExecutor

I just discovered that when running the optimizer within a Task/Tread/TPL Dataflow block with TaskExecutor set to ParallelTaskExecuter when instantiating GeneticAlgorithm, it blocks all other outside operations during the lifetime of the optimizer run. This does not happen when not setting the TaskExecutor option.

Most likely this is a bug? Is there a workaround? At the moment I can hence not run the objective function in parallel.

Can someone please help?

IntegerChromosome example for 32 gene length Last gene is always 0

Hi,

I was doing some experiments with the library, it seems in the integer chromosome example when one has 32 genes, last gene value will always be one.

Please let me know if something is missing in my understanding, I guess one can escape this problem by shifting the bit of the integer using some probability cut-off.

regards,

Friendliear FloatingPointChromosome

Is your feature request related to a problem? Please describe.
It was difficult to calculate the number of bits needed. I looked into GeneticSharp's source to see how it did it and made a helper method

While researching that, it looks like negative numbers aren't handled very optimally. Once a negative min value is needed, Convert.ToString(longValue, 2) uses 64 bits with most of the left ones as 1's. Then in EnsureMinMax, it clamps to min, so most randomly chosen values would end up being min

So it looks like the best use of bits is to always have min be zero and go to some max

Describe the solution you'd like
I made a FloatingPointChromosome2 that internally has min and max go between 0 and external's max minus min

It then transforms the values on the way in/out so the user can work with their native values

It also calculates the number of bits for the user (I had to create a static Create method because the base class's constructor takes total bits)

Describe alternatives you've considered
My intermediate attempt was to use the helper methods and manually transform the values in and out of FloatingPointChromosome. It worked, but was tedious

Additional context
I'm including the FloatingPointChromosome2.cs and helper functions cs

I tested it a little bit and it seems to be working. Here is the code that calls it (search for FloatingPointChromosome2)
https://github.com/charlierix/PartyPeople/blob/master/Math_WPF/Mathematics/Math2D_wpf.cs

If you want to download the source and test, this is the tester that the code in math2d comes from. Load one of the json files (which are logs of me swinging my arms around), then hit Calculate Plane 3
https://github.com/charlierix/PartyPeople/blob/master/bepu/Testers/AnalyzeVRPoints.xaml
neutral arcs.zip
FloatingPointChromosome2.zip

Speed unit test have asserts inverted

In Domain Unit tests, linear and parallel speed tests are performed with the comparison asserts in the wrong direction. As a consequence, they just test that the algorithm takes is slower than 1ms.

If "Fast" and "Faster" is what is intended to being measured, the assert param order should be inverted and the target duration set to higher values.

I'm not sure what the expected value should be for linear execution, but with parallel stub fitness and 500ms over 100 generations, I guess a good test would be that the time evolving is no longer than 1 mn (I get 5x seconds with x on the low digits consistently).

Adding as constraint to GA instead of additional objective in FuncFitness

Hi Diego

How can we add constraints to GeneticAlgorithm - in my objective function defined in FuncFitness: we return 1/ (g(x) + h(x)), where g and h are defined on the chromosome values. I wanted to simplify the objective to just return 1/(g(x)) and add h(x)=0 as an additional constraint outside of the objective function

Is it possible to do this and any examples for the same ?

Thank you

Population calculation (in parallel mode)

Today, GeneticSharp calculates fitness by single chromosome.
Calculation of fitness for my problem can take a time and I want to sends all calculation (single population) to a HPC system.
How can I get all chromosomes, calculate all fitness values and return them?

public class MyProblemFitness : IFitness
{  
	public double Evaluate (IChromosome chromosome)
	{
		// Evaluate the fitness of chromosome.
	}
}

How to set up search steps?

Hi giacomelli,

Some times, I want to limit my search space by set up search steps. For example, instead of searching every 0.001 increments of a variable (0.001, 0.002, 0.003....in the range), I want to search every 0.005 increment (so, now I only search 0.005 0.001 in the range).

How Can I set up this in the GeneticSharp? I guess in the FloatingPointChromosome() the Number of Fraction argument can partially implement this.

Thanks in advance !

Improve Sudoku evolution to allow for lower population sizes

As part of a recently merged pull-request, a new sample was added to solve Sudokus. The sample includes several strategies, and the better ones seem successful at solving most Sudokus.
However, the only way I figured to ensure the population does not get stuck on a partial solution local maximum is to increase the population size, and that considerably for hard Sudokus.
This results approximately in the corresponding metrics:

  • Very Easy Sudoku: 250 chromosomes, <1 sec
  • Easy Sudoku: 5000 chromosomes, 10 sec
  • Medium Sudoku: 100000 chromosomes, 5-10 min
  • Hard Sudoku: 300000 chromosomes, 1-2h

This is raises the following questions:

  • Can we think of any set of parameters that make the current implementation more efficient?
  • How could we explain that other GAs libraries used to tackle the same problem seem able to work with lower populations and yield progresses over higher generation numbers? See for instance this article, that one, or many other implementations on Github.

Some additional thoughts to get started:

  • In order to trade population size for generation number, I introduced 2 partially successful alternatives on top of the initial 1 gene = 1 cell and 1 gene = 1 row-permutation strategies:
  1. Multiple Chromosome: I made that one general purpose as part of the Extension project: it evolves an arbitrary number of chromosomes rather than just one by inlining the genes.
  2. Random permutations: Instead of having just one gene per row permutation, I had several genes picked randomly.
  • Because of the way Sudokus work, I expect that a 2-points crossover at the 4th and 7th row with permutations (or 27th and 54th gene with 81-cells chromosomes) might somehow help in order to properly isolate "boxes", that is, 3x3 cell groups where digits must differ, additionally to rows and columns.
  • However, local maxima are such that it seems nearly impossible to escape one with random mutations once the entire population has commited to a single one. Thus it seems key to avoid such a global collapse and preseve genetic diversity instead. The various texts I ended up adding to the top of the gtk drawing box were meant to assess precisely when the entire population collapses to a single local maximum. They're not too pretty nor helpful otherwise, so feel free to change that part. The collapse to a local maximum usually won't take more than 50 generations.
  • Again the only efficient way I found to escape collapsing into a local maximum was to increase the population size according to the search space (a row with 5 cells in an easy Sudoku will allow for 24 legal permutations, whereas a row with no cell in a hard Sudoku will allow for the complete 9!=362880 permutations), but that is akin to simultaneously visiting and collapsing to all local maxima in the same small number of generations, which I don't consider very satisfying.
  • Now it might simply be that most generally, crossover won't work with Sudokus, that it any mixture of 2 partially resolved Sudokus will result in a much worse one. Then I would suppose that other libraries are better at escaping local maxima by implementing some kind of tabu search not found in genetic sharp, where they will allow some parts of the population to get away from the initial collapsing genome without repeatedly falling in its attractor.

Rank Selection

Is your feature request related to a problem? Please describe.
I'm migrating some code from Accord.NET which uses the RankSelection method. There doesn't appear to be an implementation in GeneticSharp.

Describe the solution you'd like
An implementation of the Rank Selection included in GeneticSharp.

Describe alternatives you've considered
I've implemented this for my own project and I'm happy if you don't want to include this in GeneticSharp. However I do believe it will add value to other people.

Add constructor with values to FloatingPointChromosome

As it is now when ever you create instance of FloatingPointChromosome, it will randomly create gene values.

I have a case where I need to stop optimization at some time, save results to DB and resume it later. For this I need to be able to give gene values to FloatingPointChromosome.

If you are willing to merge, I'll create pull request with this fix.

Generation workflow issues and room for improvements

Following investigations about issue #47, I'm a bit puzzled with the evolution workflow and the resulting behavior.
It seems to me that on most tasks, Elite selection and Elitist reinsertion are constantly outperforming any other alternative operators, that accordingly, preserving genetic diversity is hard with usually a quick collapse to sub-optimal solutions, and that more generally despite an abundance of parameters or extensive code coverage, parameter tuning is pretty hard.

I would be willing to investigate contributing extensions dealing specifically with those issues, such as Island GAs variants or other meta-heuristics, but I believe the basic workflow has existing issues that might need addressing first.

Let me try to follow a generation cycle starting at Crossover stage, which is an interesting entry point for improvements IMHO. Returning from IOperatorsStrategy.Cross we get a number of children <= MinSize, depending on child/parent ratio (1 for most crossovers) and crossover probability (<=1). Pair-wise parents matching is performed without specific attention, simply following parents order returned by selection.

After crossover, offspring are mutated on an individual basis, without impacting the population globally.

Reinsertion operator doesn't seem right:
Elitist and Uniform reinsertion will fill up the new population to MinSize respectively with best parents and random offspring copies. I wasn't able to get Uniform reinsertion to work at all, with fitness consistantly not improving.
Pure reinsertion will only work if crossover yields the same number of offspring as parents (certain crossover are not permitted + crossover probability must be equal to 1 + MinSize must be an even number). Just as for uniform reinsertion, with the appropriate population size compatible settings, I wasn't able to get any result at all.
FitnessBasedReinsertion also has issues:

  • reinsertion is meant to trim children population size to MaxSize, but IOperatorsStrategy.Cross consistently keeps children number below or equal to MinSize. Without any ICrossover producing more children than parents, MaxSize seems currently unused at all and the only population dynamics occuring seems to be filling up to MinSize when needed with the 2 compatible Reinsertions (Elite and Uniform).
  • Even in the event where we would have offspring number > MaxSize, Fitness reinsertion is supposedly based on offspring fitness, but fitness evaluation occurs at a later stage during the generation, so offspring fitnesses will be unavailable at that point. That also suggests the FitnessBasedReinsertionTest unit test wrongly assumes that reinsertion does its job.

That leaves us with apparently only Elitist reinsertion usable, that is, the necessity to keep best parents in subsequent generations.

Either way, a typical generation currently ends with a population of unordered children filled up with best parents or additional children if needed, to a total number of MinSize, then sorted twice by Fitness value in GA.EvaluateFitness and again in Generation.End, which also trims to MaxSize (both seem unneeded)

At the Selection stage of next generation, the selection operator might do differents things according to the type used:
In all cases, it will yield a MinSize number of parents.

  • Elite selection orders new parents according to fitness and trims the population to MinSize: both the trimming and sorting currently seem unneeded, since according to the above, input population size is consistantly MinSize with already sorted elements. Rank selection also does the fitness sort.
  • Elite selection keeps parents sorted with great impact on crossover pairing, whereas Roulette, Rank and Tournament yield random crossover candidate pairs accross selected parents, and StochasticUniversalSampling will generate pairs following an order starting from a random point, then starting over, which seems oddly specific behavior.

The whole workflow suggests to me a revamp might be needed to make sense of the currently available options:

  • Evolution of population size might need a review. Population Maxsize is enforced in several places though effectively unused: only Minsize seems to be of any use for now; accordingly FitnessBased reinsertion or any collapse capable reinsertion also seem unusable. Maybe Crossover operator strategy could be updated to allow for modulating offspring population size, independently of Crossover probability and crossover operators.

  • More attention could be put into population order / sorting by fitness.
    When using Elite reinsertion and Elite Selection, as far as I can see, population will be sorted 4 times by fitness in GA.EvaluateFitness, Generation.End, EliteSelection.PerformSelectChromosomes and ElitistReinsertion.PerformSelectChromosomes.
    Then, according to the current implementation, crossover pairwise matching, which will greatly influence search dynamics, relies on post selection order, in what seems a non consistent way (see StochasticUniversalSampling above).
    Finally about the sorting overhead itself, that does not seem too much, but it can also be discussed. Linq OrderByDescending, is mostly used in several places, and uses Quicksearch internally, which includes an overhead with already sorted sets, and even more so with near sorted sets. Interestingly, Insertion sort performs much better with near sorted sets, which might be of consideration with evolution depending on operators, and even though Quicksearch is interesting when only a subset of the first sorted elements is needed, the corresponding improvements documented in the following article were not accounted for in the latest linq internals, and a full quicksort is still triggered every time.
    Accordingly there are 2 issues here:

    • having explicit control on pairwise matching between Selection and Crossover
    • making sure no more sorting than strictly necessary is performed (maybe with a lazy/flag mechanism, and ideally having control on the sorting algorithm, depending on the expected presorting configurations),
  • The very idea of FitnessBased reinsertion challanges the current operations sequence. Either reinsertion should not be concerned with offspring fitnesses at all, leaving that to the selection operators, or the current workflow should be updated to allow for fitness evaluation before reinsertion.

CutAndSpliceCrossover resize problem with FloatingPointChromosome

When using CutAndSpliceCrossover with FloatingPointChromosome I get following error:
The representation length should be the same of the sum of the totalBits.

From what I was able to determine, problem is that CutAndSpliceCrossover will resize child but keep initial chromosome settings (min, max, totalBits, fractionSize) from parents.

Following unit test can be used to reproduce problem:

[Test]
public void Cross_with_FloatingPointChromosome()
{
	var c1 = new FloatingPointChromosome(
			new[] { 70d, 1d, 1d, 1d },
			new[] { 80d, 39d, 39d, 15d },
			new[] { 10, 6, 6, 4 },
			new[] { 1, 0, 0, 0 }
		);

	var c2 = new FloatingPointChromosome(
			new[] { 70d, 1d, 1d, 1d },
			new[] { 80d, 39d, 39d, 15d },
			new[] { 10, 6, 6, 4 },
			new[] { 1, 0, 0, 0 }
		);

	var cross = new CutAndSpliceCrossover();
	var child = cross.Cross(new List<IChromosome>() { c1, c2 });

	c1.ToFloatingPoints();
	c2.ToFloatingPoints();
	(child[0] as FloatingPointChromosome).ToFloatingPoints();
	(child[1] as FloatingPointChromosome).ToFloatingPoints();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.