math-optim/algo/randomSearch.go
surtur 8a2d3eb5ee
All checks were successful
continuous-integration/drone/push Build is passing
fix(go): only pass raw dimensions count
2022-06-17 20:26:21 +02:00

122 lines
3.4 KiB
Go

// Copyright 2022 wanderer <a_mirre at utb dot cz>
// SPDX-License-Identifier: GPL-3.0-or-later
package algo
import (
"fmt"
"log"
"os"
"git.dotya.ml/wanderer/math-optim/bench"
"gonum.org/v1/gonum/stat/distuv"
)
func getRandomSearchLogPrefix() string {
return " ***  random search:"
}
func fmtRandomSearchOut(input string) string {
return getRandomSearchLogPrefix() + " " + input
}
func printRandomSearch(input string) {
if _, err := fmt.Fprintln(os.Stderr, fmtRandomSearchOut(input)); err != nil {
fmt.Fprintf(
os.Stdout,
getRandomSearchLogPrefix(),
"error while printing to stderr: %q\n * original message was: %q",
err, input,
)
}
}
func genValsRandomSearch(dimens uint, vals []float64, uniform *distuv.Uniform) {
for i := uint(0); i < dimens; i++ {
// using Uniform.Rand from gonum's stat/distuv package.
// https://pkg.go.dev/gonum.org/v1/gonum/stat/distuv#Uniform.Rand
// boundaries are already set at this point.
vals[i] = uniform.Rand()
}
}
// singleRandomSearch performs a single iteration of the 'RandomSearch' algorithm.
// it takes a couple of arguments:
// * dimens uint: number of dimensions of the objective function
// * f string: name of the bench func to optimise (see bench/functions)
// * min/max float64: the upper/lower limit of the uniform distribution span,
// which is relevant to the objective function.
// nolint
func singleRandomSearch(dimens uint, f string, min, max float64) ([]float64, float64) {
var vals []float64
var res float64
// create a continuous uniform distribution representation within min/max bounds
uniformDist := distuv.Uniform{Min: min, Max: max}
genValsRandomSearch(dimens, vals, &uniformDist)
// result of the benchmarking function computation over vals
switch f {
// Schwefel
case bench.Functions[0]:
res = bench.Schwefel(vals)
// "DeJong1st"
case bench.Functions[1]:
res = bench.DeJong1st(vals)
// "DeJong2nd"
case bench.Functions[2]:
res = bench.DeJong2nd(vals)
}
return vals, res
}
func RandomSearch(fes uint) {
if fes == 0 {
log.Fatalln(" random search: fes set to 0, bailing")
}
var valsSchwefel []Values
var valsDeJong1st []Values
var valsDeJong2nd []Values
var resultsSchwefel Values
var resultsDeJong1st Values
var resultsDeJong2nd Values
// iterations needed to establish a minimal viable statistical baseline
minIters := 30
for _, dimens := range bench.Dimensions {
for j := 0; j < minIters; j++ {
// run Schwefel.
v, r := singleRandomSearch(dimens, "Schwefel", bench.SchwefelParams.Min(), bench.SchwefelParams.Max())
valsSchwefel = append(valsSchwefel, v)
resultsSchwefel = append(resultsSchwefel, r)
// run De Jong 1st.
vDJ1, rDJ1 := singleRandomSearch(dimens, "DeJong1st", bench.DeJong1Params.Min(), bench.DeJong1Params.Max())
valsDeJong1st = append(valsDeJong1st, vDJ1)
resultsDeJong1st = append(resultsDeJong1st, rDJ1)
// run De Jong 2nd.
vDJ2, rDJ2 := singleRandomSearch(dimens, "DeJong2nd", bench.DeJong2Params.Min(), bench.DeJong2Params.Max())
valsDeJong2nd = append(valsDeJong2nd, vDJ2)
resultsDeJong2nd = append(resultsDeJong2nd, rDJ2)
}
}
fmt.Fprintln(os.Stderr, "vals schw:", valsSchwefel)
fmt.Fprintln(os.Stderr, "vals dj1", valsDeJong1st)
fmt.Fprintln(os.Stderr, "vals dj2", valsDeJong2nd)
fmt.Fprintln(os.Stderr, "res schw:", resultsSchwefel)
fmt.Fprintln(os.Stderr, "res dj1", resultsDeJong1st)
fmt.Fprintln(os.Stderr, "res dj2", resultsDeJong2nd)
}