From 44c6a26f9d00618efad13be204340e7d594b9d12 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Mon, 22 Nov 2021 21:34:55 -0800 Subject: [PATCH] Minify program after hitting score --- grow/definition.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++ grow/mutate.go | 3 +-- vm/state.go | 17 ++++++++------- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/grow/definition.go b/grow/definition.go index 88a0998..543c1de 100644 --- a/grow/definition.go +++ b/grow/definition.go @@ -65,6 +65,19 @@ func (def *Definition) Grow(statusChan chan<- Status) (*vm.Program, error) { } if status.BestScore == status.TargetScore { + err = def.minifyProgram(prog) + if err != nil { + if statusChan != nil { + close(statusChan) + } + + return nil, err + } + + if statusChan != nil { + statusChan <- status + } + if statusChan != nil { close(statusChan) } @@ -106,3 +119,42 @@ func (def *Definition) sumOuts() uint64 { return sum } + +func (def *Definition) minifyProgram(prog *vm.Program) error { + for f := 0; f < len(prog.Functions); f++ { + err := def.minifyFunction(prog, f) + if err != nil { + return err + } + } + + return nil +} + +func (def *Definition) minifyFunction(prog *vm.Program, f int) error { + baseScore, err := def.score(prog) + if err != nil { + return err + } + + for loop := true; loop; { + loop = false + + for i := 0; i < len(prog.Functions[f].Instructions); i++ { + origInstructions := prog.Functions[f].Instructions + tmp := make([]*vm.Instruction, len(prog.Functions[f].Instructions)) + copy(tmp, prog.Functions[f].Instructions) + prog.Functions[f].Instructions = append(tmp[:i], tmp[i+1:]...) + + newScore, err := def.score(prog) + if err == nil && newScore >= baseScore { + loop = true + break + } else { + prog.Functions[f].Instructions = origInstructions + } + } + } + + return nil +} diff --git a/grow/mutate.go b/grow/mutate.go index ebde4f1..0111383 100644 --- a/grow/mutate.go +++ b/grow/mutate.go @@ -1,6 +1,5 @@ package grow -import "math" import "math/rand" import "github.com/firestuff/subcoding/gen" @@ -10,7 +9,7 @@ const instructionsPerFunctionMean = 15 const instrucitonsPerFunctionStdDev = 10 func Mutate(prog *vm.Program) { - target := int(math.Max(2, rand.NormFloat64()*instrucitonsPerFunctionStdDev+instructionsPerFunctionMean)) + target := int(rand.NormFloat64()*instrucitonsPerFunctionStdDev+instructionsPerFunctionMean) if len(prog.Functions[0].Instructions) < target { addInstruction(prog, prog.Functions[0]) diff --git a/vm/state.go b/vm/state.go index cd590fd..c0cbeb5 100644 --- a/vm/state.go +++ b/vm/state.go @@ -68,6 +68,15 @@ func (state *State) setHandlers() { } func (state *State) processInstruction() { + for state.functionIndex < 0 || + state.functionIndex >= int64(len(state.program.Functions)) || + state.instructionIndex < 0 || + state.instructionIndex >= int64(len(state.function().Instructions)) { + + state.ret() + return + } + fnc := state.function() instr := fnc.Instructions[state.instructionIndex] state.instructionIndex += 1 @@ -77,14 +86,6 @@ func (state *State) processInstruction() { if state.program.InstructionLimit > 0 && state.instructionCount > state.program.InstructionLimit { state.setError(fmt.Errorf("Instruction limit (%d) exceeded", state.program.InstructionLimit)) } - - for state.functionIndex < 0 || - state.functionIndex >= int64(len(state.program.Functions)) || - state.instructionIndex < 0 || - state.instructionIndex >= int64(len(state.function().Instructions)) { - - state.ret() - } } func (state *State) readUnsigned(op *Operand) uint64 {