def test_recurse_vs_loop(): from wfc_tiles import make_tile_catalog from wfc_patterns import make_pattern_catalog, pattern_grid_to_tiles from wfc_adjacency import adjacency_extraction from wfc_solver import run, makeWave, makeAdj, lexicalLocationHeuristic, lexicalPatternHeuristic from wfc_visualize import figure_list_of_tiles, figure_false_color_tile_grid, figure_pattern_catalog, render_tiles_to_output, figure_adjacencies import imageio img = imageio.imread("../images/samples/Red Maze.png") tile_size = 1 pattern_width = 2 rotations = 0 output_size = [84, 84] ground = None direction_offsets = list(enumerate([(0, -1), (1, 0), (0, 1), (-1, 0)])) tile_catalog, tile_grid, code_list, unique_tiles = make_tile_catalog( img, tile_size) pattern_catalog, pattern_weights, pattern_list, pattern_grid = make_pattern_catalog( tile_grid, pattern_width, rotations) adjacency_relations = adjacency_extraction(pattern_grid, pattern_catalog, direction_offsets) number_of_patterns = len(pattern_weights) encode_patterns = dict(enumerate(pattern_list)) decode_patterns = {x: i for i, x in enumerate(pattern_list)} decode_directions = {j: i for i, j in direction_offsets} adjacency_list = {} for i, d in direction_offsets: adjacency_list[d] = [set() for i in pattern_weights] for i in adjacency_relations: adjacency_list[i[0]][decode_patterns[i[1]]].add(decode_patterns[i[2]]) wave = makeWave(number_of_patterns, output_size[0], output_size[1]) adjacency_matrix = makeAdj(adjacency_list) solution_loop = run(wave.copy(), adjacency_matrix, locationHeuristic=lexicalLocationHeuristic, patternHeuristic=lexicalPatternHeuristic, periodic=True, backtracking=False, onChoice=None, onBacktrack=None) solution_recurse = run_recurse(wave.copy(), adjacency_matrix, locationHeuristic=lexicalLocationHeuristic, patternHeuristic=lexicalPatternHeuristic, periodic=True, backtracking=False, onChoice=None, onBacktrack=None) assert (numpy.array_equiv(solution_loop, solution_recurse))
def test_run(): wave = makeWave(3, 3, 4) adjLists = {} adjLists[(+1, 0)] = adjLists[(-1, 0)] = adjLists[(0, +1)] = adjLists[(0, -1)] = [[1], [0], [2]] adj = makeAdj(adjLists) first_result = run(wave.copy(), adj, locationHeuristic=lexicalLocationHeuristic, patternHeuristic=lexicalPatternHeuristic, periodic=False) expected_first_result = numpy.array([[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 1]]) assert numpy.array_equal(first_result, expected_first_result) event_log = [] def onChoice(pattern, i, j): event_log.append((pattern, i, j)) def onBacktrack(): event_log.append('backtrack') second_result = run(wave.copy(), adj, locationHeuristic=lexicalLocationHeuristic, patternHeuristic=lexicalPatternHeuristic, periodic=True, backtracking=True, onChoice=onChoice, onBacktrack=onBacktrack) expected_second_result = numpy.array([[2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]) assert numpy.array_equal(second_result, expected_second_result) print(event_log) assert event_log == [(0, 0, 0), 'backtrack'] def explode(wave): if wave.sum() < 20: raise Infeasible try: result = run(wave.copy(), adj, locationHeuristic=lexicalLocationHeuristic, patternHeuristic=lexicalPatternHeuristic, periodic=True, backtracking=True, checkFeasible=explode) print(result) happy = False except Contradiction: happy = True assert happy
def run(wave, adj, locationHeuristic, patternHeuristic, periodic=False, backtracking=False, onBacktrack=None, onChoice=None, onObserve=None, onPropagate=None, checkFeasible=None, onFinal=None, depth=0, depth_limit=None): #print("run.") if checkFeasible: if not checkFeasible(wave): raise Contradiction if depth_limit: if depth > depthlimit: raise TimedOut if depth % 50 == 0: print(depth) original = wave.copy() propagate(wave, adj, periodic=periodic, onPropagate=onPropagate) try: pattern, i, j = observe(wave, locationHeuristic, patternHeuristic) if onChoice: onChoice(pattern, i, j) wave[:, i, j] = False wave[pattern, i, j] = True if onObserve: onObserve(wave) propagate(wave, adj, periodic=periodic, onPropagate=onPropagate) if wave.sum() > wave.shape[1] * wave.shape[2]: #return run(wave, adj, locationHeuristic, patternHeuristic, periodic, backtracking, onBacktrack) return run(wave, adj, locationHeuristic, patternHeuristic, periodic=periodic, backtracking=backtracking, onBacktrack=onBacktrack, onChoice=onChoice, onObserve=onObserve, onPropagate=onPropagate, checkFeasible=checkFeasible, depth=depth + 1, depth_limit=depth_limit) else: if onFinal: onFinal(wave) return numpy.argmax(wave, 0) except Contradiction: if backtracking: if onBacktrack: onBacktrack() wave = original wave[pattern, i, j] = False return run(wave, adj, locationHeuristic, patternHeuristic, periodic=periodic, backtracking=backtracking, onBacktrack=onBacktrack, onChoice=onChoice, onObserve=onObserve, onPropagate=onPropagate, checkFeasible=checkFeasible, depth=depth + 1, depth_limit=depth_limit) else: if onFinal: onFinal(wave) raise