go: collect and process mean vals
All checks were successful
continuous-integration/drone/push Build is passing

* compute and save mean values of x (e.g. 30) bench runs
* safely save mean vals for all bench-dimens combinations to AlgoMeans
  from goroutines (use mutex to protect shared access)
* rework algo/plot.go to use already computed mean values.

todo: plot mean vals of all algorithms (per benchmark) in a single pic.
This commit is contained in:
surtur 2022-07-19 21:56:49 +02:00
parent c433b11eea
commit 2bf3a4a767
Signed by: wanderer
GPG Key ID: 19CE1EC1D9E0486D
5 changed files with 80 additions and 5 deletions

@ -15,6 +15,11 @@ import (
// methods over it.
type Values []float64
// mu protects access to meanStats.
var mu sync.Mutex
var meanStats = &stats.MeanStats{}
// DoRandomSearch executes a search using the 'Random search' method.
func DoRandomSearch(wg *sync.WaitGroup, m *sync.Mutex) {
defer wg.Done()

@ -21,7 +21,7 @@ import (
const preferredFontStyle = "Mono"
func plotMeanVals(vals []stats.BenchRound, title string, fes int) *plot.Plot {
func plotMeanVals(meanVals []float64, title string, fes int) *plot.Plot {
plotter.DefaultFont.Typeface = preferredFontStyle
plotter.DefaultLineStyle.Width = vg.Points(2.0)
@ -43,9 +43,6 @@ func plotMeanVals(vals []stats.BenchRound, title string, fes int) *plot.Plot {
p.Title.TextStyle.Font.Weight = 2 // SemiBold
p.Title.Padding = 3 * vg.Millimeter
// get mean vals.
meanVals := stats.GetMeanVals(vals, fes)
// mark the end of the X axis with len(meanVals).
p.X.Max = float64(len(meanVals))
p.Y.Min = floats.Min(meanVals)
@ -190,7 +187,7 @@ func plotAllDims(algoStats []stats.Stats, fPrefix, fExt string, ch chan report.P
picMean.FilePath = filenameMean
// get the *mean* plot.
pMean := plotMeanVals(dim.BenchResults, meanTitle, s.Generations)
pMean := plotMeanVals(dim.MeanVals, meanTitle, s.Generations)
elapsed := time.Since(start)
info := "saving img to file: " + filename + "(-Mean)" + fExt +

@ -99,6 +99,8 @@ func RandomSearchNG(maxFES, benchMinIters int, theD []int, benchFunc string, ch
)),
}
rsMeans := &stats.AlgoMean{Algo: "Random Search"}
// iterate over whatever was passed to us with theD - dimens slice.
for _, dimens := range localD {
randomSearchStatDimX := &stats.Stats{
@ -109,6 +111,14 @@ func RandomSearchNG(maxFES, benchMinIters int, theD []int, benchFunc string, ch
}
funcStats := &stats.FuncStats{BenchName: benchFunc}
benchFuncParams := bench.FunctionParams[benchFunc]
dimXMean := &stats.Mean{
Bench: benchFunc,
Dimens: dimens,
Iterations: minIters,
Generations: fes,
// not applicable to Random Search...
Neighbours: -1,
}
// set min/max bounds.
uniformDist.Min = benchFuncParams.Min()
@ -156,6 +166,11 @@ func RandomSearchNG(maxFES, benchMinIters int, theD []int, benchFunc string, ch
}
}
// get mean vals.
dimXMean.MeanVals = stats.GetMeanVals(funcStats.BenchResults, fes)
// save to funcStats, too.
funcStats.MeanVals = dimXMean.MeanVals
// save cumulative results of 'minIters' runs.
randomSearchStatDimX.BenchFuncStats = append(
randomSearchStatDimX.BenchFuncStats,
@ -164,7 +179,15 @@ func RandomSearchNG(maxFES, benchMinIters int, theD []int, benchFunc string, ch
// save stats for each dimension to a stats slice.
randomSearchStats = append(randomSearchStats, *randomSearchStatDimX)
// save to AlgoMeans
rsMeans.Means = append(rsMeans.Means, *dimXMean)
}
// export AlgoMeans.
mu.Lock()
meanStats.AlgoMeans = append(meanStats.AlgoMeans, *rsMeans)
mu.Unlock()
ch <- randomSearchStats
}

@ -186,6 +186,8 @@ func HillClimb(maxFES, benchMinIters int, theD []int, benchFunc string, ch chan
localD = theD
minIters = benchMinIters
shcMeans := &stats.AlgoMean{Algo: "Stochastic Hill Climbing"}
for _, dimens := range localD {
stochasticHCStatDimX := &stats.Stats{
Algo: "Stochastic Hill Climbing",
@ -198,6 +200,13 @@ func HillClimb(maxFES, benchMinIters int, theD []int, benchFunc string, ch chan
}
funcStats := &stats.FuncStats{BenchName: benchFunc}
benchFuncParams := bench.FunctionParams[benchFunc]
dimXMean := &stats.Mean{
Bench: benchFunc,
Dimens: dimens,
Iterations: minIters,
Generations: fesPerIter,
Neighbours: bench.Neighbourhood,
}
uniDist := distuv.Uniform{
Min: benchFuncParams.Min(),
Max: benchFuncParams.Max(),
@ -276,13 +285,26 @@ func HillClimb(maxFES, benchMinIters int, theD []int, benchFunc string, ch chan
benchFunc + "\" for " + fmt.Sprint(dimens) + "D took " + fmt.Sprint(elapsed),
)
// get mean vals.
dimXMean.MeanVals = stats.GetMeanVals(funcStats.BenchResults, fesPerIter)
// save to funcStats, too.
funcStats.MeanVals = dimXMean.MeanVals
stochasticHCStatDimX.BenchFuncStats = append(
stochasticHCStatDimX.BenchFuncStats,
*funcStats,
)
stochasticHCStats = append(stochasticHCStats, *stochasticHCStatDimX)
// save to AlgoMeans.
shcMeans.Means = append(shcMeans.Means, *dimXMean)
}
// export AlgoMeans.
mu.Lock()
meanStats.AlgoMeans = append(meanStats.AlgoMeans, *shcMeans)
mu.Unlock()
ch <- stochasticHCStats
}

@ -21,6 +21,34 @@ type BenchRound struct {
type FuncStats struct {
BenchName string
BenchResults []BenchRound
// MeanVals holds the mean value for each step of the iteration.
MeanVals []float64
}
// Mean structure holds mean vals and metadata of a specified
// bench-algo-settings combination.
type Mean struct {
Bench string
Dimens int
Iterations int
Generations int
// Neighbours param is used in Hill Climbing type algos, set to -1 if not
// applicable.
Neighbours int
// MeanVals holds the mean value for each step of the iteration.
MeanVals []float64
}
// AlgoMean holds Mean structs of different benchmarks but the same algorithm.
type AlgoMean struct {
Algo string
Means []Mean
}
// MeanStats aggregates AlgoMean structs of different algos.
type MeanStats struct {
AlgoMeans []AlgoMean
}
type Stats struct {