math-optim/stats/table.go
surtur 13fd0b3bff
All checks were successful
continuous-integration/drone/push Build is passing
go(stats/table): let the printing func just print
...and handle constructing the actual table in a separate func.
also, add more tests.
2022-06-27 21:56:44 +02:00

113 lines
2.6 KiB
Go

// Copyright 2022 wanderer <a_mirre at utb dot cz>
// SPDX-License-Identifier: GPL-3.0-or-later
package stats
import (
"fmt"
"os"
"gonum.org/v1/gonum/floats"
"gonum.org/v1/gonum/stat"
)
// statsRow represents the header in the table.
type statsHdr struct {
Algo string
BenchFuncName string
Dimens int
Generations int
Iterations int
}
// statsRow represents a single row in the table.
type statsRow struct {
Min float64
Max float64
Mean float64
Median float64
StdDev float64
}
// PrintStatisticTable prints to console computed statistics for current algo.
func PrintStatisticTable(algoStats [][]Stats) {
fmt.Fprintln(os.Stderr, "printing statistic table data (min, max, mean, median, stddev)")
for _, singleFunc := range algoStats {
fmt.Fprintln(os.Stderr, statsSingleFunc(singleFunc))
}
}
// statsSingleFunc computes statistics out of results of a single bench func
// and returns the statistic table as a []interface{} because it contains
// multiple table headers and rows. perhaps a table struct could be returned in
// the future.
func statsSingleFunc(singleFuncStats []Stats) []interface{} {
var (
// hdr is the table header as determined based on the data being dealt with.
hdr statsHdr
// row contains the data of the statistic properties being tracked.
row statsRow
)
// out contains the constructed table and is returned at the end of
// this func.
out := make([]interface{}, 0)
for _, s := range singleFuncStats {
for _, dim := range s.BenchFuncStats {
hdr = makeTableHdr(
s.Algo,
s.BenchFuncStats[0].BenchName,
s.Dimens,
s.Generations,
s.Iterations,
)
out = append(out, "\n", hdr, "\n")
// collect the best.
var best []float64
for _, iter := range dim.Solution {
last := s.Generations - 1
best = append(best, iter.Results[last])
}
row.Min = floats.Min(best)
row.Max = floats.Max(best)
row.Mean = stat.Mean(best, nil)
row.Median = stat.Mean(best, nil)
row.StdDev = stat.StdDev(best, nil)
out = append(out, row)
}
}
out = append(out, "\n")
return out
}
// makeTableHdr fills the table header with passed information.
// TODO(me): add checks to assert only valid inputs are passed in.
func makeTableHdr(
algo, benchFuncName string,
dimens, generations, iterations int,
) statsHdr {
hdr := newStatsHdr()
hdr.Algo = algo
hdr.BenchFuncName = benchFuncName
hdr.Dimens = dimens
hdr.Generations = generations
hdr.Iterations = iterations
return *hdr
}
// newStatsHdr returns a pointer to a newly created statsHdr instance.
func newStatsHdr() *statsHdr {
return &statsHdr{}
}