https://github.com/sile/kurobako-go
A Golang library to help implement kurobako's solvers and problems
https://github.com/sile/kurobako-go
black-box-benchmarking black-box-optimization golang-library
Last synced: about 1 year ago
JSON representation
A Golang library to help implement kurobako's solvers and problems
- Host: GitHub
- URL: https://github.com/sile/kurobako-go
- Owner: sile
- License: mit
- Created: 2019-12-18T16:04:44.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2020-03-19T01:35:01.000Z (about 6 years ago)
- Last Synced: 2025-03-25T07:12:47.407Z (about 1 year ago)
- Topics: black-box-benchmarking, black-box-optimization, golang-library
- Language: Go
- Homepage:
- Size: 89.8 KB
- Stars: 6
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
kurobako-go
===========

[](https://godoc.org/github.com/sile/kurobako-go)
[](https://goreportcard.com/report/github.com/sile/kurobako-go)
[](https://github.com/sile/kurobako-go/actions)
A Golang library to help implement [kurobako]'s solvers and problems.
[kurobako]: https://github.com/sile/kurobako
Usage Examples
--------------
### 1. Define a solver based on random search
```go
// file: random-solver.go
package main
import (
"math"
"math/rand"
"github.com/sile/kurobako-go"
)
type randomSolverFactory struct{}
func (r *randomSolverFactory) Specification() (*kurobako.SolverSpec, error) {
spec := kurobako.NewSolverSpec("Random Search")
return &spec, nil
}
func (r *randomSolverFactory) CreateSolver(seed int64, problem kurobako.ProblemSpec) (kurobako.Solver, error) {
rng := rand.New(rand.NewSource(seed))
return &randomSolver{rng, problem}, nil
}
type randomSolver struct {
rng *rand.Rand
problem kurobako.ProblemSpec
}
func (r *randomSolver) sampleUniform(low float64, high float64) float64 {
return r.rng.Float64()*(high-low) + low
}
func (r *randomSolver) sampleLogUniform(low float64, high float64) float64 {
return math.Exp(r.sampleUniform(math.Log(low), math.Log(high)))
}
func (r *randomSolver) Ask(idg *kurobako.TrialIDGenerator) (kurobako.NextTrial, error) {
var trial kurobako.NextTrial
for _, p := range r.problem.Params {
if p.Distribution == kurobako.Uniform {
value := r.sampleUniform(p.Range.Low(), p.Range.High())
trial.Params = append(trial.Params, &value)
} else {
value := r.sampleLogUniform(p.Range.Low(), p.Range.High())
trial.Params = append(trial.Params, &value)
}
}
trial.TrialID = idg.Generate()
trial.NextStep = r.problem.Steps.Last()
return trial, nil
}
func (r *randomSolver) Tell(trial kurobako.EvaluatedTrial) error {
return nil
}
func main() {
runner := kurobako.NewSolverRunner(&randomSolverFactory{})
if err := runner.Run(); err != nil {
panic(err)
}
}
```
### 2. Define a solver based on [Goptuna]
[Goptuna]: https://github.com/c-bata/goptuna
```go
// file: goptuna-solver.go
package main
import (
"github.com/c-bata/goptuna"
"github.com/c-bata/goptuna/tpe"
"github.com/sile/kurobako-go"
"github.com/sile/kurobako-go/goptuna/solver"
)
func createStudy(seed int64) (*goptuna.Study, error) {
sampler := tpe.NewSampler(tpe.SamplerOptionSeed(seed))
return goptuna.CreateStudy("example-study", goptuna.StudyOptionSampler(sampler))
}
func main() {
factory := solver.NewGoptunaSolverFactory(createStudy)
runner := kurobako.NewSolverRunner(&factory)
if err := runner.Run(); err != nil {
panic(err)
}
}
```
### 3. Define a problem that represents a quadratic function `x**2 + y`
```go
// file: quadratic-problem.go
package main
import (
"github.com/sile/kurobako-go"
)
type quadraticProblemFactory struct {
}
func (r *quadraticProblemFactory) Specification() (*kurobako.ProblemSpec, error) {
spec := kurobako.NewProblemSpec("Quadratic Function")
x := kurobako.NewVar("x")
x.Range = kurobako.ContinuousRange{-10.0, 10.0}.ToRange()
y := kurobako.NewVar("y")
y.Range = kurobako.DiscreteRange{-3, 3}.ToRange()
spec.Params = []kurobako.Var{x, y}
spec.Values = []kurobako.Var{kurobako.NewVar("x**2 + y")}
return &spec, nil
}
func (r *quadraticProblemFactory) CreateProblem(seed int64) (kurobako.Problem, error) {
return &quadraticProblem{}, nil
}
type quadraticProblem struct {
}
func (r *quadraticProblem) CreateEvaluator(params []float64) (kurobako.Evaluator, error) {
x := params[0]
y := params[1]
return &quadraticEvaluator{x, y}, nil
}
type quadraticEvaluator struct {
x float64
y float64
}
func (r *quadraticEvaluator) Evaluate(nextStep uint64) (uint64, []float64, error) {
values := []float64{r.x*r.x + r.y}
return 1, values, nil
}
func main() {
runner := kurobako.NewProblemRunner(&quadraticProblemFactory{})
if err := runner.Run(); err != nil {
panic(err)
}
}
```
### 4. Run a benchmark that uses the above solver and problem
```console
// Define solver and problem.
$ SOLVER1=$(kurobako solver command go run random-solver.go)
$ SOLVER2=$(kurobako solver command go run goptuna-solver.go)
$ PROBLEM=$(kurobako problem command go run quadratic-problem.go)
// Execute benchmark.
$ kurobako studies --solvers $SOLVER1 $SOLVER2 --problems $PROBLEM | kurobako run > result.json
// Generate Markdown format report and visualization image.
$ cat result.json | kurobako report
$ cat result.json | kurobako plot curve
```