From d4907eb204bb86f9a83d7c805f3bd58320f9278d Mon Sep 17 00:00:00 2001 From: Forest Belton <65484+forestbelton@users.noreply.github.com> Date: Tue, 3 Aug 2021 19:28:18 -0400 Subject: [PATCH] Implement operand mutation --- ex.py | 21 +-------------------- gbso/cpu/insn.py | 3 +++ gbso/program/mutate.py | 27 +++++++++++++++++++-------- tests/program/test_mutate.py | 3 +++ 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/ex.py b/ex.py index d2d4476..66da56d 100644 --- a/ex.py +++ b/ex.py @@ -1,16 +1,8 @@ from gbso.cpu.insn import * from gbso.cpu.regs import R8, R16 -from gbso.optimize import ( - DEFAULT_PROB_INSN, - DEFAULT_PROB_INSN_UNUSED, - DEFAULT_PROB_OPCODE, - DEFAULT_PROB_OPERAND, - DEFAULT_PROB_SWAP, - optimize, -) +from gbso.optimize import optimize from gbso.program.program import Program -from gbso.program.mutate import mutate_program rLCDC = 0xFF40 rIE = 0xFFFF @@ -30,14 +22,3 @@ prgm = Program( optimized_prgm = optimize(prgm) optimized_prgm.display() - -for _ in range(10): - prgm = mutate_program( - prgm, - prob_opcode=DEFAULT_PROB_OPCODE, - prob_operand=DEFAULT_PROB_OPERAND, - prob_swap=DEFAULT_PROB_SWAP, - prob_insn=DEFAULT_PROB_INSN, - prob_insn_unused=DEFAULT_PROB_INSN_UNUSED, - ) - prgm.display() diff --git a/gbso/cpu/insn.py b/gbso/cpu/insn.py index 6c4f2e2..9e557ff 100644 --- a/gbso/cpu/insn.py +++ b/gbso/cpu/insn.py @@ -1047,6 +1047,9 @@ class DEC_HL(Insn): return "DEC (HL)" +# TODO: Implement DAA + + @dataclass class CPL(Insn): @staticmethod diff --git a/gbso/program/mutate.py b/gbso/program/mutate.py index 0b87bc1..1ce64e1 100644 --- a/gbso/program/mutate.py +++ b/gbso/program/mutate.py @@ -1,9 +1,10 @@ +from dataclasses import replace from enum import Enum -from gbso.cpu.regs import R16, R16_WITHOUT_SP, R8 from random import choice, randint, random, randrange from typing import List, Tuple, Type, TypeVar, Union from gbso.cpu.insn import ALL_INSN_CLASSES, Insn, Operand, UNUSED, get_signature_class +from gbso.cpu.regs import R16, R16_WITHOUT_SP, R8 from gbso.program.program import Program @@ -31,19 +32,16 @@ def mutate_program( ] ) new_prgm = prgm - print("======") + if mutation == Mutation.OPCODE: - print("OPCODE") new_prgm = mutate_opcode(prgm) elif mutation == Mutation.OPERAND: - print("OPERAND") new_prgm = mutate_operand(prgm) elif mutation == Mutation.SWAP: - print("SWAP") new_prgm = mutate_swap(prgm) elif mutation == Mutation.INSTRUCTION: - print("INSN") new_prgm = mutate_insn(prgm, prob_insn_unused) + return new_prgm @@ -57,9 +55,22 @@ def mutate_opcode(prgm: Program) -> Program: return Program(insns=insns) -# TODO: Implement +# God, this is ugly... a better approach would be to store operands as a tuple +# instead of individual named fields. def mutate_operand(prgm: Program) -> Program: - return prgm + insn_index = randrange(len(prgm.insns)) + insn = prgm.insns[insn_index] + + operand_index = randrange(len(insn.signature())) + operand_type = insn.signature()[operand_index] + operand_name = list(vars(insn).keys())[operand_index] + + insns = prgm.insns.copy() + insns[insn_index] = replace( + insn, **{operand_name: create_random_operand(operand_type)} + ) + + return Program(insns=insns) def mutate_swap(prgm: Program) -> Program: diff --git a/tests/program/test_mutate.py b/tests/program/test_mutate.py index 473cb99..33605b5 100644 --- a/tests/program/test_mutate.py +++ b/tests/program/test_mutate.py @@ -1,6 +1,9 @@ from gbso.cpu.insn import ADD_A_N, ADD_A_R, DEC_HL, LD_RR_NN from gbso.program.mutate import * +# NOTE: All of these trial counts and probabilities could be a lot more precise, +# but it is easier to just throw extra trials at the problem. + def test_mutate_swap(): trials = 1000