示例#1
0
def string_from_file(file_name, indent = 0, verbosity = 0):
    """Read pattern file into string"""
    print_message('Reading file "' + file_name + '" ...', 3, indent = indent, verbosity = verbosity)
    with open(file_name, "r") as pattern_file:
        input_string = pattern_file.read()
    print_message('Done\n', 3, indent = indent, verbosity = verbosity)
    return input_string
示例#2
0
def solve(search_pattern,
          DIMACS_string,
          DIMACS_variables_from_CNF_list_variables,
          solver=None,
          parameters=None,
          timeout=None,
          save_dimacs=None,
          dry_run=None,
          indent=0,
          verbosity=0):
    print_message('Solving...', indent=indent, verbosity=verbosity)
    DIMACS_solution, time_taken = LLS_SAT_solvers.SAT_solve(
        DIMACS_string,
        solver=solver,
        parameters=parameters,
        timeout=timeout,
        save_dimacs=save_dimacs,
        dry_run=dry_run,
        indent=indent + 1,
        verbosity=verbosity)
    if DIMACS_solution not in ["UNSAT\n", "TIMEOUT\n", "DRYRUN\n"]:
        sat = "SAT"
        solution = search_pattern.substitute_solution(
            DIMACS_solution,
            DIMACS_variables_from_CNF_list_variables,
            indent=indent + 1,
            verbosity=verbosity)
    else:
        sat = DIMACS_solution[:-1]
        solution = None
    print_message('Done\n', indent=indent, verbosity=verbosity)
    return solution, sat, time_taken
示例#3
0
    def force_distinct(self, solution, determined = False, indent = 0, verbosity = 0):
        """Force search_pattern to have at least one differnence from given solution"""

        print_message("Forcing pattern to be different from solution...", 3, indent = indent, verbosity = verbosity)

        clause = []

        for t, generation in enumerate(self.grid):
            if t == 0 or not determined:
                for y, row in enumerate(generation):
                    for x, cell in enumerate(row):
                        other_cell = solution.grid[t][y][x]
                        assert other_cell in ["0", "1"], "Only use force_distinct against solved patterns"
                        if other_cell == "0":
                            clause.append(cell)
                        else:
                            clause.append(negate(cell))

        for transition, literal in self.rule.items():
            other_literal = solution.rule[transition]
            assert other_literal in ["0", "1"], "Only use force_distinct against solved patterns"
            if other_literal == "0":
                clause.append(literal)
            else:
                clause.append(negate(literal))
        self.clauses.append(clause)
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)
示例#4
0
def make_csv(grid,
             ignore_transition=None,
             rule=None,
             determined=None,
             indent=0,
             verbosity=0):
    """Turn a search pattern in list form into nicely formatted csv string"""

    print_message('Format: csv', 3, indent=indent, verbosity=verbosity)

    grid = copy.deepcopy(grid)
    if ignore_transition == None:
        ignore_transition = [[[False for cell in row] for row in generation]
                             for generation in grid]

    lengths = []
    for t, generation in enumerate(grid):
        for y, row in enumerate(generation):
            for x, cell in enumerate(row):
                if x != 0:
                    lengths.append(len(cell) + ignore_transition[t][y][x - 1])

    length_first_column = max(
        [max([len(row[0]) for row in generation]) for generation in grid])
    if len(lengths) > 0:
        length_other_columns = max(lengths)
    for t, generation in enumerate(grid):
        for y, row in enumerate(generation):
            for x, cell in enumerate(row):
                if x == 0:
                    grid[t][y][x] = " " * (length_first_column -
                                           len(cell)) + cell
                else:
                    grid[t][y][x] = " " * (length_other_columns - len(
                        cell) - ignore_transition[t][y][x - 1]) + grid[t][y][x]
                if ignore_transition[t][y][x]:
                    grid[t][y][x] += "'"

    csv_string = ""

    if rule != None:
        csv_string += "Rule = " + LLS_rules.rulestring_from_rule(rule) + "\n"

    csv_string += "\n".join(",".join(line) for line in grid[0])

    if not determined:
        csv_string += "\n\n" + "\n\n".join("\n".join(",".join(line)
                                                     for line in generation)
                                           for generation in grid[1:])

    return csv_string
示例#5
0
    def substitute_solution(self, solution, DIMACS_variables_from_CNF_list_variables, indent = 0, verbosity = 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)

        print_message('Substituting solution back into search grid...', 3, indent = indent, verbosity = verbosity)

        # Remove the first line that just says "SAT", and split into a list of literals
        solution = 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 DIMACS_variables_from_CNF_list_variables.has_key(CNF_variable):
                            DIMACS_variable = DIMACS_variables_from_CNF_list_variables[CNF_variable]

                            DIMACS_literal = negate(DIMACS_variable, negated)

                            if DIMACS_literal in solution:
                                grid[t][y][x] = "1"
                            else:
                                grid[t][y][x] = "0"
                        else:
                            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 DIMACS_variables_from_CNF_list_variables.has_key(CNF_variable):
                    DIMACS_variable = DIMACS_variables_from_CNF_list_variables[CNF_variable]

                    DIMACS_literal = negate(DIMACS_variable, negated)

                    if DIMACS_literal in solution:
                        rule[transition] = "1"
                    else:
                        rule[transition] = "0"
                else:
                    rule[transition] = "0"

        print_message('Done\n', 3, indent = indent, verbosity = verbosity)

        return SearchPattern(grid, rule = rule)
示例#6
0
    def force_change(self, t_0, t_1, indent = 0, verbosity = 0):
        """Adds clauses forcing at least one cell to change between specified generations"""

        print_message("Forcing at least one cell to change between generations " + str(t_0) + " and " + str(t_1) + " ...", 3, indent = indent, verbosity = verbosity)

        generation_0 = self.grid[t_0]
        generation_1 = self.grid[t_1]

        clause = []
        clauses = []

        for y, rows in enumerate(zip(generation_0,generation_1)):
            for x, cells in enumerate(zip(*rows)):
                cells_equal = ("x" + str(x) +
                               "y" + str(y) +
                               "is_equal_at" +
                               "t" + str(t_0) +
                               "and" +
                               "t" + str(t_1))
                clauses.append(implies(cells, cells_equal))
                clauses.append(implies(map(negate, cells), cells_equal))
                clause.append(negate(cells_equal))

        clauses.append(clause)
        print_message("Number of clauses used: " + str(len(clauses)), 3, indent = indent + 1, verbosity = verbosity)
        self.clauses += clauses
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)
示例#7
0
    def force_nonempty(self, indent = 0, verbosity = 0):
        """Adds clauses forcing at least one cell to be live in first generation"""

        print_message("Forcing at least one cell to be live in first generation...", 3, indent = indent, verbosity = verbosity)

        self.clauses += [[cell for row in self.grid[0] for cell in row]]
        print_message("Number of clauses used: 1", 3, indent = indent + 1, verbosity = verbosity)
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)
示例#8
0
    def standardise_varaibles_names(self, indent = 0, verbosity = 0):
        print_message("Standardising variable names...", 3, indent = indent, verbosity = verbosity)

        #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.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 not standard_variables_from_input_variables.has_key(variable):
                            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 clauses
        for clause_number, clause in enumerate(self.clauses):
            for literal_number, literal in enumerate(clause):
                if literal not in ["0", "1"]:
                    (variable, negated) = variable_from_literal(literal)
                    if not standard_variables_from_input_variables.has_key(variable):
                        standard_variables_from_input_variables[variable] = negate("c" + str(current_variable_number),negated)
                        current_variable_number += 1
                    self.clauses[clause_number][literal_number] = 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 not standard_variables_from_input_variables.has_key(variable):
                    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, verbosity = verbosity)
