From a5e44a7e070595d594b8c968062e9226e6cac2cf Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Mon, 22 Nov 2021 20:33:22 -0800 Subject: [PATCH] Switch to add/remove instruction mutation --- gen/instruction.go | 6 +++--- gen/opcode.go | 2 +- gen/operand.go | 2 +- gen/program.go | 19 ------------------- grow/definition.go | 12 ++++++++++-- grow/defs/mul_five.yaml | 2 +- grow/mutate.go | 36 ++++++++++++++++++++++++++++++++++++ test/gen_test.go | 9 --------- 8 files changed, 52 insertions(+), 36 deletions(-) delete mode 100644 gen/program.go create mode 100644 grow/mutate.go delete mode 100644 test/gen_test.go diff --git a/gen/instruction.go b/gen/instruction.go index a98004d..58cf937 100644 --- a/gen/instruction.go +++ b/gen/instruction.go @@ -2,13 +2,13 @@ package gen import "github.com/firestuff/subcoding/vm" -func randInstruction(prog *vm.Program) *vm.Instruction { +func RandInstruction(prog *vm.Program) *vm.Instruction { instr := &vm.Instruction{ - OpCode: randOpCode(), + OpCode: RandOpCode(), } for i, t := range vm.OperandsByOpCode[instr.OpCode] { - instr.Operands[i] = randOperand(prog, t) + instr.Operands[i] = RandOperand(prog, t) } return instr diff --git a/gen/opcode.go b/gen/opcode.go index c82e2c7..95588aa 100644 --- a/gen/opcode.go +++ b/gen/opcode.go @@ -48,7 +48,7 @@ var opCodes = []vm.OpCodeType{ vm.OpSqrt, } -func randOpCode() vm.OpCodeType { +func RandOpCode() vm.OpCodeType { // Uniform distribution return opCodes[rand.Intn(len(opCodes))] } diff --git a/gen/operand.go b/gen/operand.go index 0599242..fbdff1e 100644 --- a/gen/operand.go +++ b/gen/operand.go @@ -4,7 +4,7 @@ import "math/rand" import "github.com/firestuff/subcoding/vm" -func randOperand(prog *vm.Program, t vm.OperandNumericType) *vm.Operand { +func RandOperand(prog *vm.Program, t vm.OperandNumericType) *vm.Operand { for { op := &vm.Operand{ Type: randOperandType(), diff --git a/gen/program.go b/gen/program.go deleted file mode 100644 index 3e3e8dd..0000000 --- a/gen/program.go +++ /dev/null @@ -1,19 +0,0 @@ -package gen - -import "github.com/firestuff/subcoding/vm" - -func RandProgram(globalMemorySize, functionMemorySize, instructionLimit uint64) *vm.Program { - prog := &vm.Program{ - GlobalMemorySize: globalMemorySize, - FunctionMemorySize: functionMemorySize, - InstructionLimit: instructionLimit, - } - - prog.Functions = append(prog.Functions, &vm.Function{ - Instructions: []*vm.Instruction{ - randInstruction(prog), - }, - }) - - return prog -} diff --git a/grow/definition.go b/grow/definition.go index 405648f..996e8b0 100644 --- a/grow/definition.go +++ b/grow/definition.go @@ -4,7 +4,6 @@ import "io" import "gopkg.in/yaml.v2" -import "github.com/firestuff/subcoding/gen" import "github.com/firestuff/subcoding/vm" type Definition struct { @@ -37,10 +36,19 @@ func (def *Definition) Grow(statusChan chan<- Status) (*vm.Program, error) { statusChan <- status } + prog := &vm.Program{ + GlobalMemorySize: def.GlobalMemorySize, + FunctionMemorySize: def.FunctionMemorySize, + InstructionLimit: def.InstructionLimit, + Functions: []*vm.Function{ + &vm.Function{}, + }, + } + for { status.Attempts++ - prog := gen.RandProgram(def.GlobalMemorySize, def.FunctionMemorySize, def.InstructionLimit) + Mutate(prog) score, err := def.score(prog) if err != nil { diff --git a/grow/defs/mul_five.yaml b/grow/defs/mul_five.yaml index bb97b0d..f57a77d 100644 --- a/grow/defs/mul_five.yaml +++ b/grow/defs/mul_five.yaml @@ -1,6 +1,6 @@ global_memory_size: 1 function_memory_size: 1 -instruction_limit: 2 +instruction_limit: 10 samples: - in: [0] out: [0] diff --git a/grow/mutate.go b/grow/mutate.go new file mode 100644 index 0000000..2a627c8 --- /dev/null +++ b/grow/mutate.go @@ -0,0 +1,36 @@ +package grow + +import "math" +import "math/rand" + +import "github.com/firestuff/subcoding/gen" +import "github.com/firestuff/subcoding/vm" + +func Mutate(prog *vm.Program) { + target := int(math.Max(2, rand.NormFloat64()*10+15)) + + if len(prog.Functions[0].Instructions) < target { + addInstruction(prog, prog.Functions[0]) + } else { + removeInstruction(prog, prog.Functions[0]) + } +} + +func addInstruction(prog *vm.Program, fnc *vm.Function) { + if len(fnc.Instructions) == 0 { + fnc.Instructions = append(fnc.Instructions, gen.RandInstruction(prog)) + } else { + i := rand.Intn(len(fnc.Instructions)) + fnc.Instructions = append(fnc.Instructions[:i+1], fnc.Instructions[i:]...) + fnc.Instructions[i] = gen.RandInstruction(prog) + } +} + +func removeInstruction(prog *vm.Program, fnc *vm.Function) { + if len(fnc.Instructions) == 0 { + return + } + + i := rand.Intn(len(fnc.Instructions)) + fnc.Instructions = append(fnc.Instructions[:i], fnc.Instructions[i+1:]...) +} diff --git a/test/gen_test.go b/test/gen_test.go deleted file mode 100644 index 8f54e68..0000000 --- a/test/gen_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package test - -import "testing" - -import "github.com/firestuff/subcoding/gen" - -func TestRandProgram(t *testing.T) { - gen.RandProgram(4, 4, 0) -}