From 2bf3a4a767ec8d39371f2bb11605aeac889769fc Mon Sep 17 00:00:00 2001 From: surtur Date: Tue, 19 Jul 2022 21:56:49 +0200 Subject: [PATCH] go: collect and process mean vals * 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. --- algo/algo.go | 5 +++++ algo/plot.go | 7 ++----- algo/randomSearch.go | 23 +++++++++++++++++++++++ algo/stochasticHillClimbing.go | 22 ++++++++++++++++++++++ stats/stats.go | 28 ++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 5 deletions(-) diff --git a/algo/algo.go b/algo/algo.go index 7a9bbbc..9fa247c 100644 --- a/algo/algo.go +++ b/algo/algo.go @@ -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() diff --git a/algo/plot.go b/algo/plot.go index 20b4e79..5ed19d9 100644 --- a/algo/plot.go +++ b/algo/plot.go @@ -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 + diff --git a/algo/randomSearch.go b/algo/randomSearch.go index 82a2a8e..eca2e78 100644 --- a/algo/randomSearch.go +++ b/algo/randomSearch.go @@ -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 } diff --git a/algo/stochasticHillClimbing.go b/algo/stochasticHillClimbing.go index 82c0cba..8b82802 100644 --- a/algo/stochasticHillClimbing.go +++ b/algo/stochasticHillClimbing.go @@ -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 } diff --git a/stats/stats.go b/stats/stats.go index e28e90c..ee57c18 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -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 {