示例#9
0
def make_rle(grid, rule=None, determined=None, indent=0, verbosity=0):
    """Turn a search pattern into nicely formatted string form"""

    print_message('Format: RLE', 3, indent=indent, verbosity=verbosity)

    grid = copy.deepcopy(grid)

    width = len(grid[0][0])
    height = len(grid[0])

    for t, generation in enumerate(grid):
        for y, row in enumerate(generation):
            for x, cell in enumerate(row):
                assert cell in ["0",
                                "1"], "Cell not equal to 0 or 1 in RLE format"
                if cell == "0":
                    grid[t][y][x] = "b"
                elif cell == "1":
                    grid[t][y][x] = "o"

    rle_string = "x = " + str(width) + ", y = " + str(height)

    if rule != None:
        rle_string += ", rule = " + LLS_rules.rulestring_from_rule(rule)

    rle_string += "\n"

    rle_string += "$\n".join("".join(line) for line in grid[0])

    rle_string += "!"

    if not determined:
        rle_string += "\n\nOther generations:\n"
        rle_string += "\n\n".join("$\n".join("".join(line)
                                             for line in generation)
                                  for generation in grid[1:])

    return rle_string
示例#10
0
    def force_symmetry(self, symmetry, indent = 0, verbosity = 0):
        """Changes the grid to enforce the specified symmetry"""

        symmetry = symmetry.upper()

        if symmetry == "C1":
            return None

        print_message("Enforcing symmetry...", 3, indent = indent, verbosity = verbosity)

        symmetries = ["C1","C2","C4","D2-","D2/","D2|","D2\\","D4+","D4X","D8"]
        assert symmetry in symmetries, "Specified symmetry is unknown"

        width = len(self.grid[0][0])
        height = len(self.grid[0])

        if symmetry in ["C4","D2/","D2\\","D4X","D8"]:
            assert width == height, "Pattern must have width = height for the given symmetry"

        to_force_equal = []
        for t, generation in enumerate(self.grid):
            for y, row in enumerate(generation):
                for x, cell in enumerate(row):
                    if symmetry == "C2":
                        to_force_equal.append((self.grid[t][y][x], self.grid[t][height-y-1][width-x-1]))
                    if symmetry == "C4":
                        to_force_equal.append((self.grid[t][y][x], self.grid[t][height-x-1][y]))
                    if symmetry in ["D2-","D4+","D8"]:
                        to_force_equal.append((self.grid[t][y][x], self.grid[t][height-y-1][x]))
                    if symmetry in ["D2/","D4X","D8"]:
                        to_force_equal.append((self.grid[t][y][x], self.grid[t][height-x-1][width-y-1]))
                    if symmetry in ["D2|","D4+"]:
                        to_force_equal.append((self.grid[t][y][x], self.grid[t][y][width-x-1]))
                    if symmetry in ["D2\\","D4X"]:
                        to_force_equal.append((self.grid[t][y][x], self.grid[t][x][y]))
        self.force_equal(to_force_equal)
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)
示例#11
0
 def optimise(self, grid_changed = True, clauses_changed = True, indent = 0, verbosity = 0):
     print_message("Optimising search pattern...", 3, indent = indent, verbosity = verbosity)
     number_of_improvements = 0
     while grid_changed or clauses_changed:
         number_of_improvements += 1
         print_message("Improving search pattern (Pass " + str(number_of_improvements) + ") ...", 3, indent = indent + 1, verbosity = verbosity)
         grid_changed0 = False
         clauses_changed0 = False
         if grid_changed:
             grid_changed1, clauses_changed1, _ = self.improve_grid(indent = indent + 2, verbosity = verbosity)
             grid_changed0 = grid_changed0 or grid_changed1
             clauses_changed0 = clauses_changed0 or clauses_changed1
         if clauses_changed:
             grid_changed1, clauses_changed1, _ = self.improve_clauses(indent = indent + 2, verbosity = verbosity)
             grid_changed0 = grid_changed0 or grid_changed1
             clauses_changed0 = clauses_changed0 or clauses_changed1
         grid_changed = grid_changed0
         clauses_changed = clauses_changed0
         print_message("Done\n", 3, indent = indent + 1, verbosity = verbosity)
     self.standardise_varaibles_names()
     print_message("Done\n", 3, indent = indent, verbosity = verbosity)
示例#12
0
    def force_period(self, period, x_translate = None, y_translate = None, indent = 0, verbosity = 0):

        if period != None:

            width = len(self.grid[0][0])
            height = len(self.grid[0])
            duration = len(self.grid)

            if x_translate is None:
                x_translate = 0
            if y_translate is None:
                y_translate = 0
            if (x_translate, y_translate) == (0, 0):
                if period == 1:
                    print_message("Forcing pattern to be a still life...", 3, indent = indent, verbosity = verbosity)
                else:
                    print_message("Forcing pattern to have period " + str(period) + " ...", 3, indent = indent, verbosity = verbosity)
            else:
                print_message("Forcing pattern to move with speed (" + str(x_translate) + ", " + str(y_translate) + ")c/" + str(period) + " ...", 3, indent = indent, verbosity = verbosity)

            to_force_equal = []
            for t, generation in enumerate(self.grid):
                for y, row in enumerate(generation):
                    for x, cell in enumerate(row):
                        if t - period in range(duration):
                            if x - x_translate in range(width) and y - y_translate in range(height):
                                to_force_equal.append((self.grid[t][y][x], self.grid[t - period][y - y_translate][x - x_translate]))
                            else:
                                to_force_equal.append((self.grid[t][y][x], "0"))
                        if t + period in range(duration):
                            if x + x_translate in range(width) and y + y_translate in range(height):
                                to_force_equal.append((self.grid[t][y][x], self.grid[t + period][y + y_translate][x + x_translate]))
                            else:
                                to_force_equal.append((self.grid[t][y][x], "0"))

            self.force_equal(to_force_equal)
            print_message("Done\n", 3, indent = indent, verbosity = verbosity)
