Browse Source

Implement operand mutation

master
Forest Belton 2 years ago
parent
commit
d4907eb204
4 changed files with 26 additions and 28 deletions
  1. +1
    -20
      ex.py
  2. +3
    -0
      gbso/cpu/insn.py
  3. +19
    -8
      gbso/program/mutate.py
  4. +3
    -0
      tests/program/test_mutate.py

+ 1
- 20
ex.py View File

@ -1,16 +1,8 @@
from gbso.cpu.insn import * from gbso.cpu.insn import *
from gbso.cpu.regs import R8, R16 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.program import Program
from gbso.program.mutate import mutate_program
rLCDC = 0xFF40 rLCDC = 0xFF40
rIE = 0xFFFF rIE = 0xFFFF
@ -30,14 +22,3 @@ prgm = Program(
optimized_prgm = optimize(prgm) optimized_prgm = optimize(prgm)
optimized_prgm.display() 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()

+ 3
- 0
gbso/cpu/insn.py View File

@ -1047,6 +1047,9 @@ class DEC_HL(Insn):
return "DEC (HL)" return "DEC (HL)"
# TODO: Implement DAA
@dataclass @dataclass
class CPL(Insn): class CPL(Insn):
@staticmethod @staticmethod

+ 19
- 8
gbso/program/mutate.py View File

@ -1,9 +1,10 @@
from dataclasses import replace
from enum import Enum from enum import Enum
from gbso.cpu.regs import R16, R16_WITHOUT_SP, R8
from random import choice, randint, random, randrange from random import choice, randint, random, randrange
from typing import List, Tuple, Type, TypeVar, Union 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.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 from gbso.program.program import Program
@ -31,19 +32,16 @@ def mutate_program(
] ]
) )
new_prgm = prgm new_prgm = prgm
print("======")
if mutation == Mutation.OPCODE: if mutation == Mutation.OPCODE:
print("OPCODE")
new_prgm = mutate_opcode(prgm) new_prgm = mutate_opcode(prgm)
elif mutation == Mutation.OPERAND: elif mutation == Mutation.OPERAND:
print("OPERAND")
new_prgm = mutate_operand(prgm) new_prgm = mutate_operand(prgm)
elif mutation == Mutation.SWAP: elif mutation == Mutation.SWAP:
print("SWAP")
new_prgm = mutate_swap(prgm) new_prgm = mutate_swap(prgm)
elif mutation == Mutation.INSTRUCTION: elif mutation == Mutation.INSTRUCTION:
print("INSN")
new_prgm = mutate_insn(prgm, prob_insn_unused) new_prgm = mutate_insn(prgm, prob_insn_unused)
return new_prgm return new_prgm
@ -57,9 +55,22 @@ def mutate_opcode(prgm: Program) -> Program:
return Program(insns=insns) 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: 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: def mutate_swap(prgm: Program) -> Program:

+ 3
- 0
tests/program/test_mutate.py View File

@ -1,6 +1,9 @@
from gbso.cpu.insn import ADD_A_N, ADD_A_R, DEC_HL, LD_RR_NN from gbso.cpu.insn import ADD_A_N, ADD_A_R, DEC_HL, LD_RR_NN
from gbso.program.mutate import * 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(): def test_mutate_swap():
trials = 1000 trials = 1000

Loading…
Cancel
Save