def standardise_variables_names(self, indent=0): print_message("Standardising variable names...", 3, indent=indent) # Give variables standard names and replace stars with new variable names standard_variables_from_input_variables = {} current_variable_number = 0 for t, generation in enumerate(self.background_grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell == "*": self.background_grid[t][y][x] = "c" + str(current_variable_number) current_variable_number += 1 elif cell not in ["0", "1"]: (variable, negated) = variable_from_literal(cell) if variable not in standard_variables_from_input_variables: standard_variables_from_input_variables[variable] = negate( "c" + str(current_variable_number), negated) current_variable_number += 1 self.background_grid[t][y][x] = negate(standard_variables_from_input_variables[variable], negated) for t, generation in enumerate(self.grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell == "*": self.grid[t][y][x] = "c" + str(current_variable_number) current_variable_number += 1 elif cell not in ["0", "1"]: (variable, negated) = variable_from_literal(cell) if variable not in standard_variables_from_input_variables: standard_variables_from_input_variables[variable] = negate( "c" + str(current_variable_number), negated) current_variable_number += 1 self.grid[t][y][x] = negate(standard_variables_from_input_variables[variable], negated) # Rename any literals in rule for transition, literal in self.rule.items(): if literal not in ["0", "1"]: (variable, negated) = variable_from_literal(literal) if variable not in standard_variables_from_input_variables: standard_variables_from_input_variables[variable] = negate("c" + str(current_variable_number), negated) current_variable_number += 1 self.rule[transition] = negate(standard_variables_from_input_variables[variable], negated) print_message("Done\n", 3, indent=indent)
def rulestring_from_rule(rule): variables = [variable_from_literal(value)[0] for value in rule.values() if value not in ["0", "1"]] if len(variables) != len(set(variables)): return "{" + ", ".join( ("'" + transition + "': '" + literal + "'") for transition, literal in sorted(rule.items())) + "}" elif len(variables) == 0: partial_flag = False else: partial_flag = True rulestring = "" if partial_flag: rulestring += "p" for BS_letter in ["B", "S"]: rulestring += BS_letter for number_of_neighbours in "012345678": if not partial_flag: possible_number_of_transitions = len(possible_transitions[number_of_neighbours]) number_of_transitions = sum((rule[BS_letter + number_of_neighbours + character] == "1") for character in possible_transitions[number_of_neighbours]) if number_of_transitions == possible_number_of_transitions: rulestring += number_of_neighbours elif 0 < number_of_transitions <= possible_number_of_transitions / 2: rulestring += number_of_neighbours for character in possible_transitions[number_of_neighbours]: if rule[BS_letter + number_of_neighbours + character] == "1": rulestring += character elif number_of_transitions != 0: rulestring += number_of_neighbours rulestring += "-" for character in possible_transitions[number_of_neighbours]: if rule[BS_letter + number_of_neighbours + character] == "0": rulestring += character else: characters = "" banned_characters = "" for character in possible_transitions[number_of_neighbours]: literal = rule[BS_letter + number_of_neighbours + character] if literal == "0": banned_characters += character elif literal == "1": characters += character if characters == "" and banned_characters == "": rulestring += number_of_neighbours elif len(banned_characters) < len(possible_transitions[number_of_neighbours]): rulestring += number_of_neighbours rulestring += characters if len(banned_characters) > 0: rulestring += "-" rulestring += banned_characters if BS_letter == "B": rulestring += "/" return rulestring
def search_pattern_from_string(input_string, indent=0): """Create the grid and ignore_transition of a search pattern from the given string""" grid, ignore_transition = src.formatting.parse_input_string(input_string, indent=indent) print_message("Pattern parsed as:\n" + src.formatting.make_csv(grid, ignore_transition) + "\n", 3, indent=indent) for t, generation in enumerate(grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell not in ["0", "1", "*"]: variable, negated = variable_from_literal(cell) grid[t][y][x] = negate("user_input_" + variable, negated) return grid, ignore_transition
def deterministic(self, indent=0): print_message("Checking if pattern is deterministic...", 3, indent=indent) determined = make_grid(False, template=self.grid) determined_variables = set() width = len(self.grid[0][0]) height = len(self.grid[0]) while True: determined_copy = copy.deepcopy(determined) for t, generation in enumerate(self.grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if not determined[t][y][x]: if cell in ["0", "1"]: determined[t][y][x] = True else: variable, negated = variable_from_literal(cell) if t == 0: determined[t][y][x] = True determined_variables.add(variable) elif variable in determined_variables: determined[t][y][x] = True elif all(determined[t - 1][y + y_offset][x + x_offset] for x_offset in range(2) for y_offset in range(2) if x + x_offset in range(width) and y + y_offset in range(height)) and not \ self.ignore_transition[t][y][x]: determined[t][y][x] = True determined_variables.add(variable) if determined == determined_copy: break print_message("Done\n", 3, indent=indent) if all(flag for generation in determined for row in generation for flag in row): return True else: return False
def append(self, clause): dimacs_clause = [] clause = set(clause) if "1" in clause: return for literal in clause: if literal == "0": pass else: (variable, negated) = variable_from_literal(literal) # If we haven't seen it before then add it to the dictionary if variable not in self.dimacs_literal_from_variable: self.dimacs_literal_from_variable[variable] = str( self.number_of_variables + 1) self.number_of_variables += 1 elif negate(literal) in clause: return dimacs_clause.append( negate(self.dimacs_literal_from_variable[variable], negated, dimacs=True)) dimacs_clause.sort() dimacs_clause.append("0\n") self.clause_set.add(" ".join(dimacs_clause))
def substitute_solution(self, solution, indent=0): """Return a copy of the search_pattern with the solution substituted back into it""" grid = copy.deepcopy(self.grid) rule = copy.deepcopy(self.rule) background_grid = copy.deepcopy(self.background_grid) print_message('Substituting solution back into search grid...', 3, indent=indent) # Remove the first line that just says "SAT", and split into a list of literals solution = set(solution.split("\n")[1].split()) for t, generation in enumerate(grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell in ["0", "1"]: pass else: (CNF_variable, negated) = variable_from_literal(cell) if CNF_variable in self.clauses.dimacs_literal_from_variable: dimacs_variable = self.clauses.dimacs_literal_from_variable[CNF_variable] dimacs_literal = negate(dimacs_variable, negated, dimacs=True) if dimacs_literal in solution: grid[t][y][x] = "1" else: grid[t][y][x] = "0" else: grid[t][y][x] = "0" for t, generation in enumerate(background_grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell in ["0", "1"]: pass else: (CNF_variable, negated) = variable_from_literal(cell) if CNF_variable in self.clauses.dimacs_literal_from_variable: dimacs_variable = self.clauses.dimacs_literal_from_variable[CNF_variable] dimacs_literal = negate(dimacs_variable, negated, dimacs=True) if dimacs_literal in solution: background_grid[t][y][x] = "1" else: background_grid[t][y][x] = "0" else: background_grid[t][y][x] = "0" for transition, literal in rule.items(): if literal in ["0", "1"]: pass else: (CNF_variable, negated) = variable_from_literal(literal) if CNF_variable in self.clauses.dimacs_literal_from_variable: dimacs_variable = self.clauses.dimacs_literal_from_variable[CNF_variable] dimacs_literal = negate(dimacs_variable, negated, dimacs=True) if dimacs_literal in solution: rule[transition] = "1" else: rule[transition] = "0" else: rule[transition] = "0" print_message('Done\n', 3, indent=indent) return SearchPattern(grid, background_grid=background_grid, rule=rule, add_border=False)
def force_equal(self, argument_0, argument_1=None): if argument_1 is not None: assert isinstance(argument_0, str) and isinstance(argument_1, str), "force_equal arguments not understood" cell_pair_list = [(argument_0, argument_1)] elif argument_0 == []: return elif isinstance(argument_0[0], str): assert len(argument_0) == 2 and isinstance(argument_0[1], str), "force_equal arguments not understood" cell_pair_list = [argument_0] else: cell_pair_list = argument_0 replacement = {} replaces = {} for cell_0, cell_1 in cell_pair_list: while cell_0 not in ["0", "1"]: variable_0, negated_0 = variable_from_literal(cell_0) if variable_0 in replacement: cell_0 = negate(replacement[variable_0], negated_0) else: break while cell_1 not in ["0", "1"]: variable_1, negated_1 = variable_from_literal(cell_1) if variable_1 in replacement: cell_1 = negate(replacement[variable_1], negated_1) else: break if cell_0 != cell_1: if cell_0 == negate(cell_1): raise UnsatInPreprocessing elif cell_0 in ["0", "1"]: cell_0, cell_1 = cell_1, cell_0 variable_0, negated_0 = variable_from_literal(cell_0) cell_0, cell_1 = variable_0, negate(cell_1, negated_0) if cell_1 not in ["0", "1"]: variable_1, negated_1 = variable_from_literal(cell_1) if variable_1 not in replaces: replaces[variable_1] = [] if variable_0 in replaces: for variable in replaces[variable_0]: replacement_variable, replacement_negated = variable_from_literal(replacement[variable]) replacement[variable] = negate(cell_1, replacement_negated) if cell_1 not in ["0", "1"]: replaces[variable_1].append(variable) del replaces[variable_0] replacement[variable_0] = cell_1 if cell_1 not in ["0", "1"]: replaces[variable_1].append(variable_0) for t, generation in enumerate(self.grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell not in ["0", "1"]: variable, negated = variable_from_literal(cell) if variable in replacement: if replacement[variable] != variable: self.grid[t][y][x] = negate(replacement[variable], negated) for t, generation in enumerate(self.background_grid): for y, row in enumerate(generation): for x, cell in enumerate(row): if cell not in ["0", "1"]: variable, negated = variable_from_literal(cell) if variable in replacement: if replacement[variable] != variable: self.background_grid[t][y][x] = negate(replacement[variable], negated) for transition, literal in self.rule.items(): if literal not in ["0", "1"]: variable, negated = variable_from_literal(literal) if variable in replacement: if replacement[variable] != variable: self.rule[transition] = negate(replacement[variable], negated)
def number_of_cells(self): return len(set(variable_from_literal(cell) for generation in self.grid for row in generation for cell in row if cell not in ["0", "1"]))