示例#13
0
    def make_string(self, pattern_output_format = None, determined = None, indent = 0, verbosity = 0):
        if pattern_output_format == None:
            pattern_output_format = "rle"

        print_message('Formatting output...', 3, indent = indent, verbosity = verbosity)

        assert pattern_output_format in ["rle","csv"], "Format not recognised"

        if not determined:
            print_message('(Including all generations)', 3, indent = indent, verbosity = verbosity)

        if pattern_output_format == "rle":
            output_string = LLS_formatting.make_rle(self.grid, rule = self.rule, determined = determined, indent = indent + 1, verbosity = verbosity)
        elif pattern_output_format == "csv":
            output_string = LLS_formatting.make_csv(self.grid, ignore_transition = self.ignore_transition, rule = self.rule, determined = determined, indent = indent + 1, verbosity = verbosity)

        print_message('Done\n', 3, indent = indent, verbosity = verbosity)

        return output_string
示例#14
0
    def improve_grid(self, indent = 0, verbosity = 0):
        print_message("Improving grid...", 3, indent = indent, verbosity = verbosity)
        parents_dict = {}
        to_force_equal = []
        grid_changed0 = False
        outer_totalistic = LLS_rules.outer_totalistic(self.rule)
        for t, generation in enumerate(self.grid):
            if t > 0:
                for y, row in enumerate(generation):
                    for x, cell in enumerate(row):
                        predecessor_cell = self.grid[t - 1][y][x]
                        neighbours = neighbours_from_coordinates(self.grid, x, y, t)

                        if not self.ignore_transition[t][y][x]:
                            parents = [predecessor_cell] + list(LLS_rules.sort_neighbours(neighbours, outer_totalistic))
                            parents_string = str(parents)
                            if parents_dict.has_key(parents_string):
                                self.grid[t][y][x] = parents_dict[parents_string]
                                if self.grid[t][y][x] != cell:
                                    grid_changed0 = True
                                to_force_equal.append((parents_dict[parents_string],cell))
                                self.ignore_transition[t][y][x] = True
                            elif all(parent in ["0", "1"] for parent in parents):
                                BS_letter = ["B", "S"][["0", "1"].index(predecessor_cell)]
                                transition = LLS_rules.transition_from_cells(neighbours)
                                child = self.rule[BS_letter + transition]
                                self.grid[t][y][x] = child
                                if self.grid[t][y][x] != cell:
                                    grid_changed0 = True
                                to_force_equal.append((cell, child))
                                self.ignore_transition[t][y][x] = True
                                parents_dict[parents_string] = child
                            else:
                                parents_dict[parents_string] = cell
                                variables = []
                                for literal in [cell, predecessor_cell] + neighbours:
                                    if literal not in ["0", "1"]:
                                        variable, _ = variable_from_literal(literal)
                                        if variable not in variables:
                                            variables.append(variable)
                                booleans = [False, True]

                                transition_redundant = True

                                variables_true = set(range(len(variables)))
                                variables_false = set(range(len(variables)))
                                variables_equal = set(itertools.combinations(range(len(variables)),2))
                                variables_unequal = set(itertools.combinations(range(len(variables)),2))

                                for variables_alive in itertools.product(booleans, repeat=len(variables)):
                                    dead_literals = map(negate, variables, variables_alive)
                                    if cell == "0":
                                        cell_alive = False
                                    elif cell not in dead_literals:
                                        cell_alive = True
                                    else:
                                        cell_alive = False

                                    if predecessor_cell == "0":
                                        predecessor_cell_alive = False
                                    elif predecessor_cell not in dead_literals:
                                        predecessor_cell_alive = True
                                    else:
                                        predecessor_cell_alive = False

                                    neighbours_alive = []
                                    for neighbour in neighbours:
                                        if neighbour == "0":
                                            neighbours_alive.append(False)
                                        elif neighbour not in dead_literals:
                                            neighbours_alive.append(True)
                                        else:
                                            neighbours_alive.append(False)

                                    BS_letter = "S" if predecessor_cell_alive else "B"
                                    transition = LLS_rules.transition_from_cells(neighbours_alive)
                                    transition_variable = self.rule[BS_letter + transition]


                                    if (transition_variable not in ["0", "1"]) or (transition_variable == "0" and not cell_alive) or (transition_variable == "1" and cell_alive):
                                        to_remove = []
                                        for variable_number in variables_true:
                                            if not variables_alive[variable_number]:
                                                to_remove.append(variable_number)
                                        variables_true.difference_update(to_remove)

                                        to_remove = []
                                        for variable_number in variables_false:
                                            if variables_alive[variable_number]:
                                                to_remove.append(variable_number)
                                        variables_false.difference_update(to_remove)

                                        to_remove = []
                                        for variable_number_0, variable_number_1 in variables_equal:
                                            if variables_alive[variable_number_0] != variables_alive[variable_number_1]:
                                                to_remove.append((variable_number_0, variable_number_1))
                                        variables_equal.difference_update(to_remove)

                                        to_remove = []
                                        for variable_number_0, variable_number_1 in variables_unequal:
                                            if variables_alive[variable_number_0] == variables_alive[variable_number_1]:
                                                to_remove.append((variable_number_0, variable_number_1))
                                        variables_unequal.difference_update(to_remove)

                                    if (transition_variable not in ["0", "1"]) or (transition_variable == "0" and cell_alive) or (transition_variable == "1" and not cell_alive):
                                        transition_redundant = False
                                if transition_redundant:
                                    self.ignore_transition[t][y][x] = True
                                for variable_number in variables_true:
                                    to_force_equal.append((variables[variable_number], "1"))
                                for variable_number in variables_false:
                                    to_force_equal.append((variables[variable_number], "0"))
                                for variable_number_0, variable_number_1 in variables_equal:
                                    to_force_equal.append((variables[variable_number_0], variables[variable_number_1]))
                                for variable_number_0, variable_number_1 in variables_unequal:
                                    to_force_equal.append((variables[variable_number_0], negate(variables[variable_number_1])))
        grid_changed1, clauses_changed, rule_changed = self.force_equal(to_force_equal)
        grid_changed = grid_changed0 or grid_changed1
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)

        return grid_changed, clauses_changed, rule_changed
