Пример #1
0
def mz_init(prestate):
    prestate.adjacency_directions_rc = {
        i: CoordRC(a.y, a.x)
        for i, a in prestate.adjacency_directions.items()
    }
    prestate = wfc.wfc_utilities.find_pattern_center(prestate)
    wfc_state = types.SimpleNamespace(wfc_ns=prestate)

    wfc_state.result = None
    wfc_state.adjacency_relations = adjacency_extraction_consistent(
        wfc_state.wfc_ns, wfc_state.wfc_ns.patterns)
    wfc_state.patterns = np.array(list(
        wfc_state.wfc_ns.pattern_catalog.keys()))
    wfc_state.pattern_translations = list(
        wfc_state.wfc_ns.pattern_catalog.values())
    wfc_state.number_of_patterns = wfc_state.patterns.size
    wfc_state.number_of_directions = len(wfc_state.wfc_ns.adjacency_directions)

    wfc_state.propagator_matrix = np.zeros(
        (
            wfc_state.number_of_directions,
            wfc_state.number_of_patterns,
            wfc_state.number_of_patterns,
        ),
        dtype=np.bool_,
    )
    for d, p1, p2 in wfc_state.adjacency_relations:
        wfc_state.propagator_matrix[(d, p1, p2)] = True

    wfc_state.mz_dzn = {
        "w":
        wfc_state.wfc_ns.generated_size[0],
        "h":
        wfc_state.wfc_ns.generated_size[1],
        "pattern_count":
        wfc_state.number_of_patterns,
        "direction_count":
        wfc_state.number_of_directions,
        "adjacency_count":
        len(wfc_state.adjacency_relations),
        "pattern_names":
        list(wfc_state.patterns, zip(range(wfc_state.number_of_patterns))),
        "relation_matrix":
        calculate_adjacency_grid(wfc_state.wfc_ns.generated_size,
                                 wfc_state.wfc_ns.adjacency_directions),
        "adjaceny_table": [],
        "adjacency_matrix": [],
    }
Пример #2
0
def find_random_unresolved(wfc_state, random_variation):
    noise_level = 1e-6
    entropy_map = random_variation * noise_level
    entropy_map = entropy_map.flatten() + wfc_state.entropies.flatten()
    minimum_cell = np.argmin(entropy_map)
    if np.any(np.count_nonzero(wfc_state.wave_table, axis=2) == 0):
        WFC_LOGGER.warning("Solver FAIL")
        WFC_LOGGER.debug(
            f"previous decisions: {len(wfc_state.previous_decisions)}")
        return WFC_FAILURE
    if np.count_nonzero(wfc_state.wave_table,
                        axis=2).flatten()[minimum_cell] == 0:
        WFC_LOGGER.debug(f"previous decisions: {wfc_state}")
        return WFC_FAILURE
    return None

    higher_than_threshold = np.ma.MaskedArray(
        entropy_map,
        np.count_nonzero(wfc_state.wave_table, axis=2).flatten() <= 1)
    minimum_cell = higher_than_threshold.argmin(fill_value=999999.9)
    maximum_cell = higher_than_threshold.argmax(fill_value=0.0)
    chosen_cell = maximum_cell

    if np.any(np.count_nonzero(wfc_state.wave_table, axis=2) == 0):
        WFC_LOGGER.debug("A zero-state node has been found.")

    if wfc_parameters.overflow_check:
        if np.any(np.count_nonzero(wfc_state.wave_table, axis=2) > 65534):
            WFC_LOGGER.error("Overflow A")
            WFC_LOGGER.error(np.count_nonzero(wfc_state.wave_table, axis=2))
            pdb.set_trace()
            assert False
    if np.all(np.count_nonzero(wfc_state.wave_table, axis=2) == 1):
        WFC_LOGGER.info("DETECTED FINISH")
        WFC_LOGGER.info(
            f"nonzero count: {np.count_nonzero(wfc_state.wave_table, axis=2)}")

    cell_index = np.unravel_index(
        chosen_cell,
        [
            np.count_nonzero(wfc_state.wave_table, axis=2).shape[0],
            np.count_nonzero(wfc_state.wave_table, axis=2).shape[1],
        ],
    )
    return CoordRC(row=cell_index[0], column=cell_index[1])
Пример #3
0
def wrap_coords(wfc_parameters, cell_coords):
    r = (cell_coords.row + wfc_parameters.wfc_ns.generated_size[0]) % (
        wfc_parameters.wfc_ns.generated_size[0])
    c = (cell_coords.column + wfc_parameters.wfc_ns.generated_size[1]) % (
        wfc_parameters.wfc_ns.generated_size[1])
    return CoordRC(row=r, column=c)
