|
|
@ -0,0 +1,57 @@ |
|
|
|
from enum import Enum |
|
|
|
from random import random |
|
|
|
from typing import List, Tuple, TypeVar |
|
|
|
|
|
|
|
from gbso.program.program import Program |
|
|
|
|
|
|
|
|
|
|
|
class Mutation(Enum): |
|
|
|
OPCODE = "OPCODE" |
|
|
|
OPERAND = "OPERAND" |
|
|
|
SWAP = "SWAP" |
|
|
|
INSTRUCTION = "INSTRUCTION" |
|
|
|
|
|
|
|
|
|
|
|
def mutate_program( |
|
|
|
prgm: Program, |
|
|
|
prob_opcode: float, |
|
|
|
prob_operand: float, |
|
|
|
prob_swap: float, |
|
|
|
prob_insn: float, |
|
|
|
prob_insn_unused: float, |
|
|
|
) -> Program: |
|
|
|
mutation = sample_probs( |
|
|
|
[ |
|
|
|
(Mutation.OPCODE, prob_opcode), |
|
|
|
(Mutation.OPERAND, prob_operand), |
|
|
|
(Mutation.SWAP, prob_swap), |
|
|
|
(Mutation.INSTRUCTION, prob_insn), |
|
|
|
] |
|
|
|
) |
|
|
|
new_prgm = prgm |
|
|
|
if mutation == Mutation.OPCODE: |
|
|
|
new_prgm = mutate_opcode(prgm) |
|
|
|
elif mutation == Mutation.OPERAND: |
|
|
|
new_prgm = mutate_operand(prgm) |
|
|
|
elif mutation == Mutation.SWAP: |
|
|
|
new_prgm = mutate_swap(prgm) |
|
|
|
elif mutation == Mutation.INSTRUCTION: |
|
|
|
new_prgm = mutate_insn(prgm, prob_insn_unused) |
|
|
|
return new_prgm |
|
|
|
|
|
|
|
|
|
|
|
A = TypeVar("A") |
|
|
|
|
|
|
|
|
|
|
|
# NOTE: List must be non-empty and probabilities must sum to 1 |
|
|
|
def sample_probs(probs: List[Tuple[A, float]]) -> A: |
|
|
|
r = random() |
|
|
|
cum_prob = 0.0 |
|
|
|
|
|
|
|
for val, prob in probs[:-1]: |
|
|
|
cum_prob += prob |
|
|
|
if r < cum_prob: |
|
|
|
return val |
|
|
|
|
|
|
|
val, _ = probs[-1] |
|
|
|
return val |