示例#15
0
def rule_from_rulestring(rulestring, indent = 0, verbosity = 0):

    if rulestring == None:
        return None
    else:

        rule = {}

        rulestring = rulestring.strip()
        original_rulestring = rulestring

        partial_flag = False


        if rulestring[0] == "{":
            rule_unsanitized = ast.literal_eval(rulestring)
            for BS_letter in "BS":
                for number_of_neighbours in "012345678":
                    for character in possible_transitions[number_of_neighbours]:
                        literal = LLS_formatting.standard_form_literal(str(rule_unsanitized[BS_letter + number_of_neighbours + character]))
                        assert literal[-1] not in ['\xe2\x80\x99', "'"], "Can't ignore transition in rule"
                        rule[BS_letter + number_of_neighbours + character] = literal
            return rule
        elif rulestring[0] in ["p", "P"]:
            partial_flag = True
            if len(rulestring) == 1:
                rulestring = "B012345678/S012345678"
            else:
                rulestring = rulestring[1:]

        rulestring = re.sub(' ', '', rulestring.upper())

        rulestrings = re.split("/", rulestring)

        if len(rulestrings) == 1:
            assert "B" in rulestring or "S" in rulestring, 'Rule sting not recognised (no "B" or "S")'
            B_position = rulestring.find("B")
            S_position = rulestring.find("S")
            rulestring = rulestring.strip("BS")
            rulestrings = re.split("[BS]*", rulestring)
            assert len(rulestrings) < 3, "Rule sting not recognised"
            if B_position > S_position:
                birth_string = rulestrings[1] if len(rulestrings) == 2 else ""
                survival_string = rulestrings[0]
            else:
                birth_string = rulestrings[0]
                survival_string = rulestrings[1] if len(rulestrings) == 2 else ""
        else:
            assert len(rulestrings) == 2, 'Rule sting not recognised (too many "/"s)'
            if "S" in rulestrings[0] or "B" in rulestrings[1]:
                birth_string = rulestrings[1]
                survival_string = rulestrings[0]
            else:
                birth_string = rulestrings[0]
                survival_string = rulestrings[1]

        assert "S" not in birth_string and "B" not in survival_string, "Rule sting not recognised"

        birth_string = re.sub('B', '', birth_string).lower()
        survival_string = re.sub('S', '', survival_string).lower()

        assert (birth_string == "" or birth_string[0] in "012345678") and (survival_string == "" or survival_string[0] in "012345678"), "Rule sting not recognised"

        if partial_flag:
            variable_number = 0

        for BS_letter, rulestring in zip(["B", "S"], [birth_string, survival_string]):
            transitions = []
            previous_number = 0

            if rulestring != "":
                for position in range(1,len(rulestring)):
                    if rulestring[position] in "012345678":
                        transitions.append(rulestring[previous_number:position])
                        previous_number = position
                transitions.append(rulestring[previous_number:])

            for transition in transitions:
                number_of_neighbours = transition[0]
                if not partial_flag:
                    if len(transition) == 1:
                        for character in possible_transitions[number_of_neighbours]:
                            rule[BS_letter + number_of_neighbours + character] = "1"
                    elif transition[1] == "-":
                        banned_characters = transition[2:]
                        assert all(character in possible_transitions[number_of_neighbours] for character in banned_characters), "Unrecognized character"
                        for character in possible_transitions[number_of_neighbours]:
                            if character in banned_characters:
                                rule[BS_letter + number_of_neighbours + character] = "0"
                            else:
                                rule[BS_letter + number_of_neighbours + character] = "1"
                    else:
                        characters = transition[1:]
                        assert all(character in possible_transitions[number_of_neighbours] for character in characters), "Unrecognized character"
                        for character in possible_transitions[number_of_neighbours]:
                            if character in characters:
                                rule[BS_letter + number_of_neighbours + character] = "1"
                            else:
                                rule[BS_letter + number_of_neighbours + character] = "0"
                else:
                    if len(transition) == 1:
                        for character in possible_transitions[number_of_neighbours]:
                            rule[BS_letter + number_of_neighbours + character] = "rule_variable_" + str(variable_number)
                            variable_number += 1
                    else:
                        characters = transition[1:]
                        if "-" in characters:
                            characters, banned_characters = re.split("-", characters)
                        else:
                            banned_characters = ""

                        for character in possible_transitions[number_of_neighbours]:
                            if character in characters:
                                rule[BS_letter + number_of_neighbours + character] = "1"
                            elif character in banned_characters:
                                rule[BS_letter + number_of_neighbours + character] = "0"
                            else:
                                rule[BS_letter + number_of_neighbours + character] = "rule_variable_" + str(variable_number)
                                variable_number += 1


            for number_of_neighbours in "012345678":
                if not rule.has_key(BS_letter + number_of_neighbours + "c"):
                    for character in possible_transitions[number_of_neighbours]:
                         rule[BS_letter + number_of_neighbours + character] = "0"

        new_rulestring = rulestring_from_rule(rule)
        if original_rulestring != new_rulestring:
            print_message("Rulestring parsed as: " + new_rulestring,3, indent = indent, verbosity = verbosity)

        return rule
示例#16
0
def use_solver(solver,
               file_name,
               parameters=None,
               timeout=None,
               indent=0,
               verbosity=0):

    if parameters != None:
        parameter_list = parameters.strip(" ").split(" ")
    else:
        parameter_list = []

    solver_path = sys.path[0] + "/solvers/" + solver

    if solver in ["minisat", "MapleCOMSPS", "MapleCOMSPS_LRB", "riss"]:
        command = [solver_path, file_name, "temp_SAT_solver_output"
                   ] + parameter_list
    elif solver in ["lingeling", "plingeling", "treengeling"]:
        command = [solver_path, file_name] + parameter_list
    elif solver in ["glucose", "glucose-syrup"]:
        command = [solver_path, file_name, "-model"] + parameter_list
    else:
        assert False, "Solver not recognised"

    solver_process = subprocess.Popen(command,
                                      stdout=subprocess.PIPE,
                                      stdin=subprocess.PIPE,
                                      stderr=subprocess.PIPE)

    timeout_flag = [
        False
    ]  #We want the flag to be mutable, so we put it into a little box.

    def timeout_function(solver_process, timeout_flag):
        solver_process.kill()
        timeout_flag[0] = "TIMEOUT"

    timeout_timer = threading.Timer(timeout, timeout_function,
                                    [solver_process, timeout_flag])

    print_message('Solving with "' + solver + '" ... (Start time: ' +
                  time.ctime() + ")",
                  3,
                  indent=indent,
                  verbosity=verbosity)

    try:
        start_time = time.time()
        timeout_timer.start()
        out, error = solver_process.communicate()
    except KeyboardInterrupt:
        solver_process.kill()
        timeout_flag[0] = "SIGINT"
    finally:
        timeout_timer.cancel()
        time_taken = time.time() - start_time

    if not timeout_flag[0]:
        print_message('Done\n', 3, indent=indent, verbosity=verbosity)

        print_message('Formatting SAT solver output...',
                      3,
                      indent=indent,
                      verbosity=verbosity)

        if solver in ["minisat", "MapleCOMSPS", "MapleCOMSPS_LRB", "riss"]:
            solution = LLS_files.string_from_file("temp_SAT_solver_output",
                                                  indent=indent + 1,
                                                  verbosity=verbosity)
            print_message('Removing SAT solver output file...',
                          3,
                          indent=indent + 1,
                          verbosity=verbosity)
            os.remove("temp_SAT_solver_output")
            print_message('Done\n', 3, indent=indent + 1, verbosity=verbosity)
        elif solver in ["lingeling", "plingeling", "treengeling"]:
            solution = out.split("\ns ")[1].split("\nc")[0].split("\nv ")
            solution = solution[0] + "\n" + " ".join(solution[1:])
        elif solver in ["glucose", "glucose-syrup"]:
            try:
                solution = out.split("\ns ")[1]
                solution = re.sub("s ", "", solution)
                solution = re.sub("v ", "", solution)
            except IndexError:
                solution = "UNSAT\n"

        if solver == "MapleCOMSPS_LRB":
            if solution == "":
                solution = "UNSAT\n"
        if solver == "riss":
            solution = re.sub("s ", "", solution)
            solution = re.sub("v ", "", solution)
        if solution == "UNSATISFIABLE\n":
            solution = "UNSAT\n"

        print_message("SAT solver output:",
                      3,
                      indent=indent + 1,
                      verbosity=verbosity)
        print_message(out, 3, indent=indent + 2, verbosity=verbosity)
        print_message('Error (if any): "' + error + '"',
                      3,
                      indent=indent + 1,
                      verbosity=verbosity)
        print_message('Time taken: ' + str(time_taken),
                      3,
                      indent=indent + 1,
                      verbosity=verbosity)
        print_message('Done\n', 3, indent=indent, verbosity=verbosity)

    else:
        print_message(
            'Timed out\n', 3, indent=indent, verbosity=verbosity
        )  #TODO: How to capture output from SAT solver after killing it?
        solution = "TIMEOUT\n"

    return solution, time_taken