Пример #4
0
def wfc_init(prestate):
    """
    Initialize the WFC solver, returning the fixed and mutable data structures needed.
    """
    prestate.adjacency_directions_rc = {
        i: CoordRC(a.y, a.x)
        for i, a in prestate.adjacency_directions.items()
    }  #
    prestate = wfc.wfc_utilities.find_pattern_center(prestate)
    parameters = types.SimpleNamespace(wfc_ns=prestate)

    state = types.SimpleNamespace()
    state.result = None

    parameters.heuristic = 0  # TODO: Implement control code to choose between heuristics

    parameters.adjacency_relations = adjacency_extraction_consistent(
        parameters.wfc_ns, parameters.wfc_ns.patterns)
    parameters.patterns = np.array(
        list(parameters.wfc_ns.pattern_catalog.keys()))
    parameters.pattern_translations = list(
        parameters.wfc_ns.pattern_catalog.values())
    parameters.number_of_patterns = parameters.patterns.size
    parameters.number_of_directions = len(
        parameters.wfc_ns.adjacency_directions)

    # The Propagator is a data structure that holds the adjacency information
    # for the patterns, i.e. given a direction, which patterns are allowed to
    # be placed next to the pattern that we're currently concerned with.
    # This won't change over the course of using the solver, so the important
    # thing here is fast lookup.
    parameters.propagator_matrix = np.zeros(
        (parameters.number_of_directions, parameters.number_of_patterns,
         parameters.number_of_patterns),
        dtype=np.bool_)
    for direction, pattern_one, pattern_two in parameters.adjacency_relations:
        parameters.propagator_matrix[(direction, pattern_one,
                                      pattern_two)] = True

    output = types.SimpleNamespace()

    # The Wave Table is the boolean expression table of which patterns are allowed
    # in which cells of the solution we are calculating.
    parameters.rows = parameters.wfc_ns.generated_size[0]
    parameters.columns = parameters.wfc_ns.generated_size[1]

    output.solving_time = np.full((parameters.rows, parameters.columns),
                                  0,
                                  dtype=np.int32)
    output.propagation_time = np.full((parameters.rows, parameters.columns),
                                      0,
                                      dtype=np.int32)

    parameters.wave_shape = [
        parameters.rows, parameters.columns, parameters.number_of_patterns
    ]
    state.wave_table = np.full(parameters.wave_shape, True, dtype=np.bool_)

    # The compatible_count is a running count of the number of patterns that
    # are still allowed to be next to this cell in a particular direction.
    compatible_shape = [
        parameters.rows, parameters.columns, parameters.number_of_patterns,
        parameters.number_of_directions
    ]

    WFC_LOGGER.debug(f"compatible shape:{compatible_shape}")
    state.compatible_count = np.full(
        compatible_shape, parameters.number_of_patterns,
        dtype=np.int16)  # assumes that there are less than 65536 patterns

    # The weights are how we manage the probabilities when we choose the next
    # pattern to place. Rather than recalculating them from scratch each time,
    # these let us incrementally update their values.
    state.weights = np.array(list(parameters.wfc_ns.pattern_weights.values()))
    state.weight_log_weights = np.vectorize(weight_log)(state.weights)
    state.sum_of_weights = np.sum(state.weights)

    state.sum_of_weight_log_weights = np.sum(state.weight_log_weights)
    state.starting_entropy = math.log(state.sum_of_weights) - (
        state.sum_of_weight_log_weights / state.sum_of_weights)

    state.entropies = np.zeros([parameters.rows, parameters.columns],
                               dtype=np.float64)
    state.sums_of_weights = np.zeros([parameters.rows, parameters.columns],
                                     dtype=np.float64)

    # Instead of updating all of the cells for every propagation, we use a queue
    # that marks the dirty tiles to update.
    state.observation_stack = collections.deque()

    output.output_grid = np.full([parameters.rows, parameters.columns],
                                 WFC_NULL_VALUE,
                                 dtype=np.int64)
    output.partial_output_grid = np.full(
        [parameters.rows, parameters.columns, parameters.number_of_patterns],
        -9,
        dtype=np.int64)

    output.current_iteration_count_observation = 0
    output.current_iteration_count_propagation = 0
    output.current_iteration_count_last_touch = 0
    output.current_iteration_count_crystal = 0
    output.solving_time = np.full((parameters.rows, parameters.columns),
                                  0,
                                  dtype=np.int32)
    output.ones_time = np.full((parameters.rows, parameters.columns),
                               0,
                               dtype=np.int32)
    output.propagation_time = np.full((parameters.rows, parameters.columns),
                                      0,
                                      dtype=np.int32)
    output.touch_time = np.full((parameters.rows, parameters.columns),
                                0,
                                dtype=np.int32)
    output.crystal_time = np.full((parameters.rows, parameters.columns),
                                  0,
                                  dtype=np.int32)
    output.method_time = np.full((parameters.rows, parameters.columns),
                                 0,
                                 dtype=np.int32)
    output.choices_recording = np.full((parameters.rows, parameters.columns),
                                       0,
                                       dtype=np.float32)

    output.stats_tracking = prestate.stats_tracking.copy()

    return parameters, state, output