Quick actions

cmd+k|ctrl+k

Navigation

Languages

GA

Snippet info

Language

Fsharp

Visibility

public

Author

tollask

Created

2017-04-07T13:25:46Z

Updated

2017-04-07T13:25:46Z

type Chromosome = char []
    type Fitness = int
    type Individual = Chromosome * Fitness

    let target : Chromosome = [|'H'; 'e'; 'l'; 'l'; 'o'; ' '; 'F'; '#'|]

    let eliteSize = 10

    let delta (x: char) (y: char) =
        abs( (int)x - (int)y )

    let calculateFitness (target: Chromosome) (chromosome: Chromosome) =
        Array.map2 (fun x y -> delta x y) target chromosome
        |> Array.sum

    let getFitness = calculateFitness target

    let rnd = System.Random()

    let createChromosome size : Individual =
        let chromosome = Array.init<char> size (fun _ -> (char) (rnd.Next(32, 123)) )
        let fitness = getFitness chromosome
        (chromosome, fitness)

    let initializePopulation withSize =
        Array.init<Individual> withSize (fun _ -> createChromosome target.Length)
        |> Array.sortBy (fun (_, f) -> f)

    let getElite (population: Individual []) =
        let size = population.Length / eliteSize
        population.[..size]

    let crossover (population: Individual []) =
        let top50percent = population.Length / 2
        let mom = fst population.[rnd.Next(top50percent)]
        let dad = fst population.[rnd.Next(top50percent)]

        let index = rnd.Next(target.Length)

        let chromosome = Array.append mom.[..index] dad.[index + 1..]
        let fitness = getFitness chromosome
        (chromosome, fitness)

    let newGeneration population =
        let elite = getElite population
        let withSize = population.Length - eliteSize
        Array.init<Individual> withSize (fun _ -> crossover population)
        |> Array.append elite
        |> Array.sortBy (fun (_, f) -> f)


    let printBest (population: Individual []) =
        (fst population.[0]) |> (fun x -> System.String x) |> printfn "Best (%d): %A" (snd population.[0])

    let evolve population =

        let rec evolve population n =
            printBest population

            match (n, (snd population.[0])) with
            | (0, _) -> population.[0]
            | (_, 0) -> population.[0]
            | _ ->
                let newPopulation = newGeneration population
                evolve newPopulation (n - 1)

        evolve population 100

    [<EntryPoint>]
    let main args =
        printfn "Evolve..."

        let population = initializePopulation 2048

        let best = evolve population

        System.Console.ReadLine() |> ignore
        0
INFO