示例#17
0
def SAT_solve(DIMACS_string,
              solver=None,
              parameters=None,
              timeout=None,
              save_dimacs=None,
              dry_run=None,
              indent=0,
              verbosity=0):
    """Solve the given DIMACS problem, using the specified SAT solver"""
    print_message('Preparing SAT solver input...',
                  3,
                  indent=indent,
                  verbosity=verbosity)
    solvers = [
        "minisat", "MapleCOMSPS", "MapleCOMSPS_LRB", "riss", "glucose",
        "glucose-syrup", "lingeling", "plingeling", "treengeling"
    ]
    try:
        if solver is None:
            solver = "glucose-syrup"  # Default solver
        elif int(solver) in range(len(solvers)):
            solver = solvers[solver]  # Allow solver to be specified by number
    except ValueError:
        pass

    assert solver in solvers, "Solver not found"

    if isinstance(save_dimacs, basestring):
        dimacs_file = save_dimacs
    else:
        dimacs_file = "lls_dimacs.cnf"
        file_number = 0
        while os.path.isfile(dimacs_file):
            file_number += 1
            dimacs_file = "lls_dimacs" + str(file_number) + ".cnf"

    # The solvers prefer their input as a file, so write it out
    LLS_files.file_from_string(dimacs_file,
                               DIMACS_string,
                               indent=indent + 1,
                               verbosity=verbosity)

    print_message('Done\n', 3, indent=indent, verbosity=verbosity)
    if not dry_run:
        solution, time_taken = use_solver(solver,
                                          dimacs_file,
                                          parameters=parameters,
                                          timeout=timeout,
                                          indent=indent,
                                          verbosity=verbosity)
    else:
        solution = "DRYRUN\n"
        time_taken = None

    if save_dimacs == None:
        print_message('Removing DIMACS file...',
                      3,
                      indent=indent,
                      verbosity=verbosity)
        try:
            os.remove(dimacs_file)
        except OSError as e:
            if e.errno == errno.ENOENT:
                print_message('DIMACS file "' + dimacs_file + '" not found',
                              3,
                              indent=indent + 1,
                              verbosity=verbosity)
            else:
                raise
        print_message('Done\n', 3, indent=indent, verbosity=verbosity)

    return solution, time_taken
示例#18
0
    def improve_clauses(self, indent = 0, verbosity = 0):

        print_message("Improving clause list...", 3, indent = indent, verbosity = verbosity)

        print_message('Tidying clauses...', 3, indent = indent + 1, verbosity = verbosity)
        clauses_to_remove = set()
        to_force_equal = []
        clauses_seen_so_far = set()
        clauses_changed0 = False
        for clause_number, clause in enumerate(self.clauses):
            remove_flag = False
            if "1" in clause:
                remove_flag = True
            else:
                for literal in clause:
                    if negate(literal) in clause:
                        remove_flag = True
            if remove_flag:
                clauses_to_remove.add(clause_number)
            else:
                starting_length = len(self.clauses[clause_number])
                self.clauses[clause_number] = [literal for literal in sorted(list(set(clause))) if literal != "0"]
                number_of_literals = len(self.clauses[clause_number])
                if starting_length != number_of_literals:
                    clauses_changed0 = True
                if number_of_literals == 1:
                    to_force_equal.append((self.clauses[clause_number][0],"1"))
                elif number_of_literals == 2:
                    if str(sorted([negate(self.clauses[clause_number][0]), negate(self.clauses[clause_number][1])])) in clauses_seen_so_far:
                        to_force_equal.append((self.clauses[clause_number][0],negate(self.clauses[clause_number][1])))
                    elif str(sorted([self.clauses[clause_number][0], negate(self.clauses[clause_number][1])])) in clauses_seen_so_far:
                        to_force_equal.append((self.clauses[clause_number][0],"1"))
                    elif str(sorted([negate(self.clauses[clause_number][0]), self.clauses[clause_number][1]])) in clauses_seen_so_far:
                        to_force_equal.append((self.clauses[clause_number][1],"1"))
                    else:
                        clauses_seen_so_far.add(str(self.clauses[clause_number]))
        if clauses_to_remove:
            clauses_changed0 = True
        self.clauses = [clause for clause_number, clause in enumerate(self.clauses) if clause_number not in clauses_to_remove]
        print_message('Done\n', 3, indent = indent + 1, verbosity = verbosity)

        print_message('Removing duplicate clauses...', 3, indent = indent + 1, verbosity = verbosity)
        seen = set()
        temporary_list = []
        for clause in self.clauses:
            clause.sort()
            clause_string = str(clause)
            if clause_string not in seen:
                seen.add(clause_string)
                temporary_list.append(clause)
            else:
                clauses_changed0 = True
        self.clauses = temporary_list
        print_message('Done\n', 3, indent = indent + 1, verbosity = verbosity)

        print_message('Making deductions...', 3, indent = indent + 1, verbosity = verbosity)
        grid_changed, clauses_changed1, rule_changed = self.force_equal(to_force_equal)
        print_message('Done\n', 3, indent = indent + 1, verbosity = verbosity)
        clauses_changed = clauses_changed0 or clauses_changed1
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)

        return grid_changed, clauses_changed, rule_changed
