### Shell: Example Output of Go Bohachevsky Minimization Source: https://github.com/maxhalford/eaopt/blob/master/README.md This snippet shows the expected console output when running the Go program for Bohachevsky function minimization. It illustrates the progressive improvement of the best fitness and coordinates over generations, demonstrating how the algorithm converges towards the global minimum. ```Shell >>> Best fitness at generation 0: 347.29009 at (-17.77572, 3.91475) >>> Best fitness at generation 1: 91.64634 at ( -7.79357, -3.88125) >>> Best fitness at generation 7: 84.31780 at ( 8.42342, -2.53296) >>> Best fitness at generation 8: 22.81205 at ( 3.64011, -2.09039) >>> Best fitness at generation 13: 3.17994 at ( -1.37117, 0.63824) >>> Best fitness at generation 25: 2.58142 at ( -1.05701, -0.29836) >>> Best fitness at generation 26: 2.34391 at ( 0.96249, -0.57655) >>> Best fitness at generation 70: 1.21768 at ( 0.23307, 0.17318) >>> Best fitness at generation 117: 0.78975 at ( 0.68306, -0.10444) >>> Best fitness at generation 119: 0.71870 at ( -0.10934, -0.14860) >>> Best fitness at generation 130: 0.47829 at ( 0.02383, 0.46641) >>> Best fitness at generation 277: 0.11108 at ( 0.00798, -0.05851) >>> Best fitness at generation 492: 0.07006 at ( -0.07098, 0.00333) >>> Best fitness at generation 860: 0.03000 at ( 0.01445, -0.02850) >>> Best fitness at generation 1149: 0.02192 at ( -0.03899, 0.00333) >>> Best fitness at generation 1270: 0.02055 at ( -0.03333, 0.01191) >>> Best fitness at generation 1596: 0.00650 at ( -0.02072, 0.00333) >>> Best fitness at generation 2945: 0.00249 at ( -0.00509, 0.00794) >>> Best fitness at generation 5551: 0.00134 at ( 0.00482, -0.00548) >>> Best fitness at generation 6551: 0.00063 at ( -0.00390, -0.00350) >>> Best fitness at generation 6780: 0.00056 at ( 0.00364, 0.00333) >>> Found a minimum at (0.00364, 0.00333). >>> The global minimum is known to lie at (0, 0). ``` -------------------------------- ### Go: Minimize Rastrigin Function with eaopt Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go example demonstrates how to minimize the 3-dimensional Rastrigin function using the `eaopt` library. It initializes a `DefaultOES` optimizer, fixes the random number generator for reproducibility, and then runs the minimization process, printing the best-found solution. The global minimum for the Rastrigin function is 0. ```Go package main import ( "fmt" m "math" "math/rand" "github.com/MaxHalford/eaopt" ) func Rastrigin(x []float64) (y float64) { y = 10 * float64(len(x)) for _, xi := range x { y += m.Pow(xi, 2) - 10*m.Cos(2*m.Pi*xi) } return y } func main() { // Instantiate DiffEvo var oes, err = eaopt.NewDefaultOES() if err != nil { fmt.Println(err) return } // Fix random number generation oes.GA.RNG = rand.New(rand.NewSource(42)) // Run minimization _, y, err := oes.Minimize(Rastrigin, 2) if err != nil { fmt.Println(err) return } // Output best encountered solution fmt.Printf("Found minimum of %.5f, the global minimum is 0\n", y) } ``` ```sh >>> Found minimum of 0.02270, the global minimum is 0 ``` -------------------------------- ### Understanding and Using Genetic Algorithms in eaopt Source: https://github.com/maxhalford/eaopt/blob/master/README.md This section details the fundamental concepts of Genetic Algorithms (GAs) as implemented in `eaopt`. It outlines the GA's five-step optimization process, defines various genetic operators, and lists common stopping criteria. It also provides a step-by-step guide on how to implement and use the `GA` struct for custom optimization problems. ```APIDOC Genetic Algorithm (GA) Usage in eaopt: Interface: Genome Description: Users must implement this interface to model their problem's solution representation and fitness evaluation. This interface defines how a solution behaves within the GA framework. Methods (Conceptual based on GA process): - EvaluateFitness(): float64 Description: Calculates the fitness score of the current genome, indicating how good a solution it is. - Mutate(): Genome Description: Applies a mutation operator to the genome, introducing small random changes. - Crossover(other Genome): Genome Description: Combines this genome with another to produce a new solution. - Clone(): Genome Description: Creates a deep copy of the genome, essential for maintaining population integrity. Struct: GA Description: The main struct for configuring and running genetic algorithms. Constructor: NewGA(config GAConfig) *GA Description: The preferred way to instantiate the GA struct, allowing for comprehensive configuration via a GAConfig struct. Methods: - Minimize(problem Genome): error Description: Initiates the optimization process. It requires an initial implementation of the Genome interface to define the problem space. Fields: - HallOfFame: []Genome Description: A collection of the best solutions (genomes) found throughout the evolutionary process, ordered by fitness. ``` -------------------------------- ### Minimize Styblinski-Tang Function with Go SPSO Source: https://github.com/maxhalford/eaopt/blob/master/README.md This example demonstrates how to minimize the Styblinski-Tang function with two dimensions using the Particle Swarm Optimization (SPSO) algorithm from the `eaopt` Go library. It shows the setup of the SPSO solver, fixing random number generation for reproducibility, and running the minimization process. The output displays the found minimum compared to the global minimum. ```Go package main import ( "fmt" m "math" "math/rand" "github.com/MaxHalford/eaopt" ) func StyblinskiTang(X []float64) (y float64) { for _, x := range X { y += m.Pow(x, 4) - 16*m.Pow(x, 2) + 5*x } return 0.5 * y } func main() { // Instantiate SPSO var spso, err = eaopt.NewDefaultSPSO() if err != nil { fmt.Println(err) return } // Fix random number generation spso.GA.RNG = rand.New(rand.NewSource(42)) // Run minimization _, y, err := spso.Minimize(StyblinskiTang, 2) if err != nil { fmt.Println(err) return } // Output best encountered solution fmt.Printf("Found minimum of %.5f, the global minimum is %.5f\n", y, -39.16599*2) } ``` ```Shell >>> Found minimum of -78.23783, the global minimum is -78.33198 ``` -------------------------------- ### Minimize Ackley Function with Go DiffEvo Source: https://github.com/maxhalford/eaopt/blob/master/README.md This example demonstrates how to minimize the Ackley function with two dimensions using the Differential Evolution (DiffEvo) algorithm from the `eaopt` Go library. It covers the instantiation of the DiffEvo solver, setting a fixed random seed, and executing the minimization process. The output shows the found minimum compared to the global minimum. ```Go package main import ( "fmt" m "math" "math/rand" "github.com/MaxHalford/eaopt" ) func Ackley(x []float64) float64 { var ( a, b, c = 20.0, 0.2, 2 * m.Pi s1, s2 float64 d = float64(len(x)) ) for _, xi := range x { s1 += xi * xi s2 += m.Cos(c * xi) } return -a*m.Exp(-b*m.Sqrt(s1/d)) - m.Exp(s2/d) + a + m.Exp(1) } func main() { // Instantiate DiffEvo var de, err = eaopt.NewDefaultDiffEvo() if err != nil { fmt.Println(err) return } // Fix random number generation de.GA.RNG = rand.New(rand.NewSource(42)) // Run minimization _, y, err := de.Minimize(Ackley, 2) if err != nil { fmt.Println(err) return } // Output best encountered solution fmt.Printf("Found minimum of %.5f, the global minimum is 0\n", y) } ``` ```Shell >>> Found minimum of 0.00001, the global minimum is 0 ``` -------------------------------- ### Define GAConfig Struct for Genetic Algorithm Setup in Go Source: https://github.com/maxhalford/eaopt/blob/master/README.md The `GAConfig` struct is used to configure a genetic algorithm instance. It includes required fields like population size, number of generations, and model, as well as optional fields for parallelization, migration, logging, and callbacks. This struct is essential for initializing a `GA` instance. ```Go type GAConfig struct { // Required fields NPops uint PopSize uint NGenerations uint HofSize uint Model Model // Optional fields ParallelInit bool // Whether to initialize Individuals in parallel or not ParallelEval bool // Whether to evaluate Individuals in parallel or not Migrator Migrator MigFrequency uint // Frequency at which migrations occur Speciator Speciator Logger *log.Logger Callback func(ga *GA) EarlyStop func(ga *GA) bool RNG *rand.Rand } ``` -------------------------------- ### Go: Implementing In-Place Mutation for eaopt.Genome (Slice) Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go example illustrates how to implement the `Mutate` method for a `Vector` (slice) type, ensuring in-place modification of the `Genome`. Since slices in Go are references to underlying data, direct modification of `X` within the method affects the original `Genome`. This approach is crucial for `eaopt`'s evolutionary algorithms to function correctly. ```Go type Vector []float64 func (X Vector) Mutate(rng *rand.Rand) { eaopt.MutNormal(X, rng, 0.5) } ``` -------------------------------- ### Go: Benchmarking and Profiling Application Performance Source: https://github.com/maxhalford/eaopt/blob/master/CONTRIBUTING.md These commands demonstrate how to benchmark and generate a CPU profile for a Go application. The `go test -bench` command runs benchmarks and creates a CPU profile, which can then be visualized using `go tool pprof` to identify performance bottlenecks. ```bash go test -bench . -cpuprofile=cpu.prof go tool pprof -pdf eaopt.test cpu.prof > profile.pdf ``` -------------------------------- ### General Usage Advice for eaopt Evolutionary Algorithms Source: https://github.com/maxhalford/eaopt/blob/master/README.md This section provides general guidelines for effectively using the `eaopt` library. It emphasizes the importance of using constructor functions for proper initialization, understanding the specific optimization capabilities of each algorithm's `Minimize` function, and leveraging pre-implemented genetic operators within the `GA` struct. ```APIDOC eaopt Library General Usage Guidelines: - Function: Minimize() Description: Each evolutionary algorithm method (e.g., PSO, GA) exposes a Minimize function. Inspect this function to understand the type of problem it is designed to optimize. - Constructor Functions (e.g., NewPSO) Description: Always use the provided constructor functions (e.g., NewPSO for PSO) to initialize algorithm structs. This ensures proper setup and parameter validation. - Struct: GA Description: The GA struct is the core of many algorithms in eaopt. It comes with pre-implemented evolutionary operators (mutation, crossover, selection, migration, speciation) that can be leveraged. ``` -------------------------------- ### Go DiffEvo Parameters and Instantiation Source: https://github.com/maxhalford/eaopt/blob/master/README.md This section details the parameters for instantiating a `DiffEvo` solver in Go. It explains the purpose of each parameter for the `NewDiffEvo` method, which allows for custom configuration, or the use of `NewDefaultDiffEvo` for standard settings. ```APIDOC func NewDiffEvo(nAgents, nSteps uint, min, max, cRate, dWeight float64, parallel bool, rng *rand.Rand) (*DiffEvo, error) Parameters: - nAgents (uint): The number of agents to use (it has to be at least 4). - nSteps (uint): The number of steps during which evolution occurs. - min (float64): The lower boundary from which the initial values are sampled. - max (float64): The upper boundary from which the initial values are sampled. - cRate (float64): The crossover rate. - dWeight (float64): The differential weight. - parallel (bool): Determines if the agents are evaluated in parallel. - rng (*rand.Rand): A random number generator; can be nil for random generation. ``` -------------------------------- ### Go SPSO Parameters and Instantiation Source: https://github.com/maxhalford/eaopt/blob/master/README.md This section details the parameters for instantiating an `SPSO` solver in Go. It explains the purpose of each parameter for the `NewSPSO` method, which allows for custom configuration, or the use of `NewDefaultSPSO` for standard settings. ```APIDOC func NewSPSO(nParticles, nSteps uint, min, max, w float64, parallel bool, rng *rand.Rand) (*SPSO, error) Parameters: - nParticles (uint): The number of particles to use. - nSteps (uint): The number of steps during which evolution occurs. - min (float64): The lower boundary from which the initial values are sampled. - max (float64): The upper boundary from which the initial values are sampled. - w (float64): The velocity amplifier. - parallel (bool): Determines if the particles are evaluated in parallel. - rng (*rand.Rand): A random number generator; can be nil for random generation. ``` -------------------------------- ### eaopt Go Library API Reference: GAConfig, GA Structs, and Minimize Method Source: https://github.com/maxhalford/eaopt/blob/master/README.md Detailed API documentation for the `GAConfig` and `GA` structs in the `eaopt` Go library, including descriptions of their fields, types, and purpose. This section also covers the `Minimize` method's parameters and return values. ```APIDOC // GAConfig Struct type GAConfig struct { // Required fields NPops uint // Number of populations. PopSize uint // Number of individuals inside each population. NGenerations uint // Number of generations the populations will be evolved. HofSize uint // Number of best individuals to be recorded. Model Model // Struct determining how to evolve each population. // Optional fields ParallelInit bool // Whether to initialize Individuals in parallel. ParallelEval bool // Whether to evaluate Individuals in parallel. Migrator Migrator // Migrator for exchanging individuals between populations. MigFrequency uint // Frequency at which migrations occur. Speciator Speciator // Splits each population into distinct species. Logger *log.Logger // Used to record basic population statistics. Callback func(ga *GA) // Executes code every time ga.Evolve() or ga.Initialize() is called. EarlyStop func(ga *GA) bool // Checks if evolution should be stopped early. RNG *rand.Rand // Random number generator for reproducibility. } // GA Struct type GA struct { GAConfig // Inherits configuration from GAConfig. Populations Populations // All current populations and individuals. HallOfFame Individuals // HofSize best individuals ever encountered, always sorted. Age time.Duration // Duration the GA has spent evolving. Generations uint // Number of generations that have gone by. } // Minimize Method func (ga *GA) Minimize(newGenome func(rng *rand.Rand) Genome) error // Parameters: // newGenome: func(rng *rand.Rand) Genome - A function that returns a Genome, recommended to contain random values. // Returns: // error: nil if the operation was successful, otherwise an error. ``` -------------------------------- ### Go: Implement Simulated Annealing for Function Minimization Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go program uses the `eaopt` library to find the minimum of the Holder table function via simulated annealing. It defines a `Coord2D` struct as a genome, implementing `Evaluate`, `Mutate`, `Crossover`, and `Clone` methods. The `eaopt.GA` is configured with a custom acceptance function and a callback to track progress, demonstrating how to set up and run an evolutionary algorithm for optimization. ```Go package main import ( "fmt" "math" "math/rand" "github.com/MaxHalford/eaopt" ) // A Coord2D is a coordinate in two dimensions. type Coord2D struct { X float64 Y float64 } // Evaluate evaluates the Holder-table function at the current coordinates. func (c *Coord2D) Evaluate() (float64, error) { z := -math.Abs(math.Sin(c.X) * math.Cos(c.Y) * math.Exp(math.Abs(1.0-math.Sqrt(c.X*c.X+c.Y*c.Y)/math.Pi))) return z, nil } // Mutate replaces one of the current coordinates with a random value in [-10, 10). func (c *Coord2D) Mutate(rng *rand.Rand) { v := rng.Float64()*20.0 - 10.0 if rng.Intn(2) == 0 { c.X = v } else { c.Y = v } } // Crossover does nothing. It is defined only so *Coord2D implements the eaopt.Genome interface. func (c *Coord2D) Crossover(other eaopt.Genome, rng *rand.Rand) {} // Clone returns a copy of a *Coord2D. func (c *Coord2D) Clone() eaopt.Genome { cc := *c return &cc } func main() { // Simulated annealing is implemented as a GA using the ModSimulatedAnnealing model. cfg := eaopt.NewDefaultGAConfig() cfg.Model = eaopt.ModSimulatedAnnealing{ Accept: func(g, ng uint, e0, e1 float64) float64 { // Accept readily in early generations but reluctantly in later generations. t := 1.0 - float64(g)/float64(ng) return (math.Cos(t*math.Pi) + 1.0) / 2.0 }, } cfg.NGenerations = 999 // Add a custom callback function to track progress. minFit := math.MaxFloat64 cfg.Callback = func(ga *eaopt.GA) { hof0 := ga.HallOfFame[0] fit := hof0.Fitness if fit == minFit { // Output only when we make an improvement. return } best := hof0.Genome.(*Coord2D) fmt.Printf("Best fitness at generation %3d: %10.5f at (%9.5f, %9.5f)\n", ga.Generations, fit, best.X, best.Y) minFit = fit } // Run the simulated-annealing algorithm. ga, err := cfg.NewGA() if err != nil { panic(err) } err = ga.Minimize(func(rng *rand.Rand) eaopt.Genome { var c Coord22D c.X = rng.Float64() c.Y = rng.Float64() return &c }) if err != nil { panic(err) } // Output the best encountered solution. hof0 := ga.HallOfFame[0] best := hof0.Genome.(*Coord2D) fmt.Printf("Found a minimum at (%.5f, %.5f) --> %.5f.\n", best.X, best.Y, hof0.Fitness) fmt.Println("The global minimum is known to lie at (±8.05502, ±9.66459) and have value -19.20850.") } ``` ```Console Output Best fitness at generation 0: -1.62856 at ( 0.97142, 0.13185) Best fitness at generation 1: -5.70555 at ( 0.81465, -9.68769) Best fitness at generation 2: -8.22368 at ( -8.35803, 6.91242) Best fitness at generation 3: -13.40055 at ( 7.36818, -9.18324) Best fitness at generation 6: -16.45462 at ( -7.49961, -9.68769) Best fitness at generation 7: -16.53317 at ( 8.50224, -9.39214) Best fitness at generation 8: -19.06737 at ( -7.93491, 9.65411) Best fitness at generation 12: -19.18453 at ( 8.02260, -9.70168) Best fitness at generation 44: -19.18972 at ( -8.04929, 9.70731) Best fitness at generation 80: -19.19616 at ( -8.04283, 9.63179) Best fitness at generation 82: -19.20817 at ( 8.05422, 9.65894) Found a minimum at (8.05422, 9.65894) --> -19.20817. The global minimum is known to lie at (±8.05502, ±9.66459) and have value -19.20850. ``` -------------------------------- ### Go: Enable Logging for GA Population Statistics Source: https://github.com/maxhalford/eaopt/blob/master/README.md To monitor the evolution of genetic algorithm populations, attach a standard Go `log.Logger` instance to the `GA` struct's `Logger` field. This configuration directs detailed statistics, such as population ID, minimum, maximum, and average fitness, and fitness standard deviation, to the specified output, like standard output or a file. It provides real-time insights into the population's performance across generations. ```Go ga.Logger = log.New(os.Stdout, "", log.Ldate|log.Ltime) ``` -------------------------------- ### APIDOC: eaopt.NewOES Function Parameters Source: https://github.com/maxhalford/eaopt/blob/master/README.md This API documentation details the `NewOES` constructor method for the `OES` optimizer in Go's `eaopt` library. It lists all parameters required to instantiate an `OES` object, including `nPoints`, `nSteps`, `sigma`, `lr`, `parallel`, and `rng`, along with their types and descriptions. This method allows for custom configuration of the optimizer beyond the default settings. ```Go func NewOES(nPoints, nSteps uint, sigma, lr float64, parallel bool, rng *rand.Rand) (*OES, error) ``` ```APIDOC - nPoints: uint - The number of points to use (it has to be at least 3) - nSteps: uint - The number of steps during which evolution occurs - sigma: float64 - Determines the shape of the normal distribution used to sample new points - lr: float64 - The learning rate - parallel: bool - Determines if the agents are evaluated in parallel or not - rng: *rand.Rand - A random number generator, you can set it to `nil` if you want it to be random ``` -------------------------------- ### Shell: Observe Genetic Algorithm Optimization Progress Source: https://github.com/maxhalford/eaopt/blob/master/README.md This shell output displays the progress of the genetic algorithm as it minimizes the Drop-Wave function. It shows the best fitness value found at each generation, illustrating the convergence of the algorithm towards the minimum. ```Shell >>> Best fitness at generation 0: -0.550982 >>> Best fitness at generation 1: -0.924220 >>> Best fitness at generation 2: -0.987282 >>> Best fitness at generation 3: -0.987282 >>> Best fitness at generation 4: -0.987282 >>> Best fitness at generation 5: -0.987282 >>> Best fitness at generation 6: -0.987282 >>> Best fitness at generation 7: -0.997961 >>> Best fitness at generation 8: -0.999954 >>> Best fitness at generation 9: -0.999995 >>> Best fitness at generation 10: -0.999999 ``` -------------------------------- ### Go: Implement Genetic Algorithm for Drop-Wave Function Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go code demonstrates how to use the `eaopt` library to minimize the Drop-Wave function. It defines a `Vector` type as a custom genome, implementing `Evaluate`, `Mutate`, `Crossover`, and `Clone` methods. The `main` function initializes and runs a genetic algorithm to find the minimum value of the function. ```Go package main import ( "fmt" m "math" "math/rand" "github.com/MaxHalford/eaopt" ) // A Vector contains float64s. type Vector []float64 // Evaluate a Vector with the Drop-Wave function which takes two variables as // input and reaches a minimum of -1 in (0, 0). The function is simple so there // isn't any error handling to do. func (X Vector) Evaluate() (float64, error) { var ( numerator = 1 + m.Cos(12*m.Sqrt(m.Pow(X[0], 2)+m.Pow(X[1], 2))) denominator = 0.5*(m.Pow(X[0], 2)+m.Pow(X[1], 2)) + 2 ) return -numerator / denominator, nil } // Mutate a Vector by resampling each element from a normal distribution with // probability 0.8. func (X Vector) Mutate(rng *rand.Rand) { eaopt.MutNormalFloat64(X, 0.8, rng) } // Crossover a Vector with another Vector by applying uniform crossover. func (X Vector) Crossover(Y eaopt.Genome, rng *rand.Rand) { eaopt.CrossUniformFloat64(X, Y.(Vector), rng) } // Clone a Vector to produce a new one that points to a different slice. func (X Vector) Clone() eaopt.Genome { var Y = make(Vector, len(X)) copy(Y, X) return Y } // VectorFactory returns a random vector by generating 2 values uniformally // distributed between -10 and 10. func VectorFactory(rng *rand.Rand) eaopt.Genome { return Vector(eaopt.InitUnifFloat64(2, -10, 10, rng)) } func main() { // Instantiate a GA with a GAConfig var ga, err = eaopt.NewDefaultGAConfig().NewGA() if err != nil { fmt.Println(err) return } // Set the number of generations to run for ga.NGenerations = 10 // Add a custom print function to track progress ga.Callback = func(ga *eaopt.GA) { fmt.Printf("Best fitness at generation %d: %f\n", ga.Generations, ga.HallOfFame[0].Fitness) } // Find the minimum err = ga.Minimize(VectorFactory) if err != nil { fmt.Println(err) return } } ``` -------------------------------- ### Define Go eaopt Genome Interface Source: https://github.com/maxhalford/eaopt/blob/master/README.md The `Genome` interface is the core contract for defining your problem's specific logic within the `eaopt` framework. It includes methods for evaluating a solution's fitness, mutating its variables, combining it with another solution, and creating independent copies. Implementing this interface allows `eaopt` to apply its generic optimization algorithms to your unique problem. ```Go type Genome interface { Evaluate() (float64, error) Mutate(rng *rand.Rand) Crossover(genome Genome, rng *rand.Rand) Clone() Genome } ``` ```APIDOC interface Genome { /** * @method Evaluate * @description Calculates and returns the fitness of a genome. This method encapsulates the problem's evaluation logic and can return an error if the evaluation fails. * @returns {float64} The fitness value of the genome. * @returns {error} An error if the evaluation process encounters an issue. */ Evaluate(): (float64, error); /** * @method Mutate * @description Modifies the genome's variables to introduce variation. The specific mutation logic depends on the problem being solved. * @param {*rand.Rand} rng - A random number generator to use for stochastic operations. * @returns {void} */ Mutate(rng *rand.Rand): void; /** * @method Crossover * @description Combines the current genome with another `Genome` to produce new genetic material. Due to Go's type system, the input `genome` typically needs to be type-asserted to the concrete struct. * @param {Genome} genome - The other genome to combine with. * @param {*rand.Rand} rng - A random number generator to use for stochastic operations. * @returns {void} */ Crossover(genome Genome, rng *rand.Rand): void; /** * @method Clone * @description Creates and returns an independent, deep copy of the genome. This is essential to prevent unintended side effects from shared memory addresses during evolutionary operations. * @returns {Genome} A new, independent copy of the genome. */ Clone(): Genome; } ``` -------------------------------- ### Call Minimize Method for Genetic Algorithm Optimization in Go Source: https://github.com/maxhalford/eaopt/blob/master/README.md The `Minimize` method initiates the genetic algorithm's optimization process. It requires a function that generates a `Genome`, typically with random values. Upon completion, it returns an error, and the best solution can be retrieved from the `HallOfFame` field. ```Go func (ga *GA) Minimize(newGenome func(rng *rand.Rand) Genome) error ``` -------------------------------- ### APIDOC: Overview of eaopt Genetic Algorithm Models Source: https://github.com/maxhalford/eaopt/blob/master/README.md eaopt provides various 'models' that define how a Genetic Algorithm evolves a population of individuals through genetic operators. These models abstract the underlying operator intrinsics, mimicking real-world evolution. Selecting the appropriate model is crucial as it significantly impacts GA performance. ```APIDOC Concept: Genetic Algorithm Models Description: Defines the evolutionary strategy for a GA population. Purpose: Mimics real-world evolution, abstracting genetic operator details. Importance: High influence on GA performance. Types: Generational, Steady State, Select Down to Size, Ring, Mutation Only. ``` -------------------------------- ### APIDOC: Select Down to Size Genetic Algorithm Model Source: https://github.com/maxhalford/eaopt/blob/master/README.md The Select Down to Size model employs two selection rounds. Initially, parents are selected to generate 'm' offsprings via crossover. These 'm' offsprings are then merged with the original population of 'n' individuals. A second selection round then occurs on the combined 'n+m' individuals to select down to the original population size of 'n' for the next generation. ```APIDOC Model: Select Down to Size Description: Uses a two-round selection process to manage population size. Process: 1. Generate 'm' offsprings from 'n' parents via crossover. 2. Merge the 'm' offsprings with the original 'n' population (total 'n+m' individuals). 3. Perform a second selection round on the 'n+m' individuals to select 'n' survivors for the next generation. ``` -------------------------------- ### Go: Define Cosine Temperature Drop Accept Function Source: https://github.com/maxhalford/eaopt/blob/master/README.md This `Accept` function utilizes a cosine function to control the acceptance probability. This results in a slow drop at the beginning and end of the evolution, with a quicker decrease in between, providing a different annealing schedule. ```Go func(g, ng uint, e0, e1 float64) float64 { t := 1.0 - float64(g)/float64(ng) return (math.Cos(t*math.Pi) + 1.0) / 2.0 } ``` -------------------------------- ### Go: Enforcing `var` for Variable Declaration Source: https://github.com/maxhalford/eaopt/blob/master/CONTRIBUTING.md This snippet illustrates the preferred Go variable declaration style within the `eaopt` project. It recommends using `var` for explicit type declaration or initialization over the shorthand `:=` operator for improved readability and consistency. ```go // Bad x := 42 // Good var x = 42 ``` -------------------------------- ### Go: Minimize Bohachevsky Function using eaopt Hill Climbing Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go program defines a `Coord2D` struct representing a 2D coordinate and implements the `eaopt.Genome` interface for it. It then configures and runs a hill-climbing genetic algorithm using `eaopt`'s `ModMutationOnly` model to find the minimum of the Bohachevsky function. The program prints the best fitness and coordinates found at each generation where an improvement occurs, ultimately reporting the final minimum. ```Go package main import ( "fmt" "math" "math/rand" "github.com/MaxHalford/eaopt" ) // A Coord2D is a coordinate in two dimensions. type Coord2D struct { X float64 Y float64 } // Evaluate evalutes a Bohachevsky function at the current coordinates. func (c *Coord2D) Evaluate() (float64, error) { z := c.X*c.X + 2*c.Y*c.Y - 0.3*math.Cos(3*math.Pi*c.X) - 0.4*math.Cos(4*math.Pi*c.Y) + 0.7 return z, nil } // Mutate replaces one of the current coordinates with a random value in [-100, -100]. func (c *Coord2D) Mutate(rng *rand.Rand) { if rng.Intn(2) == 0 { c.X = rng.Float64()*200.0 - 100.0 } else { c.Y = rng.Float64()*200.0 - 100.0 } } // Crossover does nothing. It is defined only so *Coord2D implements the eaopt.Genome interface. func (c *Coord2D) Crossover(other eaopt.Genome, rng *rand.Rand) {} // Clone returns a copy of a *Coord2D. func (c *Coord2D) Clone() eaopt.Genome { return &Coord2D{X: c.X, Y: c.Y} } func main() { // Hill climbing is implemented as a GA using the ModMutationOnly model // with the Strict option. cfg := eaopt.NewDefaultGAConfig() cfg.Model = eaopt.ModMutationOnly{Strict: true} cfg.NGenerations = 9999 // Add a custom callback function to track progress. minFit := math.MaxFloat64 cfg.Callback = func(ga *eaopt.GA) { hof := ga.HallOfFame[0] fit := hof.Fitness if fit == minFit { // Output only when we make an improvement. return } best := hof.Genome.(*Coord2D) fmt.Printf("Best fitness at generation %4d: %10.5f at (%9.5f, %9.5f)\n", ga.Generations, fit, best.X, best.Y) minFit = fit } // Run the hill-climbing algorithm. ga, err := cfg.NewGA() if err != nil { panic(err) } err = ga.Minimize(func(rng *rand.Rand) eaopt.Genome { return &Coord2D{ X: rng.Float64()*200.0 - 100.0, Y: rng.Float64()*200.0 - 100.0, } }) if err != nil { panic(err) } // Output the best encountered solution. best := ga.HallOfFame[0].Genome.(*Coord2D) fmt.Printf("Found a minimum at (%.5f, %.5f).\n", best.X, best.Y) fmt.Println("The global minimum is known to lie at (0, 0).") } ``` -------------------------------- ### Go: Define Exponential Temperature Drop Accept Function Source: https://github.com/maxhalford/eaopt/blob/master/README.md This `Accept` function uses an exponential decay for the acceptance probability. This causes the probability to drop quickly at the beginning of the evolution and then more slowly towards the end, ensuring some acceptance probability remains. ```Go func(g, ng uint, e0, e1 float64) float64 { t := 1.0 - float64(g)/float64(ng) return math.Exp(-3.0 * t) } ``` -------------------------------- ### Define GA Struct for Genetic Algorithm Management in Go Source: https://github.com/maxhalford/eaopt/blob/master/README.md The `GA` struct represents the core genetic algorithm instance, inheriting configuration from `GAConfig`. It manages populations, stores the best individuals in `HallOfFame`, and tracks the algorithm's age and generation count. This struct is the primary interface for running the optimization process. ```Go type GA struct { GAConfig Populations Populations HallOfFame Individuals Age time.Duration Generations uint } ``` -------------------------------- ### APIDOC: Ring Topology Genetic Algorithm Model Source: https://github.com/maxhalford/eaopt/blob/master/README.md In the Ring model, crossover operations are applied to neighboring individuals arranged in a one-directional ring topology. Two adjacent neighbors generate two offsprings. The best individual among the four (two parents and two offsprings) then replaces the first neighbor in the ring, propagating changes locally. ```APIDOC Model: Ring Description: Crossovers are applied to neighbours in a one-directional ring topology. Process: 1. Two adjacent neighbours generate 2 offsprings. 2. The best individual out of the 4 (2 parents + 2 offsprings) replaces the first neighbour. ``` -------------------------------- ### Go: Implementing a Blank Crossover Method for eaopt.Genome Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go code snippet demonstrates how to implement a blank `Crossover` method for the `eaopt.Genome` interface. It's useful when you need to satisfy the interface but do not wish to use crossover functionality in your evolutionary algorithm. The `Vector` type, being a slice, inherently allows in-place modification. ```Go type Vector []float64 func (X Vector) Crossover(Y eaopt.Genome, rng *rand.Rand) {} ``` -------------------------------- ### Go: Define and Implement the eaopt Slice Interface Source: https://github.com/maxhalford/eaopt/blob/master/README.md The `Slice` interface is fundamental in `eaopt` for representing genetic algorithm genomes, such as vectors or DNA sequences. It defines methods for accessing, modifying, and manipulating slices, enabling various mutation and crossover algorithms. Users must implement this interface for custom slice types to utilize `eaopt`'s operators. ```Go type Slice interface { At(i int) interface{} Set(i int, v interface{}) Len() int Swap(i, j int) Slice(a, b int) Slice Split(k int) (Slice, Slice) Append(Slice) Slice Replace(Slice) Copy() Slice } ``` ```APIDOC Interface: Slice Description: Core interface for genetic algorithm genomes (vectors, sequences). Purpose: Enables mutation and crossover operations on various data types. Methods: - At(i int): interface{} - Retrieves element at index 'i'. - Set(i int, v interface{}) - Sets element at index 'i' to value 'v'. - Len(): int - Returns the length of the slice. - Swap(i, j int) - Swaps elements at indices 'i' and 'j'. - Slice(a, b int): Slice - Returns a sub-slice from index 'a' to 'b'. - Split(k int): (Slice, Slice) - Splits the slice into two at index 'k'. - Append(Slice): Slice - Appends another Slice to the current one. - Replace(Slice) - Replaces the content of the current slice with another. - Copy(): Slice - Returns a deep copy of the slice. Implementations: IntSlice, Float64Slice, StringSlice (provided internally). Requirement: Must be implemented for custom genome types to use eaopt operators. ``` -------------------------------- ### APIDOC: Generational Genetic Algorithm Model Source: https://github.com/maxhalford/eaopt/blob/master/README.md The Generational model is a popular approach where 'n' offsprings are generated from a population of size 'n', completely replacing the original population. Offsprings are created by selecting two individuals, applying crossover, and then optionally mutating them. If the population size is odd, the last offspring from crossover might not be included. ```APIDOC Model: Generational Description: Generates 'n' offsprings to replace an entire population of 'n' individuals. Process: 1. Select two parents. 2. Apply crossover to generate two offsprings. 3. Optionally mutate offsprings. 4. Repeat until 'n' offsprings are generated. 5. Replace the entire current population with the new offsprings. Note: If population size is odd, one offspring from the last crossover may be excluded. ``` -------------------------------- ### Go: Define Linear Temperature Drop Accept Function Source: https://github.com/maxhalford/eaopt/blob/master/README.md This `Accept` function implements a linear decrease in acceptance probability, often referred to as 'temperature'. The probability drops directly from 1.0 to 0.0 as the generation number `g` increases from 0 to `ng` (total generations). ```Go func(g, ng uint, e0, e1 float64) float64 { t := 1.0 - float64(g)/float64(ng) return t } ``` -------------------------------- ### APIDOC: Mutation-Only Genetic Algorithm Model Source: https://github.com/maxhalford/eaopt/blob/master/README.md The Mutation Only model allows running a Genetic Algorithm without any crossover operations, relying solely on mutation. This is achieved using the `ModMutationOnly` struct. In each generation, every individual is mutated. The `strict` field within `ModMutationOnly` determines if the mutated individual replaces the original only if its fitness is superior. ```APIDOC Model: Mutation Only Description: Runs a GA solely through mutation, without crossover. Implementation: Uses the `ModMutationOnly` struct. Process: Each individual is mutated per generation. Configuration: `strict` field determines if the mutant replaces the original only if its fitness is better. ``` -------------------------------- ### Go: Define Accept Function to Always Accept Worse Moves Source: https://github.com/maxhalford/eaopt/blob/master/README.md This `Accept` function always returns 1.0, meaning a worse point will always be accepted. This behavior is equivalent to using the `ModMutationOnly` model with `Strict: false`, allowing any mutation to be accepted regardless of fitness. ```Go func(g, ng uint, e0, e1 float64) float64 { return 1.0 } ``` -------------------------------- ### Go: Define Accept Function to Never Accept Worse Moves Source: https://github.com/maxhalford/eaopt/blob/master/README.md This `Accept` function always returns 0.0, meaning a worse point will never be accepted. This behavior is equivalent to using the `ModMutationOnly` model with `Strict: true`, ensuring only improvements are accepted. ```Go func(g, ng uint, e0, e1 float64) float64 { return 0.0 } ``` -------------------------------- ### APIDOC: Steady State Genetic Algorithm Model Source: https://github.com/maxhalford/eaopt/blob/master/README.md The Steady State model differs from the Generational model by not replacing the entire population. Instead, it maintains a constant population size by adding the 2 best individuals (from parents and children) back into the population. Alternatively, parents can be replaced by children regardless of fitness, which avoids evaluation and can benefit long-term potential. ```APIDOC Model: Steady State Description: Maintains a constant population size without full replacement. Process: Option 1 (Fitness-based): Select 2 parents, generate 2 children. Add the 2 best individuals (from 2 parents + 2 children) back to the population. Option 2 (Direct Replacement): Replace parents with children regardless of fitness. Advantages: Avoids full population evaluation; can give sub-par but high-potential individuals a chance. ``` -------------------------------- ### Go: Implementing In-Place Mutation for eaopt.Genome (Pointer Struct) Source: https://github.com/maxhalford/eaopt/blob/master/README.md This Go code snippet shows how to correctly implement the `Mutate` method for a non-slice struct type, `Name`, by using a pointer receiver. To modify the `Genome` in-place, the `*` symbol is necessary to access and change the value pointed to by `n`. This ensures that the mutation operation persists outside the method call. ```Go type Name string func (n *Name) Mutate(rng *rand.Rand) { n = randomName() } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.