diff --git a/algo/algo.go b/algo/algo.go index 5d993ec..4c296e5 100644 --- a/algo/algo.go +++ b/algo/algo.go @@ -9,8 +9,10 @@ import ( "sort" "sync" + "git.dotya.ml/wanderer/math-optim/algo/cec2020" "git.dotya.ml/wanderer/math-optim/algo/de" "git.dotya.ml/wanderer/math-optim/bench" + c20 "git.dotya.ml/wanderer/math-optim/bench/cec2020" "git.dotya.ml/wanderer/math-optim/report" "git.dotya.ml/wanderer/math-optim/stats" ) @@ -403,6 +405,85 @@ func DojDE(wg *sync.WaitGroup, m *sync.Mutex) { pLsMean = append(pLsMean, pLMean) } + algoName := "Differential Evolution" + + // protect access to shared data. + m.Lock() + report.SavePicsToFile(pLs, pLsMean, algoName) + + stats.SaveTable(algoName, algoStats) + m.Unlock() +} + +func DoCEC2020jDE(wg *sync.WaitGroup, m *sync.Mutex) { + defer wg.Done() + + cec2020.LogPrintln("starting") + + // funcCount is the number of bench functions available and tested. + funcCount := len(c20.Functions) + // stats for the current algo. + algoStats := make([][]stats.Stats, funcCount) + // ch serves as a way to get the actual computed output. + ch := make(chan []stats.Stats, funcCount) + // chAlgoMeans := make(chan *stats.AlgoBenchMean, 1) + chAlgoMeans := make(chan *stats.AlgoBenchMean, funcCount) + + defer close(ch) + defer close(chAlgoMeans) + + // jDE params. + np := 50 + f := 0.5 + cr := 0.9 + + for i := range algoStats { + jDE := cec2020.NewjDE() + + // params: + // Generations, minimum bench iterations, mutation strategy, parameter + // self-adaptation scheme, initial population size, differential + // weight, mutation constant, dimensions, bench name and a + // synchronisation channel. + // + // -1 to disable generation limits, + // n > 0 for minimum bench iterations + // 0..17 to choose a mutation strategy, + // 0..1 to select a parameter self-adaptation scheme, + // np >= 4 as initial population size. + jDE.Init(-1, 30, 0, 0, np, f, cr, c20.Dimensions, c20.FuncNames[i], ch, chAlgoMeans) + + go jDE.Run() + } + + // get results. + for i := range algoStats { + s := <-ch + aM := <-chAlgoMeans + + algoStats[i] = s + + saveAlgoMeans(*aM) + } + + pCh := make(chan report.PicList, funcCount*len(c20.Dimensions)) + pMeanCh := make(chan report.PicList, funcCount*len(c20.Dimensions)) + + for _, algoStat := range algoStats { + go plotAllDims(algoStat, "plot", ".pdf", pCh, pMeanCh) + } + + pLs := []report.PicList{} + pLsMean := []report.PicList{} + + for range algoStats { + pL := <-pCh + pLMean := <-pMeanCh + + pLs = append(pLs, pL) + pLsMean = append(pLsMean, pLMean) + } + algoName := "Self-adapting Differential Evolution" // protect access to shared data. diff --git a/run.go b/run.go index e5ff00b..8747cc5 100644 --- a/run.go +++ b/run.go @@ -23,8 +23,9 @@ var ( // TODO(me): add flag for plot output format: -plotout=(svg,eps,pdf). - // run jDE by default. - jDE = flag.Bool("jde", true, "run Differential Evolution algorithm with parameter self adaptation") + jDE = flag.Bool("jde", false, "run Differential Evolution algorithm with parameter self adaptation") + // run CEC2020 jDE by default. + c2jDE = flag.Bool("c2jde", true, "run CEC2020 version of the Differential Evolution algorithm with parameter self adaptation") ) func run() { @@ -33,7 +34,7 @@ func run() { flag.Parse() if *generate { - if !*jDE && !*sHC && !*rS { + if !*jDE && !*c2jDE && !*sHC && !*rS { log.Println("at least one algo needs to be specified, exiting...") return @@ -43,18 +44,25 @@ func run() { var m sync.Mutex - switch { - case *jDE: + if *jDE { wg.Add(1) go algo.DojDE(&wg, &m) + } - case *rS: + if *c2jDE { + wg.Add(1) + + go algo.DoCEC2020jDE(&wg, &m) + } + + if *rS { wg.Add(1) go algo.DoRandomSearch(&wg, &m) + } - case *sHC: + if *sHC { wg.Add(1) if *n100 { diff --git a/run_test.go b/run_test.go index e9ef263..ba080ff 100644 --- a/run_test.go +++ b/run_test.go @@ -19,7 +19,7 @@ func TestRun(t *testing.T) { t.Errorf("failed to set timeout to %s", timeout) } - if err := flag.Set("jde", "false"); err != nil { + if err := flag.Set("c2jde", "false"); err != nil { t.Errorf("failed to not run jDE: %q", err) }