示例#19
0
def preprocess(search_pattern,
               symmetry="C1",
               period=None,
               x_translate=0,
               y_translate=0,
               force_movement=False,
               method=None,
               force_at_most=False,
               force_at_least=False,
               force_change=[],
               force_nonempty=False,
               force_evolution=True,
               indent=0,
               verbosity=0):
    print_message('Preprocessing...', indent=indent, verbosity=verbosity)
    search_pattern.force_symmetry(symmetry,
                                  indent=indent + 1,
                                  verbosity=verbosity)
    search_pattern.force_period(period,
                                x_translate,
                                y_translate,
                                indent=indent + 1,
                                verbosity=verbosity)
    if force_nonempty:
        search_pattern.force_nonempty(indent=indent + 1, verbosity=verbosity)
    if force_movement:
        search_pattern.force_movement(indent=indent + 1, verbosity=verbosity)
    for t_0, t_1 in force_change:
        search_pattern.force_change(t_0,
                                    t_1,
                                    indent=indent + 1,
                                    verbosity=verbosity)
    for arguments in force_at_least:
        amount, ts = arguments[0], arguments[1:]
        if ts == []:
            ts = [0]
        if len(ts) == 1:
            print_message('Enforcing at least ' + str(amount) +
                          ' cells in generation ' + str(ts[0]) + ' ...',
                          3,
                          indent=indent + 1,
                          verbosity=verbosity)
        else:
            print_message('Enforcing at least ' + str(amount) +
                          ' cells in generations ' + str(ts) + ' ...',
                          3,
                          indent=indent + 1,
                          verbosity=verbosity)
        literals = []
        literals = [
            literal for t in ts for row in search_pattern.grid[t]
            for literal in row
        ]
        search_pattern.force_at_least(literals,
                                      amount,
                                      indent=indent + 1,
                                      verbosity=verbosity)
        print_message('Done\n', 3, indent=indent + 1, verbosity=verbosity)
    for arguments in force_at_most:
        amount, ts = arguments[0], arguments[1:]
        if ts == []:
            ts = [0]
        if len(ts) == 1:
            print_message('Enforcing at most ' + str(amount) +
                          ' cells in generation ' + str(ts[0]) + ' ...',
                          3,
                          indent=indent + 1,
                          verbosity=verbosity)
        else:
            print_message('Enforcing at most ' + str(amount) +
                          ' cells in generations ' + str(ts) + ' ...',
                          3,
                          indent=indent + 1,
                          verbosity=verbosity)
        literals = [
            literal for t in ts for row in search_pattern.grid[t]
            for literal in row
        ]
        search_pattern.force_at_most(literals,
                                     amount,
                                     indent=indent + 1,
                                     verbosity=verbosity)
        print_message('Done\n', 3, indent=indent + 1, verbosity=verbosity)
    search_pattern.optimise(indent=indent + 1, verbosity=verbosity)
    if force_evolution:
        search_pattern.force_evolution(method=method,
                                       indent=indent + 1,
                                       verbosity=verbosity)
        search_pattern.optimise(grid_changed=False,
                                clauses_changed=True,
                                indent=indent + 1,
                                verbosity=verbosity)
    print_message("Search pattern optimised to:\n" +
                  search_pattern.make_string(pattern_output_format="csv") +
                  "\n",
                  3,
                  indent=indent + 1,
                  verbosity=verbosity)
    DIMACS_string, DIMACS_variables_from_CNF_list_variables, number_of_variables, number_of_clauses = LLS_DIMACS.DIMACS_from_CNF_list(
        search_pattern.clauses, indent=indent + 1, verbosity=verbosity)
    number_of_cells = search_pattern.number_of_cells()
    print_message('Done\n', indent=indent, verbosity=verbosity)
    return DIMACS_string, DIMACS_variables_from_CNF_list_variables, number_of_variables, number_of_clauses, number_of_cells
示例#20
0
def preprocess_solve_and_postprocess(search_pattern,
                                     symmetry="C1",
                                     period=None,
                                     x_translate=0,
                                     y_translate=0,
                                     force_movement=False,
                                     solver=None,
                                     parameters=None,
                                     timeout=None,
                                     save_dimacs=None,
                                     method=None,
                                     force_at_most=[],
                                     force_at_least=[],
                                     force_change=[],
                                     force_nonempty=False,
                                     force_evolution=True,
                                     dry_run=False,
                                     number_of_solutions=None,
                                     pattern_output_format="rle",
                                     output_file_name=None,
                                     indent=0,
                                     verbosity=0):
    (solution, sat, number_of_cells, number_of_variables, number_of_clauses,
     active_width, active_height, active_duration,
     time_taken) = preprocess_and_solve(search_pattern,
                                        symmetry=symmetry,
                                        period=period,
                                        x_translate=x_translate,
                                        y_translate=y_translate,
                                        force_movement=force_movement,
                                        solver=solver,
                                        parameters=parameters,
                                        timeout=timeout,
                                        save_dimacs=save_dimacs,
                                        method=method,
                                        force_at_most=force_at_most,
                                        force_at_least=force_at_least,
                                        force_change=force_change,
                                        force_nonempty=force_nonempty,
                                        force_evolution=force_evolution,
                                        dry_run=dry_run,
                                        indent=indent,
                                        verbosity=verbosity)
    determined = search_pattern.deterministic()
    solutions = []
    if sat == "SAT":
        solutions.append(solution)
        output_string = solution.make_string(
            pattern_output_format=pattern_output_format,
            determined=determined,
            indent=indent,
            verbosity=verbosity)
    else:
        output_string = ["Unsatisfiable", "Timed Out",
                         "Dry run"][["UNSAT", "TIMEOUT", "DRYRUN"].index(sat)]

    print_message(output_string + "\n", 1, indent=indent, verbosity=verbosity)
    if output_file_name:
        print_message('Writing to output file...',
                      indent=indent,
                      verbosity=verbosity)
        LLS_files.append_to_file_from_string(output_file_name,
                                             output_string,
                                             indent=indent + 1,
                                             verbosity=verbosity)
        print_message('Done\n', indent=indent, verbosity=verbosity)

    if number_of_solutions and sat == "SAT" and not dry_run:
        if number_of_solutions != "Infinity":
            number_of_solutions = int(number_of_solutions)
            enough_solutions = (len(solutions) >= number_of_solutions)
        else:
            enough_solutions = False
        while sat == "SAT" and not enough_solutions:
            search_pattern.force_distinct(solution, determined=determined)
            (solution, sat, _, _, _, _, _, _,
             extra_time_taken) = preprocess_and_solve(search_pattern,
                                                      solver=solver,
                                                      parameters=parameters,
                                                      timeout=timeout,
                                                      method=method,
                                                      force_evolution=False,
                                                      indent=indent,
                                                      verbosity=verbosity)
            time_taken += extra_time_taken
            if sat == "SAT":
                solutions.append(solution)
                output_string = solution.make_string(
                    pattern_output_format=pattern_output_format,
                    determined=determined,
                    indent=indent,
                    verbosity=verbosity)
                if verbosity == 1:
                    print_message("", 1, indent=indent, verbosity=verbosity)
            else:
                output_string = ["Unsatisfiable", "Timed Out",
                                 "Dry run"][["UNSAT", "TIMEOUT",
                                             None].index(sat)]
            print_message(output_string + "\n",
                          1,
                          indent=indent,
                          verbosity=verbosity)
            if output_file_name:
                print_message('Writing output file...',
                              indent=indent,
                              verbosity=verbosity)
                LLS_files.append_to_file_from_string(output_file_name,
                                                     output_string,
                                                     indent=indent + 1,
                                                     verbosity=verbosity)
                print_message('Done\n', indent=indent, verbosity=verbosity)
            if number_of_solutions != "Infinity":
                enough_solutions = (len(solutions) >= number_of_solutions)
        sat = "SAT"
        print_message('Total solver time: ' + str(time_taken),
                      indent=indent,
                      verbosity=verbosity)

    return solutions, sat, number_of_cells, number_of_variables, number_of_clauses, active_width, active_height, active_duration, time_taken
