// Copyright 2023 wanderer // SPDX-License-Identifier: GPL-3.0-or-later package ga import ( "git.dotya.ml/wanderer/math-optim/bench/cec2020" "golang.org/x/exp/rand" "gonum.org/v1/gonum/stat/distuv" ) // PopulationIndividual represents a single population individual. type SOMAT3APopulationIndividual struct { CurX DecisionVector PRTVector []float64 Jumps [][]float64 } // ChampionIndividual is a representation of the best individual currently // available in the population. type SOMAT3AChampionIndividual struct { X DecisionVector } // Population groups population individuals (agents) with metadata about the population. type SOMAT3APopulation struct { // Population is a slice of population individuals. Population []SOMAT3APopulationIndividual // Champion represents the best individual of the population. Champion SOMAT3AChampionIndividual // Problem is the current benchmarking function this population is attempting to optimise. Problem string // ProblemFunction is the actual function to optimise. ProblemFunc func([]float64) float64 // Dimen is the dimensionality of the problem being optimised. Dimen int // fes is the current number of function evaluations. fes int // Seed is the value used to (re)init population. Seed uint64 zeroToOneRNG distuv.Uniform // PRT is the perturbation parameter. PRT float64 // K is the number of individuals to choose the leader from. K int // M denotes how many individuals are picked from the population to form a // `team` during the organisation phase, can be thought of as "team size". M int // N is the number of best individuals in each team selected for actual // migration. N int // Njumps is the fixed number of jumps that each chosen migrating // individual performs on their way to the leader. Njumps int } // GetIndividual returns a reference to individual at position n. func (p *SOMAT3APopulation) GetIndividual(n uint) *PopulationIndividual { return &PopulationIndividual{} } // GetBestIdx returns the index of the best population individual. func (p *SOMAT3APopulation) GetBestIdx() int { f := p.ProblemFunc bestIndividual := 0 // the first one is the best one. bestVal := f(p.Population[0].CurX) for i, v := range p.Population { current := f(v.CurX) if current < bestVal { bestIndividual = i } } return bestIndividual } // GetWorstIdx returns the index of the worst population individual. func (p *SOMAT3APopulation) GetWorstIdx() int { f := p.ProblemFunc worstIndividual := 0 // the first one is the worst one. worstVal := f(p.Population[0].CurX) for i, v := range p.Population { current := f(v.CurX) if current > worstVal { worstIndividual = i } } return worstIndividual } // Init initialises all individuals to random values. func (p *SOMAT3APopulation) Init() { low := cec2020.SearchRange.Min() high := cec2020.SearchRange.Max() // zeroToOneRNG := distuv.Uniform{ p.zeroToOneRNG = distuv.Uniform{ Min: 0, Max: 1, Src: rand.NewSource(p.Seed), } // gaLogger.Printf("population initialisation - popCount: %d, seed: %d\n", // len(p.Population), p.Seed, // ) p.PRT = p.getPrt() // for i,v := range p.Population { for i := range p.Population { v := SOMAT3APopulationIndividual{} v.CurX = make([]float64, p.Dimen) for j := 0; j < p.Dimen; j++ { // with current settings, this will always be `low + 0` since // `high - low = 0`. v.CurX[j] = low + p.zeroToOneRNG.Rand()*(high-low) } v.PRTVector = p.getPrtVector() v.Jumps = make([][]float64, p.Njumps) p.Population[i] = v } p.Champion = SOMAT3AChampionIndividual{X: p.Population[p.GetBestIdx()].CurX} } // Reinit reinitialises all individuals. func (p *SOMAT3APopulation) Reinit() { p.Init() } // Clear sets all vectors to 0. func (p *SOMAT3APopulation) Clear() { if p.Population != nil { for _, v := range p.Population { v.CurX = make([]float64, p.Dimen) } } } // Size returns the number of population individuals. func (p *SOMAT3APopulation) Size() int { return len(p.Population) } // newPopulation returns a pointer to a new, uninitialised population. func newSOMAT3APopulation(benchProblem string, np, k, m, n, nj, dimen int) *SOMAT3APopulation { p := &SOMAT3APopulation{ Problem: benchProblem, ProblemFunc: cec2020.Functions[benchProblem], K: k, M: m, N: n, Njumps: nj, Dimen: dimen, Population: make([]SOMAT3APopulationIndividual, np), } return p }