Exemple #1
0
def test_adjacency_extraction(resources: Resources) -> None:
    # TODO: generalize this to more than the four cardinal directions
    direction_offsets = list(enumerate([(0, -1), (1, 0), (0, 1), (-1, 0)]))

    filename = resources.get_image("samples/Red Maze.png")
    img = imageio.imread(filename)
    tile_size = 1
    pattern_width = 2
    periodic = False
    _tile_catalog, tile_grid, _code_list, _unique_tiles = wfc_tiles.make_tile_catalog(
        img, tile_size)
    pattern_catalog, _pattern_weights, _pattern_list, pattern_grid = wfc_patterns.make_pattern_catalog(
        tile_grid, pattern_width, periodic)
    adjacency_relations = wfc_adjacency.adjacency_extraction(
        pattern_grid, pattern_catalog, direction_offsets)
    assert ((0, -1), -6150964001204120324,
            -4042134092912931260) in adjacency_relations
    assert ((-1, 0), -4042134092912931260,
            3069048847358774683) in adjacency_relations
    assert ((1, 0), -3950451988873469076,
            -3950451988873469076) in adjacency_relations
    assert ((-1, 0), -3950451988873469076,
            -3950451988873469076) in adjacency_relations
    assert ((0, 1), -3950451988873469076,
            3336256675067683735) in adjacency_relations
    assert (not ((0, -1), -3950451988873469076, -3950451988873469076)
            in adjacency_relations)
    assert (not ((0, 1), -3950451988873469076, -3950451988873469076)
            in adjacency_relations)
def test_pattern_to_tile(resources):
    filename = resources.get_image("samples/Red Maze.png")
    img = imageio.imread(filename)
    tile_size = 1
    pattern_width = 2
    _tile_catalog, tile_grid, _code_list, _unique_tiles = wfc_tiles.make_tile_catalog(img, tile_size)

    pattern_catalog, _pattern_weights, _pattern_list, pattern_grid = wfc_patterns.make_pattern_catalog(
        tile_grid, pattern_width
    )
    new_tile_grid = wfc_patterns.pattern_grid_to_tiles(pattern_grid, pattern_catalog)
    assert np.array_equal(tile_grid, new_tile_grid)
Exemple #3
0
def test_make_pattern_catalog(resources: Resources) -> None:
    filename = resources.get_image("samples/Red Maze.png")
    img = imageio.imread(filename)
    tile_size = 1
    pattern_width = 2
    _tile_catalog, tile_grid, _code_list, _unique_tiles = wfc_tiles.make_tile_catalog(
        img, tile_size)

    pattern_catalog, pattern_weights, pattern_list, _pattern_grid = wfc_patterns.make_pattern_catalog(
        tile_grid, pattern_width)
    assert pattern_weights[-6150964001204120324] == 1
    assert pattern_list[3] == 2800765426490226432
    assert pattern_catalog[5177878755649963747][0][1] == -8754995591521426669
Exemple #4
0
def _test_recurse_vs_loop(resources):
    # FIXME: run_recurse or run_loop do not exist anymore
    filename = resources.get_image("samples/Red Maze.png")
    img = imageio.imread(filename)
    tile_size = 1
    pattern_width = 2
    rotations = 0
    output_size = [84, 84]
    direction_offsets = list(enumerate([(0, -1), (1, 0), (0, 1), (-1, 0)]))
    _tile_catalog, tile_grid, _code_list, _unique_tiles = wfc_tiles.make_tile_catalog(img, tile_size)
    pattern_catalog, pattern_weights, pattern_list, pattern_grid = wfc_patterns.make_pattern_catalog(
        tile_grid, pattern_width, rotations
    )
    adjacency_relations = wfc_adjacency.adjacency_extraction(
        pattern_grid, pattern_catalog, direction_offsets
    )
    number_of_patterns = len(pattern_weights)
    decode_patterns = {x: i for i, x in enumerate(pattern_list)}
    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 = wfc_solver.makeWave(number_of_patterns, output_size[0], output_size[1])
    adjacency_matrix = wfc_solver.makeAdj(adjacency_list)
    solution_loop = wfc_solver.run(
        wave.copy(),
        adjacency_matrix,
        locationHeuristic=wfc_solver.lexicalLocationHeuristic,
        patternHeuristic=wfc_solver.lexicalPatternHeuristic,
        periodic=True,
        backtracking=False,
        onChoice=None,
        onBacktrack=None,
    )
    solution_recurse = wfc_solver.run_recurse(
        wave.copy(),
        adjacency_matrix,
        locationHeuristic=wfc_solver.lexicalLocationHeuristic,
        patternHeuristic=wfc_solver.lexicalPatternHeuristic,
        periodic=True,
        backtracking=False,
        onChoice=None,
        onBacktrack=None,
    )
    assert numpy.array_equiv(solution_loop, solution_recurse)
