|
|
- from math import log
- from random import random
- from typing import List, Optional, Tuple
-
- from gbso.program.test_case import Output, TestCase, eq_on_testcase
- from gbso.program.mutate import mutate_program
- from gbso.program.program import Program
-
- EPSILON = 0.00001
-
- DEFAULT_NUM_ITERS = 1_000_000
-
- DEFAULT_PROB_OPCODE = 0.25
- DEFAULT_PROB_OPERAND = 0.25
- DEFAULT_PROB_SWAP = 0.25
- DEFAULT_PROB_INSN = 0.25
-
- DEFAULT_PROB_INSN_UNUSED = 0.1
-
-
- def cost(orig_prgm, test_cases, outputs, prgm) -> Tuple[int, bool]:
- c = prgm.perf() - orig_prgm.perf()
- eq = c == 0
- # print(f"init cost: {c}")
-
- for test_case in test_cases:
- c += eq_on_testcase(orig_prgm, prgm, test_case, outputs)
- # print(f"cost after testcase: {c}")
-
- return c, eq
-
-
- def optimize(
- target_prgm: Program,
- max_size: int,
- test_cases: List[TestCase],
- outputs: List[Output],
- beta: int = 0.5, # How far away in cost you are allowed to search
- init_prgm: Optional[Program] = None,
- num_iters: int = DEFAULT_NUM_ITERS,
- prob_opcode: float = DEFAULT_PROB_OPCODE,
- prob_operand: float = DEFAULT_PROB_OPERAND,
- prob_swap: float = DEFAULT_PROB_SWAP,
- prob_insn: float = DEFAULT_PROB_INSN,
- prob_insn_unused: float = DEFAULT_PROB_INSN_UNUSED,
- ) -> Program:
- padded_prgm = (init_prgm or target_prgm).pad(max_size)
-
- last_prgm = padded_prgm
- last_cost, _last_eq = cost(target_prgm, test_cases, outputs, last_prgm)
-
- best_prgm = target_prgm.pad(max_size)
- best_cost = 0
-
- num_candidates = 0
-
- for _ in range(num_iters):
- candidate_prgm = mutate_program(
- last_prgm, prob_opcode, prob_operand, prob_swap, prob_insn, prob_insn_unused
- )
- candidate_cost, candidate_eq = cost(
- target_prgm, test_cases, outputs, candidate_prgm
- )
-
- if candidate_cost < best_cost and candidate_eq:
- best_prgm = candidate_prgm
- best_cost = candidate_cost
- num_candidates += 1
-
- if candidate_cost < last_cost - log(random()) / beta:
- last_prgm = candidate_prgm
- last_cost = candidate_cost
-
- print(f"Optimization complete. Total candidates: {num_candidates}")
- return best_prgm
|