diff --git a/algo/algo.go b/algo/algo.go index 0b7ec79..fb339bc 100644 --- a/algo/algo.go +++ b/algo/algo.go @@ -14,8 +14,13 @@ import ( // mu protects access to meanStats. var mu sync.Mutex +// mCoMPL protexts access to comparisonOfMeansPicList. +var mCoMPL sync.Mutex + var meanStats = &stats.MeanStats{} +var comparisonOfMeansPicList = &report.PicList{Algo: "Comparison of Means"} + // 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 4aaf45a..eabbb99 100644 --- a/algo/plot.go +++ b/algo/plot.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "strings" + "sync" "time" "git.dotya.ml/wanderer/math-optim/report" @@ -26,6 +27,127 @@ const ( xAxisLabel = "Generations" ) +// PlotMeanValsMulti creates plots for every member of 'stats.AlgoMeanVals' it +// is handed and saves them as 'result.Pic's results into a package-global +// slice. +func PlotMeanValsMulti( + w *sync.WaitGroup, + dimens, iterations int, + bench, fPrefix, fExt string, + algoMeanVals ...stats.AlgoMeanVals, +) { + defer w.Done() + + // track time. + start := time.Now() + + pWidth := 13 * vg.Centimeter + pHeight := 13 * vg.Centimeter + + plotter.DefaultFont.Typeface = preferredFont + plotter.DefaultLineStyle.Width = vg.Points(2.0) + + p := plot.New() + pic := report.NewPic() + + p.Title.Text = fmt.Sprintf( + "Comparison of Means (%dI) -\n%s (%dD)", + iterations, bench, dimens, + ) + + p.X.Label.Text = xAxisLabel + p.X.Label.TextStyle.Font.Variant = preferredFont + p.X.Label.TextStyle.Font.Weight = 1 // Medium + p.X.Tick.Label.Font.Variant = preferredFont + p.Y.Label.Text = yAxisLabel + p.Y.Label.TextStyle.Font.Variant = preferredFont + p.Y.Label.TextStyle.Font.Weight = 1 // Medium + p.Y.Tick.Label.Font.Variant = preferredFont + + p.Title.TextStyle.Font.Size = 14.5 + p.Title.TextStyle.Font.Variant = titlePreferredFont + p.Title.TextStyle.Font.Weight = 2 // SemiBold + p.Title.Padding = 3 * vg.Millimeter + + p.Legend.TextStyle.Font.Variant = preferredFont + p.Legend.TextStyle.Font.Size = 10 + p.Legend.Top = true + p.Legend.Padding = 2 * vg.Millimeter + + lines := make([]interface{}, 0) + + for _, v := range algoMeanVals { + // mark the end of the X axis with the greatest of len(v) + if greatest := float64(len(v.MeanVals)); greatest > p.X.Max { + p.X.Max = greatest + } + + if min := floats.Min(v.MeanVals); min < p.Y.Min { + p.Y.Min = min + } + + if max := floats.Max(v.MeanVals); max > p.Y.Max { + p.Y.Max = max + } + + pts := make(plotter.XYs, len(v.MeanVals)) + + // fill the plotter with datapoints. + for k, res := range v.MeanVals { + pts[k].X = float64(k) + pts[k].Y = res + } + + lines = append(lines, v.Title, pts) + } + + err := plotutil.AddLines( + p, + lines..., + ) + if err != nil { + log.Panic(err) + } + + filename := util.SanitiseFName( + fmt.Sprintf("%s%scomparison-of-means-%dI-%s-%02dD", + report.GetPicsDir(), + fPrefix, + iterations, + bench, + dimens, + ), + ) + + // set pic file path and caption. + pic.FilePath = filename + pic.Caption = strings.ReplaceAll( + fmt.Sprintf("Comparison of Means (%dI) - %s (%dD)", + iterations, bench, dimens, + ), + " ", "~") + pic.Bench = bench + + elapsed := time.Since(start) + info := fmt.Sprintf("saving img to file: %s%s [generated in %s]", + filename, fExt, elapsed, + ) + log.Println(info) + + // Save the plot to a file using the above-constructed 'filename'. + if err := p.Save( + pWidth, + pHeight, + filename+fExt, + ); err != nil { + panic(err) + } + + mCoMPL.Lock() + comparisonOfMeansPicList.Pics = append(comparisonOfMeansPicList.Pics, *pic) + mCoMPL.Unlock() +} + func plotMeanVals(meanVals []float64, title string, fes int) *plot.Plot { plotter.DefaultFont.Typeface = preferredFont plotter.DefaultLineStyle.Width = vg.Points(2.0) diff --git a/stats/stats.go b/stats/stats.go index 5adde67..a83ea87 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -51,6 +51,13 @@ type MeanStats struct { AlgoMeans []AlgoBenchMean } +// AlgoMeanVals holds computed mean values of an Algo. +type AlgoMeanVals struct { + Title string + // MeanVals of a particular bench func to compare. + MeanVals []float64 +} + type Stats struct { Algo string Dimens int