Exemple #5
0
def bit_wfc(level_bits, fixed_tiles):
    """ Perform WFC to create a new tile grid based on default """
    #TODO: move this stuff into Context.__init__?
    width = level_bits.shape[0]
    height = level_bits.shape[1]
    tile_size = 1
    pattern_size = 2
    # Get the tile grid
    # Tile catalog maps from the hash to a 1x1x40 vector, reversing the hashing process
    print("\tGetting tile grid")
    tile_catalog, level_data_tiles, _code_list, _unique_tiles = wfc_tiles.make_tile_catalog(
        level_bits, tile_size)
    print("\tRect size: {}".format(level_data_tiles.shape))
    adj_rules = None

    # Get the patterns
    # Pattern catalog maps tiles to patterns?
    # Input is not periodic
    print("\tGetting pattern catalog")
    pattern_catalog, pattern_weights, pattern_list, pattern_grid = wfc_patterns.make_pattern_catalog(
        level_data_tiles, pattern_size, False)
    number_of_patterns = len(pattern_catalog)
    print("\tNumber of patterns: {}".format(number_of_patterns))

    # Get the adjacencies
    print("\tGetting adjacencies")
    directions = list(enumerate([(0, -1), (1, 0), (0, 1), (-1, 0)]))
    adjacency_relations = wfc_adjacency.adjacency_extraction(
        pattern_grid, pattern_catalog, directions)

    # Create functions to make pattern arrays and decode them
    decode_patterns = np.vectorize({x: i
                                    for i, x in enumerate(pattern_list)}.get)
    encode_patterns = np.vectorize({i: x
                                    for i, x in enumerate(pattern_list)}.get)
    decode_dict = {x: i for i, x in enumerate(pattern_list)}

    # Direction -> list of sets
    adjacency_list = {}
    for i, d in directions:
        adjacency_list[d] = [set() for i in pattern_weights]
    for direction, pattern1, pattern2 in adjacency_relations:
        adjacency_list[direction][decode_dict[pattern1]].add(
            decode_dict[pattern2])
    # The original level as pattern ids
    pattern_id_grid = decode_patterns(pattern_grid)

    # ASP
    print("\tStarting ASP instance")
    ctl = clingo.Control([], logger=print)
    # WFC constraints
    ctl.add(
        "wfc", ["h", "w", "p"], """
      cell(0..h-1,0..w-1).
      pattern(0..p-1).
      wave(I,J,K) :- (I,J,K) = @constrained_tiles.
      1 { wave(I,J,P):pattern(P) } 1 :- cell(I,J).
      :- wave(I,J,A), J < w-1, not 1 { wave(I,J+1,@v_adj(A)) }.
      :- wave(I,J,A), I < h-1, not 1 { wave(I+1,J,@h_adj(A)) }.
      %:- pattern(P), not 1 { wave(I,J,P) }. % Every tile must be used at least once
      #show wave/3.
    """)
    ctx = Context(width, height, adjacency_list)
    #TODO: swap axes?
    for t in fixed_tiles:
        ctx.pin_tile(t[1], t[0], pattern_id_grid)
    print("\tGrounding ASP Model")
    ctl.ground([
        ("wfc", list(map(clingo.Number, [height, width, number_of_patterns])))
    ],
               context=ctx)
    print("\tSolving ASP Model")
    #TODO: --restart_on_model, Config object?
    #TODO: Specify seed to ASP config?
    #TODO: Constrain the amount of plagiarism?
    ctl.solve(on_model=ctx.on_model)
    solution = ctx.solution
    # Convert to pattern array
    solution_as_ids = encode_patterns(solution)
    # Convert to tile hash array
    solution_tile_grid = wfc_patterns.pattern_grid_to_tiles(
        solution_as_ids, pattern_catalog)
    output = np.zeros((height, width, level_bits.shape[2]))
    # Convert back to bit array
    #TODO: swap axes?
    for y in range(height):
        for x in range(width):
            output[y, x, :] = tile_catalog[solution_tile_grid[y, x]]
    output = np.swapaxes(output, 0, 1)
    assert output.shape == level_bits.shape
    # Convert to int
    output = output.astype("int64")
    return output