|
import numpy as np |
|
import sys, os, json |
|
from deap import base, creator, gp, tools, algorithms |
|
from dsl import * |
|
import glob |
|
|
|
from dsl import _objects |
|
|
|
|
|
class GridList(list): |
|
pass |
|
|
|
|
|
creator.create("FitnessMax", base.Fitness, weights=(1.0,)) |
|
creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMax) |
|
|
|
pset = gp.PrimitiveSetTyped("MAIN", [Grid], Grid) |
|
|
|
|
|
pset.addPrimitive(ic_compress2, [Grid], Grid) |
|
pset.addPrimitive(flipy, [Grid], Grid) |
|
pset.addPrimitive(rot90, [Grid], Grid) |
|
pset.addPrimitive(rot180, [Grid], Grid) |
|
pset.addPrimitive(mirrorX, [Grid], Grid) |
|
pset.addPrimitive(mirrorY, [Grid], Grid) |
|
pset.addPrimitive(overlay, [Grid, Grid], Grid) |
|
pset.addPrimitive(set_bg, [int, Grid], Grid) |
|
pset.addPrimitive(ic_connectY, [Grid], Grid) |
|
pset.addPrimitive(ic_connectX, [Grid], Grid) |
|
pset.addPrimitive(ic_compress3, [Grid], Grid) |
|
pset.addPrimitive(ic_erasecol, [int, Grid], Grid) |
|
pset.addPrimitive(left_half, [Grid], Grid) |
|
pset.addPrimitive(right_half, [Grid], Grid) |
|
pset.addPrimitive(top_half, [Grid], Grid) |
|
pset.addPrimitive(repeatX, [Grid], Grid) |
|
pset.addPrimitive(flipx, [Grid], Grid) |
|
pset.addPrimitive(setcol, [Colour, Grid], Grid) |
|
pset.addPrimitive(ic_embed, [Grid, Grid], Grid) |
|
pset.addPrimitive(rot270, [Grid], Grid) |
|
|
|
|
|
pset.addPrimitive(ic_splitall, [Grid], GridList) |
|
pset.addPrimitive(ic_composegrowing, [GridList], Grid) |
|
pset.addPrimitive(lambda x: GridList([x]), [Grid], GridList, name="toGridList") |
|
pset.addTerminal(GridList([]), GridList) |
|
pset.addPrimitive(ic_pickunique, [GridList], Grid) |
|
pset.addPrimitive(gravity_right, [Grid], Grid) |
|
pset.addPrimitive(split8, [Grid], GridList) |
|
pset.addPrimitive(ic_makeborder, [Grid], Grid) |
|
pset.addPrimitive(ic_filtercol, [Colour, Grid], Grid) |
|
pset.addPrimitive(ic_invert, [Grid], Grid) |
|
pset.addPrimitive(logical_and, [Grid, Grid], Grid) |
|
pset.addPrimitive(fillobj, [Colour, Grid], Grid) |
|
pset.addPrimitive(topcol, [Grid], Colour) |
|
pset.addPrimitive(rarestcol, [Grid], Colour) |
|
pset.addPrimitive(gravity_down, [Grid], Grid) |
|
pset.addPrimitive(pickcommon, [GridList], Grid) |
|
pset.addPrimitive(swapxy, [Grid], Grid) |
|
pset.addPrimitive(topcol, [Grid], Colour) |
|
pset.addPrimitive(setcol, [Colour, Grid], Grid) |
|
pset.addPrimitive(get_bg, [Grid], Colour) |
|
pset.addPrimitive(rarestcol, [Grid], Colour) |
|
pset.addPrimitive(ic_fill, [Colour, Grid], Grid) |
|
pset.addPrimitive(ic_center, [Grid], Grid) |
|
pset.addPrimitive(countToY, [Count, Colour], Grid) |
|
pset.addPrimitive(countPixels, [Grid], Count) |
|
pset.addPrimitive(ic_splitcols, [Grid], GridList) |
|
pset.addPrimitive(grid_split, [Grid], GridList) |
|
pset.addPrimitive(_objects, [Grid], GridList) |
|
pset.addPrimitive(overlay, [Grid, Grid], Grid) |
|
pset.addPrimitive(stack_no_crop, [GridList], Grid) |
|
pset.addPrimitive(move_down, [Grid], Grid) |
|
pset.addPrimitive(draw_line, [Grid, int], Grid) |
|
pset.addPrimitive(draw_line_slant_up, [Grid, Grid], Grid) |
|
pset.addPrimitive(draw_line_slant_down, [Grid], Grid) |
|
pset.addPrimitive(rarestcol, [Grid], int) |
|
pset.addPrimitive(lambda: 1, [], int, name="int_one") |
|
|
|
|
|
for i in range(1, 10): |
|
pset.addTerminal(i, int) |
|
|
|
|
|
import operator |
|
|
|
toolbox = base.Toolbox() |
|
toolbox.register("compile", gp.compile, pset=pset) |
|
toolbox.register("select", tools.selTournament, tournsize=3) |
|
|
|
|
|
toolbox.register("mate", gp.cxOnePointLeafBiased, termpb=0.1) |
|
|
|
|
|
toolbox.register("expr_mut", gp.genFull, min_=0, max_=2) |
|
toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset) |
|
|
|
|
|
MAX_TREE_HEIGHT = 17 |
|
toolbox.decorate("mate", gp.staticLimit(operator.attrgetter("height"), MAX_TREE_HEIGHT)) |
|
toolbox.decorate("mutate", gp.staticLimit(operator.attrgetter("height"), MAX_TREE_HEIGHT)) |
|
|
|
|
|
toolbox.register("population", tools.initRepeat, list, |
|
lambda: creator.Individual(gp.genHalfAndHalf(pset, min_=1, max_=3))) |
|
|
|
def evaluate_task(individual, task): |
|
func = toolbox.compile(expr=individual) |
|
total = 0 |
|
for example in task['train']: |
|
inp = Grid(np.array(example["input"])) |
|
tgt = Grid(np.array(example["output"])) |
|
try: |
|
out = func(inp) |
|
if out.grid.shape == tgt.grid.shape: |
|
total += np.sum(out.grid == tgt.grid) |
|
except: |
|
pass |
|
return (total,) |
|
|
|
toolbox.register("evaluate", evaluate_task) |
|
|
|
|
|
training_folder = "./training/" |
|
task_files = glob.glob(training_folder + "*.json") |
|
|
|
results = [] |
|
|
|
|
|
for task_file in task_files: |
|
task_name = os.path.basename(task_file) |
|
print(f"Processing {task_name}") |
|
|
|
with open(task_file, 'r') as f: |
|
task = json.load(f) |
|
|
|
|
|
pop = toolbox.population(n=150) |
|
hof = tools.HallOfFame(1) |
|
|
|
for gen in range(250): |
|
offspring = algorithms.varAnd(pop, toolbox, cxpb=0.5, mutpb=0.2) |
|
fits = toolbox.map(lambda ind: toolbox.evaluate(ind, task), offspring) |
|
|
|
for fit, ind in zip(fits, offspring): |
|
ind.fitness.values = fit |
|
|
|
hof.update(offspring) |
|
pop = toolbox.select(offspring, k=len(pop)) |
|
|
|
|
|
best_ind = hof[0] |
|
func = toolbox.compile(expr=best_ind) |
|
|
|
correct = False |
|
try: |
|
for test_case in task["test"]: |
|
test_inp = Grid(np.array(test_case["input"])) |
|
expected_out = np.array(test_case["output"]) |
|
output_grid = func(test_inp).grid |
|
if np.array_equal(output_grid, expected_out): |
|
correct = True |
|
else: |
|
correct = False |
|
break |
|
except: |
|
correct = False |
|
|
|
results.append({ |
|
"task_name": task_name, |
|
"best_program": str(best_ind), |
|
"solution_found": correct |
|
}) |
|
|
|
print(f"{task_name} completed. Solution found: {correct}") |
|
|
|
|
|
with open("tasks_results_summary.json", "w") as f: |
|
json.dump(results, f, indent=2) |
|
|
|
print("All tasks processed. Results saved to tasks_results_summary.json.") |
|
|
|
|
|
def run_task(task_path): |
|
with open(task_path, 'r') as f: |
|
task = json.load(f) |
|
|
|
pop = toolbox.population(n=150) |
|
hof = tools.HallOfFame(1) |
|
|
|
for gen in range(250): |
|
offspring = algorithms.varAnd(pop, toolbox, cxpb=0.5, mutpb=0.2) |
|
fits = toolbox.map(lambda ind: toolbox.evaluate(ind, task), offspring) |
|
|
|
for fit, ind in zip(fits, offspring): |
|
ind.fitness.values = fit |
|
|
|
hof.update(offspring) |
|
pop = toolbox.select(offspring, k=len(pop)) |
|
|
|
best_ind = hof[0] |
|
func = toolbox.compile(expr=best_ind) |
|
|
|
|
|
test_example = task["test"][0] |
|
input_grid = np.array(test_example["input"]) |
|
target_grid = np.array(test_example["output"]) |
|
|
|
try: |
|
output_grid = func(Grid(input_grid)).grid |
|
correct = np.array_equal(output_grid, target_grid) |
|
except: |
|
output_grid = np.zeros_like(input_grid) |
|
correct = False |
|
|
|
return str(best_ind), correct, input_grid.tolist(), target_grid.tolist(), output_grid.tolist() |
|
|