diff --git a/algo/algo.go b/algo/algo.go index 3351272..966a972 100644 --- a/algo/algo.go +++ b/algo/algo.go @@ -4,6 +4,8 @@ package algo import ( + "fmt" + "log" "sort" "sync" @@ -22,6 +24,17 @@ var meanStats = &stats.MeanStats{} var comparisonOfMeansPicList = &report.PicList{Algo: "Comparison of Means"} +// getComparisonOfMeansPics returns a sorted slice of pics field from the +// package global 'algoMeanPics'. +func getComparisonOfMeansPics() []report.Pic { + // note: sorting by filename (dimens value being 0-padded at generation + // time), relying on this as a hack so that we didn't have to implement our + // own natural-order sorter. + sort.Sort(comparisonOfMeansPicList.Pics) + + return comparisonOfMeansPicList.Pics +} + // GetMeanStats returns a pointer of type stats.MeanStats to a sorted package // global 'meanStats'. func GetMeanStats() *stats.MeanStats { @@ -30,6 +43,93 @@ func GetMeanStats() *stats.MeanStats { return meanStats } +func PrepComparisonOfMeans(wg *sync.WaitGroup) (*report.PicList, int) { + pL := report.NewPicList() + meanStats := GetMeanStats() + algos := make([]string, 0) + + // learn how many algos were processed based on the data. + for _, v := range meanStats.AlgoMeans { + // if algos is empty just add the value directly, else determine if + // it's already been added or not. + if len(algos) > 0 { + alreadyadded := false + + for _, algoName := range algos { + if algoName == v.Algo { + // early bail if already added. + alreadyadded = true + break + } + } + + if !alreadyadded { + algos = append(algos, v.Algo) + } + } else { + algos = append(algos, v.Algo) + } + } + + // construct title consisting of names of all involved algorithms. + for _, v := range algos { + switch pL.Algo { + case "": + pL.Algo = v + default: + pL.Algo += " vs " + v + } + } + + log.Println(`generating "Comparison of Means" plots`) + + algoCount := len(algos) + dimLen := len(bench.Dimensions) + benchCount := len(bench.Functions) + + // note: this is a wee bit ugly. + for d := 0; d < dimLen; d++ { + for i := 0; i < benchCount; i++ { + dimXAlgoMeanVals := make([]stats.AlgoMeanVals, 0, algoCount) + + for j := 0; j < algoCount*benchCount; j += benchCount { + neighbInfo := "" + + // only add info about neighbours if it was changed (from + // the default of -1). + if n := meanStats.AlgoMeans[d+j].BenchMeans[i].Neighbours; n != -1 { + neighbInfo = fmt.Sprintf(" (N: %d)", n) + } + + ms := &stats.AlgoMeanVals{ + Title: meanStats.AlgoMeans[d+j].Algo + neighbInfo, + MeanVals: meanStats.AlgoMeans[d+j].BenchMeans[i].MeanVals, + } + dimXAlgoMeanVals = append(dimXAlgoMeanVals, *ms) + } + + dimens := meanStats.AlgoMeans[d].BenchMeans[i].Dimens + iterations := meanStats.AlgoMeans[d].BenchMeans[i].Iterations + bench := meanStats.AlgoMeans[d].BenchMeans[i].Bench + + wg.Add(1) + + // construct plots concurrently. + go PlotMeanValsMulti( + wg, dimens, iterations, bench, "plot-", ".svg", + dimXAlgoMeanVals..., + ) + } + } + + // wait for all the plotting to conclude. + wg.Wait() + + pL.Pics = getComparisonOfMeansPics() + + return pL, benchCount +} + // DoRandomSearch executes a search using the 'Random search' method. func DoRandomSearch(wg *sync.WaitGroup, m *sync.Mutex) { defer wg.Done()