示例#21
0
def DIMACS_from_CNF_list(clauses, indent=0, verbosity=0):
    """Convert CNF list-of-lists to DIMACS format"""

    clauses_copy = copy.deepcopy(clauses)

    print_message("Converting to DIMACS format...",
                  3,
                  indent=indent,
                  verbosity=verbosity)

    print_message("Subsituting in DIMACS variable names...",
                  3,
                  indent=indent + 1,
                  verbosity=verbosity)

    # In DIMACS format variables are called "1", "2", ... . So we will rename
    # all our variables. This keeps track of which numbers we've used
    numbers_used = 0

    # We'll also build a dictionary of which of our old variables recieves
    # which new name
    DIMACS_variables_from_CNF_list_variables = {}
    for clause_number, clause in enumerate(clauses_copy):
        for literal_number, literal in enumerate(clause):
            (variable, negated) = variable_from_literal(literal, DIMACS=True)

            # If we haven't seen it before then add it to the dictionary
            if not DIMACS_variables_from_CNF_list_variables.has_key(variable):
                DIMACS_variables_from_CNF_list_variables[variable] = str(
                    numbers_used + 1)
                numbers_used += 1  # We've used another number, so increment the counter

            # Substitute in its new name
            clauses_copy[clause_number][literal_number] = negate(
                DIMACS_variables_from_CNF_list_variables[variable],
                negated,
                DIMACS=True)

    print_message("Done\n", 3, indent=indent + 1, verbosity=verbosity)

    number_of_clauses = len(clauses_copy)
    number_of_variables = numbers_used

    # From our list of clauses create a string according to the DIMACS format
    print_message("Creating DIMACS string...",
                  3,
                  indent=indent + 1,
                  verbosity=verbosity)
    DIMACS_string = "p cnf " + str(number_of_variables) + " " + str(number_of_clauses) + \
        "\n" + "\n".join([(" ".join(clause) + " 0") for clause in clauses_copy])
    print_message("Done\n", 3, indent=indent + 1, verbosity=verbosity)
    print_message("Done\n", 3, indent=indent, verbosity=verbosity)

    return DIMACS_string, DIMACS_variables_from_CNF_list_variables, number_of_variables, number_of_clauses
示例#22
0
    def force_evolution(self, method=None, indent = 0, verbosity = 0):
        """Adds clauses that force the search pattern to obey the transition rule"""

        # Methods:
        # 0. An implementation of the scheme Knuth describes in TAOCP Volume 4, Fascile 6, solution to exercise 65b (57 clauses and 13 auxillary variables per cell)
        # 1. An implementation of the naive scheme Knuth gives in the solution to exercise 65a                      (190 clauses and 0 auxillary variables per cell)
        # 2. A very naive scheme just listing all possible predecessor neighbourhoods                               (512 clauses and 0 auxillary variables per cell)

        print_message("Enforcing evolution rule...", 3, indent = indent, verbosity = verbosity)

        if method is None:
            if LLS_rules.rulestring_from_rule(self.rule) == "B3/S23":
                method = 1 # Optimal method for Life
            else:
                method = 2 # Default method
        assert method in range(3), "Method not found"
        assert method == 2 or LLS_rules.rulestring_from_rule(self.rule) == "B3/S23", "Rules other than Life can only use method 2"

        print_message("Method: " + str(method), 3, indent = indent + 1, verbosity = verbosity)

        clauses = []
        # Iterate over all cells not in the first generation
        for t, generation in enumerate(self.grid):
            if t > 0:
                for y, row in enumerate(generation):
                    for x, cell in enumerate(row):
                        if not self.ignore_transition[t][y][x]:

                            if method == 0:
                                clauses += LLS_taocp_variable_scheme.transition_rule(self.grid, x, y, t)

                            elif method == 1:
                                predecessor_cell = self.grid[t - 1][y][x]
                                neighbours = neighbours_from_coordinates(self.grid, x, y, t)

                                #TODO: Do the following clauses work if there aren't eight neighbours?

                                # If any four neighbours were live, then the cell is
                                # dead
                                for four_neighbours in itertools.combinations(neighbours, 4):
                                    clause = implies(four_neighbours, negate(cell))
                                    clauses.append(clause)

                                # If any seven neighbours were dead, the cell is dead
                                for seven_neighbours in itertools.combinations(neighbours, 7):
                                    clause = implies(map(negate,seven_neighbours), negate(cell))
                                    clauses.append(clause)

                                # If the cell was dead, and any six neighbours were
                                # dead, the cell is dead
                                for six_neighbours in itertools.combinations(neighbours, 6):
                                    clause = implies([negate(predecessor_cell)] + map(negate,six_neighbours), negate(cell))
                                    clauses.append(clause)

                                # If three neighbours were alive and five were dead,
                                # then the cell is live
                                for three_neighbours in itertools.combinations(neighbours, 3):
                                    neighbours_counter = collections.Counter(neighbours)
                                    neighbours_counter.subtract(three_neighbours)
                                    three_neighbours, five_neighbours = list(three_neighbours), list(neighbours_counter.elements())

                                    clause = implies(three_neighbours + map(negate, five_neighbours), cell)
                                    clauses.append(clause)

                                # Finally, if the cell was live, and two neighbours
                                # were live, and five neighbours were dead, then the
                                # cell is live (independantly of the final neighbour)
                                for two_neighbours in itertools.combinations(neighbours, 2):
                                    neighbours_counter = collections.Counter(neighbours)
                                    neighbours_counter.subtract(two_neighbours)
                                    two_neighbours, five_neighbours = list(two_neighbours), list(neighbours_counter.elements())[1:]

                                    clause = implies([predecessor_cell] + two_neighbours + map(negate, five_neighbours), cell)
                                    clauses.append(clause)

                            elif method == 2:

                                predecessor_cell = self.grid[t - 1][y][x]
                                neighbours = neighbours_from_coordinates(self.grid,x,y,t)

                                booleans = [True, False]

                                # For each combination of neighbourhoods
                                for predecessor_cell_alive in booleans:
                                    for neighbours_alive in itertools.product(booleans,repeat=8):

                                        BS_letter = "S" if predecessor_cell_alive else "B"
                                        transition = LLS_rules.transition_from_cells(neighbours_alive)
                                        transition_literal = self.rule[BS_letter + transition]

                                        clauses.append(implies([transition_literal] + [negate(predecessor_cell, not predecessor_cell_alive)] + map(negate, neighbours, map(lambda P: not P, neighbours_alive)), cell))
                                        clauses.append(implies([negate(transition_literal)] + [negate(predecessor_cell, not predecessor_cell_alive)] + map(negate, neighbours, map(lambda P: not P, neighbours_alive)), negate(cell)))

        print_message("Number of clauses used: " + str(len(clauses)), 3, indent = indent + 1, verbosity = verbosity)
        print_message("Done\n", 3, indent = indent, verbosity = verbosity)

        self.clauses += clauses
