This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
kse-02/genetic.py

139 lines
4.4 KiB
Python
Raw Normal View History

2023-12-09 10:56:23 +00:00
import os
from typing import Callable
from deap import creator, base, tools, algorithms
import fuzzer
import instrument
from fuzzer import get_test_cases, get_test_class
import frozendict
INDMUPROB = 0.05
MUPROB = 0.1
CXPROB = 0.5
TOURNSIZE = 3
NPOP = 300
NGEN = 200
REPS = 10
to_test: str = ""
OUT_DIR = os.path.join(os.path.dirname(__file__), "tests")
def normalize(x):
return x / (1.0 + x)
def get_test_case_generator(f_name: str, arguments: list[instrument.Arg]) -> Callable[[], list]:
return lambda: list(list(get_test_cases(f_name, arguments, 1, enable_bar=False))[0].items())
def generate(f_name: str):
global to_test
to_test = f_name
creator.create("Fitness", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.Fitness)
n_initial = 10
args = instrument.functions[f_name]
toolbox = base.Toolbox()
toolbox.register("attr_test_case", get_test_case_generator(to_test, instrument.functions[to_test]))
toolbox.register("individual",
tools.initRepeat,
creator.Individual,
toolbox.attr_test_case,
n=n_initial)
toolbox.register("population",
tools.initRepeat,
list,
toolbox.individual)
toolbox.register("evaluate", fitness)
def mate(tc1, tc2):
t1, t2 = frozendict.frozendict(tc1), frozendict.frozendict(tc2)
print("ticino", tc1, tc2)
o1, o2 = fuzzer.crossover(t1, t2, args)
i1, i2 = creator.Individual(o1.items()), creator.Individual(o2.items())
print("mate", i1, i2)
return i1, i2
def mutate(tc):
t = frozendict.frozendict(tc)
o = fuzzer.mutate(t, args)
i1 = creator.Individual(o.items())
print("mutate", i1)
return i1,
toolbox.register("mate", mate)
toolbox.register("mutate", mutate)
toolbox.register("select", tools.selTournament, tournsize=TOURNSIZE)
coverage = []
for i in range(REPS):
instrument.archive_true_branches = {}
instrument.archive_false_branches = {}
population = toolbox.population(n=NPOP)
print("population", population)
algorithms.eaSimple(population, toolbox, CXPROB, MUPROB, NGEN, verbose=False)
cov = len(instrument.archive_true_branches) + len(instrument.archive_false_branches)
print(cov, instrument.archive_true_branches, instrument.archive_false_branches)
coverage.append(cov)
print(coverage)
def fitness(individuals: list[list]) -> tuple[float]:
range_start, range_end = instrument.n_of_branches[to_test]
# Reset any distance values from previous executions
instrument.distances_true = {}
instrument.distances_false = {}
fitness = 0.0
for individual in individuals:
x = frozendict.frozendict(individual)
# Run the function under test
try:
out = instrument.invoke(to_test, x)
except AssertionError:
print(to_test, x, "=", "[FAILS]")
return 10000,
# Sum up branch distances
for branch in range(range_start, range_end):
if branch in instrument.distances_true:
if instrument.distances_true[branch] == 0 and branch not in instrument.archive_true_branches:
instrument.archive_true_branches[branch] = x
if branch not in instrument.archive_true_branches:
fitness += normalize(instrument.distances_true[branch])
for branch in range(range_start, range_end):
if branch in instrument.distances_false:
if instrument.distances_false[branch] == 0 and branch not in instrument.archive_false_branches:
instrument.archive_false_branches[branch] = x
if branch not in instrument.archive_false_branches:
fitness += normalize(instrument.distances_false[branch])
print(to_test, x, "=", out)
print("fitness", fitness)
print()
return fitness,
def main():
instrument.load_benchmark(save_instrumented=False) # instrument all files in benchmark
f_name = "railencrypt_instrumented"
generate(f_name)
with open(os.path.join(OUT_DIR, f_name + ".py"), "w") as f:
cases = get_test_cases(f_name, instrument.functions[f_name], 100)
f.write(get_test_class(f_name, cases))
if __name__ == '__main__':
main()