chore: add package de (Differential Evolution)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
base package (wip)
This commit is contained in:
parent
84fcad715c
commit
525b30c38e
6
algo/de/doc.go
Normal file
6
algo/de/doc.go
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2023 wanderer <a_mirre at utb dot cz>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// Package de contains implementation details of Differential Evolution kind of
|
||||
// algorithms.
|
||||
package de
|
139
algo/de/jDE.go
Normal file
139
algo/de/jDE.go
Normal file
@ -0,0 +1,139 @@
|
||||
// Copyright 2023 wanderer <a_mirre at utb dot cz>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package de
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"git.dotya.ml/wanderer/math-optim/stats"
|
||||
)
|
||||
|
||||
// JDE is a holder for the settings of an instance of a self-adapting
|
||||
// differential evolution (jDE) algorithm.
|
||||
type JDE struct {
|
||||
// Generations denotes the number of generations the population evolves
|
||||
// for. Special value -1 disables limiting the number of generations.
|
||||
Generations int
|
||||
// Dimensions to solve the problem for.
|
||||
Dimensions []int
|
||||
// F is the differential weight (mutation/weighting factor).
|
||||
F float64
|
||||
// CR is the crossover probability constant.
|
||||
CR float64
|
||||
// MutationStrategy selects the mutation strategy, i.e. the variant of the
|
||||
// jDE algorithm (0..17), see mutationStrategies.go for more details.
|
||||
MutationStrategy int
|
||||
// AdptScheme is the parameter self-adaptation scheme (0..1).
|
||||
AdptScheme int
|
||||
// NP is the initial population size.
|
||||
NP int
|
||||
// Population is a pointer to population
|
||||
Population *Population
|
||||
// BenchName is a name of the problem to optimise.
|
||||
BenchName string
|
||||
// initialised denotes the initialisation state of the struct.
|
||||
initialised bool
|
||||
}
|
||||
|
||||
const (
|
||||
// jDEMinNP is the minimum size of the initial population for jDE.
|
||||
jDEMinNP = 4
|
||||
// fMin is the minimum allowed value of the differential weight.
|
||||
fMin = 0.5
|
||||
// fMax is the maximum allowed value of the differential weight.
|
||||
fMax = 2.0
|
||||
// crMin is the minimum allowed value of the crossover probability constant.
|
||||
crMin = 0.2
|
||||
// crMax is the maximum allowed value of the crossover probability constant.
|
||||
crMax = 0.9
|
||||
)
|
||||
|
||||
// jDELogger declares and initialises a "custom" jDE logger.
|
||||
var jDELogger = log.New(os.Stderr, " *** δ jDE:", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
// Init initialises the jDE algorithm, performs sanity checks on the inputs.
|
||||
func (j *JDE) Init(generations, mutStrategy, adptScheme, np int, f, cr float64, dimensions []int, bench string, ch chan []stats.Stats) {
|
||||
if j == nil {
|
||||
jDELogger.Fatalln("jDE needs to be initialised before calling RunjDE, exiting...")
|
||||
}
|
||||
|
||||
// check input parameters.
|
||||
switch {
|
||||
case generations == 0:
|
||||
jDELogger.Fatalln("Generations cannot be 0, got", generations)
|
||||
|
||||
case generations == -1:
|
||||
jDELogger.Println("Generations is '-1', disabling generation limits..")
|
||||
|
||||
case mutStrategy < 0 || mutStrategy > 17:
|
||||
jDELogger.Fatalln("Mutation strategy needs to be from the interval <0; 17>, got", mutStrategy)
|
||||
|
||||
case adptScheme < 0 || adptScheme > 1:
|
||||
jDELogger.Fatalln("Parameter self-adaptation scheme needs to be from the interval <0; 1>, got", adptScheme)
|
||||
|
||||
case np < jDEMinNP:
|
||||
jDELogger.Fatalf("NP needs to be greater than %d, got: %d\n.", jDEMinNP, np)
|
||||
|
||||
case f < fMin || f > fMax:
|
||||
jDELogger.Fatalf("F needs to be from the interval <%f;%f>, got: %f\n.", fMin, fMax, f)
|
||||
|
||||
case cr < crMin || cr > crMax:
|
||||
jDELogger.Fatalf("CR needs to be from the interval <%f;>%f, got: %f\n.", crMin, crMax, cr)
|
||||
|
||||
case len(dimensions) == 0:
|
||||
jDELogger.Fatalf("Dimensions cannot be empty, got: %+v\n", dimensions)
|
||||
|
||||
case bench == "":
|
||||
jDELogger.Fatalln("Bench cannot be empty, got:", bench)
|
||||
}
|
||||
|
||||
j.Generations = generations
|
||||
j.MutationStrategy = mutStrategy
|
||||
j.AdptScheme = adptScheme
|
||||
j.NP = np
|
||||
j.F = f
|
||||
j.CR = cr
|
||||
j.Dimensions = dimensions
|
||||
j.BenchName = bench
|
||||
j.initialised = true
|
||||
|
||||
pop := newPopulation(bench, j.NP)
|
||||
|
||||
pop.Init()
|
||||
}
|
||||
|
||||
// Evolve evolves a population by running the jDE (self-adapting Differential
|
||||
// Evolution) algorithm on the passed population until termination conditions
|
||||
// are met.
|
||||
func (j *JDE) Evolve(maxFES int, wg *sync.WaitGroup) {}
|
||||
|
||||
// Run self-adapting differential evolution algorithm.
|
||||
func RunjDE(jDE *JDE) {}
|
||||
|
||||
// NewjDE returns a pointer to a new, uninitialised jDE instance.
|
||||
func NewjDE() *JDE {
|
||||
return &JDE{}
|
||||
}
|
||||
|
||||
// LogPrintln wraps the jDE logger's Println func.
|
||||
func LogPrintln(v ...any) {
|
||||
jDELogger.Println(v...)
|
||||
}
|
||||
|
||||
// LogPrintf wraps the jDE logger's Printf func.
|
||||
func LogPrintf(s string, v ...any) {
|
||||
jDELogger.Printf(s, v...)
|
||||
}
|
||||
|
||||
// LogFatalln wraps the jDE logger's Fatalln func.
|
||||
func LogFatalln(s string) {
|
||||
jDELogger.Fatalln(s)
|
||||
}
|
||||
|
||||
// LogFatalf wraps the jDE logger's Fatalf func.
|
||||
func LogFatalf(s string, v ...any) {
|
||||
jDELogger.Fatalf(s, v...)
|
||||
}
|
51
algo/de/mutationStrategies.go
Normal file
51
algo/de/mutationStrategies.go
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2023 wanderer <a_mirre at utb dot cz>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package de
|
||||
|
||||
const (
|
||||
// DEBest1Exp is the DE/best/1/exp strategy.
|
||||
DEBest1Exp int = iota
|
||||
// DERand1Exp is the DE/rand/1/exp strategy.
|
||||
DERand1Exp
|
||||
// DERandtoBest1Exp is the DE/rand-to-best/1/exp strategy.
|
||||
DERandtoBest1Exp
|
||||
// DEBest2Exp is the DE/best/2/exp strategy.
|
||||
DEBest2Exp
|
||||
// DERand2Exp is the DE/rand/2/exp strategy.
|
||||
DERand2Exp
|
||||
|
||||
// binomial cross-over strategies.
|
||||
|
||||
// DEBest1Bin is the DE/best/1/bin strategy.
|
||||
DEBest1Bin
|
||||
// DERand1Bin is the DE/rand/1/bin strategy.
|
||||
DERand1Bin
|
||||
// DERandtoBest1Bin is the DE/rand-to-best/1/bin strategy.
|
||||
DERandtoBest1Bin
|
||||
// DEBest2Bin is the DE/best/2/bin strategy.
|
||||
DEBest2Bin
|
||||
// DERand2Bin is the DE/rand/2/bin strategy.
|
||||
DERand2Bin
|
||||
|
||||
// 3-wide changes.
|
||||
|
||||
// DEBest3Exp is the DE/best/3/exp strategy.
|
||||
DEBest3Exp
|
||||
// DEBest3Bin is the DE/best/3/bin strategy.
|
||||
DEBest3Bin
|
||||
// DERand3Exp is the DE/rand/3/exp strategy.
|
||||
DERand3Exp
|
||||
// DERand3Bin is the DE/rand/3/bin strategy.
|
||||
DERand3Bin
|
||||
|
||||
// DERandtoCurrent2E is the DE/rand-to-current/2/exp strategy.
|
||||
DERandtoCurrent2Exp
|
||||
// DERandtoCurrent2Bin is the DE/rand-to-current/2/bin strategy.
|
||||
DERandtoCurrent2Bin
|
||||
|
||||
// DERandtoBestandCurrent2Exp is the DE/rand-to-best-and-current/2/exp strategy.
|
||||
DERandtoBestandCurrent2Exp
|
||||
// DERandtoBestandCurrent2Bin is the DE/rand-to-best-and-current/2/bin strategy.
|
||||
DERandtoBestandCurrent2Bin
|
||||
)
|
75
algo/de/population.go
Normal file
75
algo/de/population.go
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2023 wanderer <a_mirre at utb dot cz>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package de
|
||||
|
||||
type (
|
||||
// DecisionVector is a []float64 abstraction representing the decision vector.
|
||||
DecisionVector []float64
|
||||
// FitnessVector is a []float64 abstraction representing the fitness vector.
|
||||
FitnessVector []float64
|
||||
// ConstraintVector is a []float64 abstraction representing the constraint vector.
|
||||
ConstraintVector []float64
|
||||
)
|
||||
|
||||
// PopulationIndividual representats a single population individual.
|
||||
type PopulationIndividual struct {
|
||||
CurX DecisionVector
|
||||
CurV DecisionVector
|
||||
CurC ConstraintVector
|
||||
CurF FitnessVector
|
||||
|
||||
BestX DecisionVector
|
||||
BestC ConstraintVector
|
||||
BestF FitnessVector
|
||||
}
|
||||
|
||||
// ChampionIndividual is a representation of the best individual currently
|
||||
// available in the population.
|
||||
type ChampionIndividual struct {
|
||||
X DecisionVector
|
||||
C ConstraintVector
|
||||
F FitnessVector
|
||||
}
|
||||
|
||||
// Population groups population individuals (agents) with metadata about the population.
|
||||
type Population struct {
|
||||
// Population is a slice of population individuals.
|
||||
Population []PopulationIndividual
|
||||
// Problem is the current benchmarking function this population is attempting to optimise.
|
||||
Problem string
|
||||
// Seed is the value used to (re)init population.
|
||||
Seed uint64
|
||||
}
|
||||
|
||||
// GetIndividal returns a reference to individual at position n.
|
||||
func (p *Population) GetIndividual(n uint) *PopulationIndividual { return &PopulationIndividual{} }
|
||||
func (p *Population) GetBestIdx() int { return 0 }
|
||||
func (p *Population) GetWorstIdx() int { return 0 }
|
||||
func (p *Population) SetX(n int, nuX DecisionVector) {}
|
||||
func (p *Population) SetV(n int, nuV DecisionVector) {}
|
||||
|
||||
// Init initialises all individuals.
|
||||
func (p *Population) Init() {}
|
||||
|
||||
// Reinit reinitialises all individuals.
|
||||
func (p *Population) Reinit() {}
|
||||
|
||||
// ReinitN reinitialises the individual at position n.
|
||||
func (p *Population) ReinitN(n uint) {}
|
||||
func (p *Population) Clear() {}
|
||||
|
||||
// meanVelocity computes the mean current velocity of all individuals in the population.
|
||||
func (p *Population) MeanVelocity() float64 { return 0.0 }
|
||||
|
||||
// newPopulation returns a pointer to a new, uninitialised population.
|
||||
func newPopulation(benchProblem string, np int) *Population {
|
||||
p := &Population{}
|
||||
|
||||
p.Problem = benchProblem
|
||||
|
||||
// pre-alloc.
|
||||
p.Population = make([]PopulationIndividual, 0, np)
|
||||
|
||||
return p
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
// Copyright 2022 wanderer <a_mirre at utb dot cz>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package algo
|
||||
|
||||
// Evolve runs an evolution algorithm on population (WIP).
|
||||
func Evolve(population any) any {
|
||||
return population
|
||||
}
|
Loading…
Reference in New Issue
Block a user