diff --git a/grow/definition.go b/grow/definition.go index deeaa3d..1efa7d6 100644 --- a/grow/definition.go +++ b/grow/definition.go @@ -4,6 +4,9 @@ import "io" import "gopkg.in/yaml.v2" +import "github.com/firestuff/subcoding/gen" +import "github.com/firestuff/subcoding/vm" + type Definition struct { GlobalMemorySize uint64 `yaml:"global_memory_size"` FunctionMemorySize uint64 `yaml:"function_memory_size"` @@ -24,3 +27,61 @@ func NewDefinition(r io.Reader) (*Definition, error) { return def, nil } + +func (def *Definition) Grow(statusChan chan<- Status) (*vm.Program, error) { + status := Status{ + TargetScore: uint64(len(def.Samples)), + } + + if statusChan != nil { + statusChan <- status + } + + // TODO: Score should be number of output criteria, not number of Samples + for { + status.Attempts++ + + prog := gen.RandProgram(def.GlobalMemorySize, def.FunctionMemorySize, def.InstructionLimit) + + score, err := def.Score(prog) + if err != nil { + close(statusChan) + return nil, err + } + + if score > status.BestScore { + status.BestScore = score + status.BestProgram = prog + + if statusChan != nil { + statusChan <- status + } + + if status.BestScore == status.TargetScore { + close(statusChan) + return prog, nil + } + } + } +} + +func (def *Definition) Score(prog *vm.Program) (uint64, error) { + score := uint64(0) + + for _, sample := range def.Samples { + state, err := vm.NewState(prog) + if err != nil { + return 0, err + } + + sample.SetInputs(state) + + state.Execute() // ignore error + + if sample.OutputsMatch(state) { + score += 1 + } + } + + return score, nil +} diff --git a/grow/grow.go b/grow/grow.go deleted file mode 100644 index 1d93bdd..0000000 --- a/grow/grow.go +++ /dev/null @@ -1,62 +0,0 @@ -package grow - -import "github.com/firestuff/subcoding/gen" -import "github.com/firestuff/subcoding/vm" - -func (def *Definition) Grow(statusChan chan<- Status) (*vm.Program, error) { - status := Status{ - TargetScore: uint64(len(def.Samples)), - } - - if statusChan != nil { - statusChan <- status - } - - // TODO: Score should be number of output criteria, not number of Samples - for { - status.Attempts++ - - prog := gen.RandProgram(def.GlobalMemorySize, def.FunctionMemorySize, def.InstructionLimit) - - score, err := def.Score(prog) - if err != nil { - close(statusChan) - return nil, err - } - - if score > status.BestScore { - status.BestScore = score - status.BestProgram = prog - - if statusChan != nil { - statusChan <- status - } - - if status.BestScore == status.TargetScore { - close(statusChan) - return prog, nil - } - } - } -} - -func (def *Definition) Score(prog *vm.Program) (uint64, error) { - score := uint64(0) - - for _, sample := range def.Samples { - state, err := vm.NewState(prog) - if err != nil { - return 0, err - } - - sample.SetInputs(state) - - state.Execute() // ignore error - - if sample.OutputsMatch(state) { - score += 1 - } - } - - return score, nil -}