math-optim/algo/randomSearch.go
surtur cbf47031f9
All checks were successful
continuous-integration/drone/push Build is passing
go: implement RandomSearch wip2
* perform RandomSearch with each of the benchmarking functions for a
  prescribed number of iterations

left to do:
* saving the solution
* parsing the solution to a table
* parsing the solution to generate graphs

* follow-up of b3787da640
2022-06-17 22:33:37 +02:00

184 lines
4.6 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.
func singleRandomSearch(dimens uint, f string, min, max float64) ([]float64, float64) {
vals := make([]float64, dimens)
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
}
// TODO(me): split this up
// nolint: gocognit
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
var bestResultsSchwefel []float64
var bestResultsDeJong1st []float64
var bestResultsDeJong2nd []float64
// iterations needed to establish a minimal viable statistical baseline
minIters := 30
for _, dimens := range bench.Dimensions {
for i := 0; i < minIters; i++ {
var bestResult float64
for j := 0; j < int(fes); j++ {
// run Schwefel.
v, r := singleRandomSearch(
dimens,
bench.Functions[0],
bench.SchwefelParams.Min(),
bench.SchwefelParams.Max(),
)
valsSchwefel = append(valsSchwefel, v)
resultsSchwefel = append(resultsSchwefel, r)
switch j {
// first iteration
case 0:
bestResult = r
default:
// any other than the first iteration and a better solution
if r < bestResult {
bestResult = r
}
}
bestResultsSchwefel = append(bestResultsSchwefel, bestResult)
}
for k := 0; k < int(fes); k++ {
// run De Jong 1st.
v, r := singleRandomSearch(
dimens,
bench.Functions[1],
bench.DeJong1Params.Min(),
bench.DeJong1Params.Max(),
)
valsDeJong1st = append(valsDeJong1st, v)
resultsDeJong1st = append(resultsDeJong1st, r)
// first iteration or better solution
if k == 0 || r < bestResult {
bestResult = r
}
bestResultsDeJong1st = append(bestResultsDeJong1st, bestResult)
}
for l := 0; l < int(fes); l++ {
// run De Jong 2nd.
v, r := singleRandomSearch(
dimens,
bench.Functions[2],
bench.DeJong2Params.Min(),
bench.DeJong2Params.Max(),
)
valsDeJong2nd = append(valsDeJong2nd, v)
resultsDeJong2nd = append(resultsDeJong2nd, r)
// first iteration or better solution
if l == 0 || r < bestResult {
bestResult = r
}
bestResultsDeJong2nd = append(bestResultsDeJong2nd, bestResult)
}
}
}
fmt.Fprintln(os.Stderr, "vals schw len", len(valsSchwefel))
fmt.Fprintln(os.Stderr, "vals dj1 len", len(valsDeJong1st))
fmt.Fprintln(os.Stderr, "vals dj2 len", len(valsDeJong2nd))
fmt.Fprintln(os.Stderr, "res schw len", len(resultsSchwefel))
fmt.Fprintln(os.Stderr, "res dj1 len", len(resultsDeJong1st))
fmt.Fprintln(os.Stderr, "res dj2 len", len(resultsDeJong2nd))
fmt.Fprintln(os.Stderr, "best res schw len", len(bestResultsSchwefel))
fmt.Fprintln(os.Stderr, "best res dj1 len", len(bestResultsDeJong1st))
fmt.Fprintln(os.Stderr, "best res dj2 len", len(bestResultsDeJong2nd))
}