示例#23
0
def parse_input_string(input_string, indent=0, verbosity=0):
    """Transforms a "search pattern" given as a string into a SearchPattern"""

    print_message("Parsing input pattern...",
                  3,
                  indent=indent,
                  verbosity=verbosity)

    # Remove any trailing (or leading) whitespace and commas
    input_string = input_string.strip(", \t\n\r\f\v")

    # Break down string into list-of-lists-of-lists
    split_by_generation = re.split(
        "[ ,\t]*(?:\n|\r|(?:\r\n))(?:[ ,\t]*(?:\n|\r|(?:\r\n)))+[ ,\t]*",  # Split on at least two newlines (or carriage returns) and any commas or spaces
        input_string)
    split_by_line = [
        re.split(
            "[ ,\t]*(?:\n|\r|(?:\r\n))[ ,\t]*",  # Split on signle newline (or carriage return) and any ammount of commas or spaces
            generation) for generation in split_by_generation
    ]
    grid = [
        [
            re.split(
                "[ ,\t]*",  # Split on any amount of commas or spaces
                line) for line in generation
        ] for generation in split_by_line
    ]

    # Check that the list is cuboidal
    assert (all(
               len(generation) == len(grid[0])
               for generation in grid)
            and all(all(
               len(line) == len(grid[0][0])
               for line in generation) for generation in grid)), \
           "Search pattern is not cuboidal"

    # Tidy up any weird inputs
    grid = [[[standard_form_literal(cell) for cell in row]
             for row in generation] for generation in grid]

    # Create array which says when a "'" means that a transition should be ignored
    ignore_transition = [[[(cell[-1] == "'") for cell in row]
                          for row in generation] for generation in grid]
    grid = [
        [
            [
                cell.rstrip("'")  # The "'"s are now unnecessary
                for cell in line
            ] for line in generation
        ] for generation in grid
    ]

    # #Check that "" isn't being used as a variable name
    # assert all(all(all(
    #     cell not in ["","-"]
    #     for cell in row) for row in generation) for generation in grid), \
    #     "Malformed input and/or null string used as variable name"

    print_message("Done\n", 3, indent=indent, verbosity=verbosity)

    return grid, ignore_transition
示例#24
0
def preprocess_and_solve(search_pattern,
                         symmetry="C1",
                         period=None,
                         x_translate=0,
                         y_translate=0,
                         force_movement=False,
                         solver=None,
                         parameters=None,
                         timeout=None,
                         save_dimacs=None,
                         method=None,
                         force_at_most=[],
                         force_at_least=[],
                         force_change=[],
                         force_nonempty=False,
                         force_evolution=True,
                         dry_run=False,
                         indent=0,
                         verbosity=0):
    try:
        DIMACS_string, DIMACS_variables_from_CNF_list_variables, number_of_variables, number_of_clauses, number_of_cells = preprocess(
            search_pattern,
            symmetry=symmetry,
            period=period,
            x_translate=x_translate,
            y_translate=y_translate,
            force_movement=force_movement,
            method=method,
            force_at_most=force_at_most,
            force_at_least=force_at_least,
            force_change=force_change,
            force_nonempty=force_nonempty,
            force_evolution=force_evolution,
            indent=indent,
            verbosity=verbosity)
        width = len(search_pattern.grid[0][0])
        height = len(search_pattern.grid[0])
        duration = len(search_pattern.grid)
        active_width = sum(
            any(
                any((search_pattern.grid[z][y][x] not in ["0", "1"])
                    for y in range(height)) for z in range(duration))
            for x in range(width))
        active_height = sum(
            any(
                any((search_pattern.grid[z][y][x] not in ["0", "1"])
                    for z in range(duration)) for x in range(width))
            for y in range(height))
        active_duration = sum(
            any(
                any((search_pattern.grid[z][y][x] not in ["0", "1"])
                    for x in range(width)) for y in range(height))
            for z in range(duration))
        print_message('Number of undetermined cells: ' + str(number_of_cells),
                      indent=indent,
                      verbosity=verbosity)
        print_message('Number of variables: ' + str(number_of_variables),
                      indent=indent,
                      verbosity=verbosity)
        print_message('Number of clauses: ' + str(number_of_clauses) + "\n",
                      indent=indent,
                      verbosity=verbosity)
        print_message('Active width: ' + str(active_width),
                      indent=indent,
                      verbosity=verbosity)
        print_message('Active height: ' + str(active_height),
                      indent=indent,
                      verbosity=verbosity)
        print_message('Active duration: ' + str(active_duration) + "\n",
                      indent=indent,
                      verbosity=verbosity)
    except UnsatInPreprocessing:
        solution, sat, number_of_cells, number_of_variables, number_of_clauses, active_width, active_height, active_duration, time_taken = None, "UNSAT", None, None, None, None, None, None, 0
        print_message("Unsatisfiability proved in preprocessing",
                      indent=indent + 1,
                      verbosity=verbosity)
        print_message('Done\n', indent=indent, verbosity=verbosity)
    else:
        solution, sat, time_taken = solve(
            search_pattern,
            DIMACS_string,
            DIMACS_variables_from_CNF_list_variables,
            solver=solver,
            parameters=parameters,
            timeout=timeout,
            save_dimacs=save_dimacs,
            dry_run=dry_run,
            indent=indent,
            verbosity=verbosity)
    if not dry_run:
        print_message('Time taken: ' + str(time_taken) + " seconds\n",
                      indent=indent,
                      verbosity=verbosity)
    return solution, sat, number_of_cells, number_of_variables, number_of_clauses, active_width, active_height, active_duration, time_taken
示例#25
0
def append_to_file_from_string(file_name, input_string, indent = 0, verbosity = 0):
    """Append string to file"""
    print_message('Writing to file "' + file_name + '" ...', 3, indent = indent, verbosity = verbosity)
    with open(file_name, "a+") as output_file:
        output_file.write(input_string)
    print_message('Done\n', 3, indent = indent, verbosity = verbosity)
示例#26
0
    def force_at_least(self, literals, at_least, indent = 0, verbosity = 0):
        """Adds clauses forcing at least at_least of literals to be true"""

        name, number_of_clauses = self.define_cardinality_variable(literals, at_least)
        self.clauses.append([name])
        print_message("Number of clauses used: " + str(number_of_clauses + 1), 3, indent = indent + 1, verbosity = verbosity)