예제 #1
0
    def get_best_var_to_flip(self, instance, best_solution,
                             current_no_of_unsat_clauses):
        best_no_of_unsat_clauses = current_no_of_unsat_clauses
        best = best_solution.copy()
        utils = SatUtils()

        for i in range(1, len(best)):
            # checking if given variable is part of tabu list. If it is then next var is selected for the flip
            if self.is_var_tabu(i):
                continue

            tmp_solution = best_solution.copy()
            # working copy of the proposed solution
            var_to_flip = tmp_solution[i]

            # flipping a selected variable to opposing value
            tmp_solution[i] = SatUtils.flip_var(var_to_flip)

            _, no_of_unsat_clauses = SatUtils.solution_status(
                instance, tmp_solution)

            # if solution hasn't been found check if proposed temp solution is better than previous best
            if no_of_unsat_clauses < best_no_of_unsat_clauses:
                best_no_of_unsat_clauses = no_of_unsat_clauses

                # add current selection to tabu list
                self.add_to_tabu(i)
                # remember the best solution found so far for the next iteration
                best = tmp_solution.copy()

        return best
예제 #2
0
    def main(self,
             max_restarts=10,
             max_iterations=1000,
             instance_path="./sat_data/test.cnf"):
        instance = SatUtils.read_instance(instance_path)
        var_count = len(instance[0])

        start = time.time()
        end = None

        for restart in range(max_restarts):
            best_solution = SatUtils.initialize_variables(var_count)

            for iteration in range(max_iterations):
                solution_status, no_of_unsat_clauses = SatUtils.solution_status(
                    instance, best_solution)

                # if solution has been found terminate the search
                if solution_status is True:
                    end = time.time()

                    print("Iteration,{0},Restart,{1},Duration,{2}".format(
                        iteration, restart, end - start))
                    return
                best_solution = self.get_best_var_to_flip(
                    instance, best_solution, no_of_unsat_clauses)

            # resetting tabu list in between the restarts
            GsatSolver.tabu = []
    def test_basic_solution_status_with_true_state(self):
        formula = [[1, 2, 3, 4, 5, 6],
                   [[1, -2, 3], [1, -2, -3], [1, 2, 4], [-4, -5, 6]]]

        solution = {1: 1, 2: 1, 3: 0, 4: 1, 5: 1, 6: 1}

        solution_found, unsat_result = SatUtils.solution_status(
            formula, solution)
        self.assertTrue(solution_found)
        self.assertEqual(unsat_result, 0)
예제 #4
0
    def execute_search(self, proposed_solution, currently_flipped_variable,
                       random_clause):
        """
        Choose a variable to be flipped.
        If a randomly chosen variable is present in the randomly selected unsatisfied clause then return that variable.
        Otherwise find best and second best variable to be flipped. The choice between which variable to select, best
        or second best is made based on the probability provided.
        :param proposed_solution:
        :return:
        """
        if currently_flipped_variable not in random_clause:
            return currently_flipped_variable
        else:
            # Chose best or second best variable to flip based on the probability provided
            tmp_solution = proposed_solution.copy()
            flip_scores = {}
            utils = SatUtils()

            # loop over the variables to see which flip generates the lowest number of unsatisfied clauses
            for i in range(len(self.variables)):
                tmp_solution[i] = SatUtils.flip_var(self.variables[i])
                _, unsat_clauses = SatUtils.solution_status(
                    self.instance, tmp_solution)

                # keep track of which variable flip generated what number of unsatisfied clauses
                flip_scores[self.variables[i]] = unsat_clauses

                # flip the selected variable
                tmp_solution[i] = SatUtils.flip_var(self.variables[i])

            # Find best and second best - extremely efficient according to stack overflow
            two_smallest_keys = heapq.nsmallest(2,
                                                flip_scores,
                                                key=flip_scores.get)

            best = two_smallest_keys[0]
            second_best = two_smallest_keys[1]

            # generate noise value
            noise_value = random.uniform(0, 1)

            # compare noise value generated to the probability of second best variable being selected
            if noise_value < self.probability:
                return second_best
            else:
                return best