2

Backtracking search is a well-known problem-solving technique, that recurs through all possible combinations of variable assignments in search of a valid solution. The general algorithm is abstracted into a concise higher-order function: https://en.wikipedia.org/wiki/Backtracking

Some problems require partial backtracking, that is, they have a mixture of don't-know non-determinism (have a choice to make, that matters, if you get it wrong you have to backtrack) and don't-care non-determinism (have a choice to make, that doesn't matter, maybe it matters for how long it takes you to find the solution, but not for the correctness thereof, you don't have to backtrack).

Consider for example the Boolean satisfiability problem that can be solved with the DPLL algorithm. If you try to represent that with the general backtracking algorithm, the result will not only recur through all 2^N variable assignments (which is sadly necessary in the general case), but all N! orders of trying the variables (completely unnecessary and hopelessly inefficient).

Is there a general algorithm for partial backtracking? A concise higher-order function that takes function parameters for both don't-know and don't-care choices?

rwallace
  • 31,405
  • 40
  • 123
  • 242
  • Would DPLL actually go through all permutations of the variables? I was under the impression that it picked some single variable at each step using a heuristic, then tried both branches to see if the formula was satisfiable. If both branches fail, then the formula at the given point is definitely not satisfiable and there's no reason to try a different variable. – templatetypedef Sep 06 '20 at 19:48
  • @templatetypedef Indeed, the DPLL algorithm itself is fine in that regard. But what if you strip out the backtracking part from DPLL, in favor of using the general backtracking algorithm (just giving it parameters for the domain-specific parts)? The general backtracking algorithm will not behave so well; it will go through all permutations of the variables. (In a sense, it won't know that the choice of variable order is the kind of choice that does not need to be backtracked.) – rwallace Sep 06 '20 at 19:51
  • 1
    I don't like how the Wikipedia pseudocode simulates an iterator/lazy list with two different functions -- it makes it harder to implement an interesting branching heuristic compared to one function that returns a lazy list of search tree children to open in order (and even then the choice of tree exploration strategy makes a large difference, comparing something like depth first search to depth first with best first backtracking). – David Eisenstat Sep 06 '20 at 22:16
  • 1
    The heuristic I commonly use that generalizes the best is, most-constrained-first. For SAT-solving with DPLL specifically, reducing clauses to unit clauses is a huge win because it lets you do unit propagation, so I would have my heuristic focus on the shortest clauses. This should give you unit clauses sooner. – Davislor Sep 07 '20 at 01:23
  • However, there are many free, highly-optimized SAT-solvers out there. Unless this is a learning exercise, consider using one of them. – Davislor Sep 07 '20 at 01:25

1 Answers1

3

If I understand you correctly, you’re asking about symmetry-breaking in tree search. In the specific example you gave, all permutations of the list of variable assignments are equivalent.

Symmetries are going to be domain-specific. So is the more-general technique of pruning the search tree, by short-circuiting and backtracking eagerly. There are a few symmetry-breaking techniques I’ve used that generalize.

One is to search the problem space in a canonical order. If the branch that sets variable 10 only tries variables 11, 12 and up, not variables 9, 8 or 7, it won’t search any permutation of the same solution. It will only test solutions that are unique up to permutation. (In the specific case of SAT-solving, this might rule out an optimal search order—although you could re-order the variables arbitrarily.)

Another is to make a test that only one distinct solution of any equivalence class will pass, ideally one that can be checked near the top of the search tree. The classic example of this is, in the 8-queens problem, checking whether the queen on the row you look at first is on the left or the right side of the chessboard. Any solution where she’s on the right is a mirror-image of one other solution where she’s on the left, so you can cut the search space in half. (You can actually do better than this with that problem.) If you only need to test for satisfiability, you can get by with a filter that merely guarantees that, if any solution exists, at least one solution will pass.

If you have enough memory, you might also store a set of branches that have already been searched, and then check whether a branch that you are considering whether to search is equivalent to one already in the set. This would be more practical for a search space with a huge number of symmetries than one with a huge number of solutions unique up to symmetry.

Davislor
  • 14,674
  • 2
  • 34
  • 49