# A tentative satisfiability algorithm

General satisfiability (with a few exceptions such as Horn Clauses) is not believed to have an algorithmic solution. However, the following algorithm appears to be a solution for general satisfiability. What exactly is the flaw with the following algorithm?

1. Let $W$ be an empty set which will contain all variables that necessarily have to be true or false.
2. Let $L$ be the set of clauses.
3. Loop through $L$.
4. Every time a non-conditional variable is found, remove it from $L$ and insert it into $W$.
5. If this leaves an empty AND implication, remove all variables in that empty implication from $L$ and insert into $W$.
6. If this leaves an empty OR implication, create new instances of the algorithm, where each instance deals with one variable in the implication (i.e. if the implication is: $x V \implies y$, create one instance where $x$ is inserted into $W$, one where $y$ is inserted into $W$ and one where $x$ and $y$ are inserted into $W$).
7. Set all variables in $W$ to the value they necessarily have to be.
8. Reinsert the variables in $W$ in $L$ with their changed values and check if all clauses are satisfied.
9. If satisfiability is met, then return $L$, else return "Not Satisfiable".

A non conditional variable is defined as a variable that is necessary true or false, e.g. $\implies x$ or $\implies \neg y$.

An empty implication is defined as an implication where one side is empty (e.g. $\implies x \wedge y$) or the other side is necessarily true (e.g. $\mathrm{true} \vee a \implies b$.

To get a more intuitive understanding of the algorithm consider the following set of clauses $L$:

\begin{align} a \wedge b &\implies c & \text{(i)} \\ &\implies f \wedge g & \text{(ii)} \\ f &\implies \neg a & \text{(iii)} \\ f \vee a &\implies b & \text{(iv)} \\ &\implies c & \text{(v)} \\ \end{align}

The algorithm will do the following:

1) Since $c$, $f$, $g$ are non-conditional variables, the algorithm will insert them into $W$. $W = \{c, f, g\}$.

2) Removing $c$, $f$ and $g$ will leave the empty clauses: $\implies \neg a, a \wedge b, b$. These will be added to $W$. $W = \{c, f, g, b, \neg a\}$.

3) Reinserting the variables into $L$ will result in the first clauses being violated: $a \wedge b \implies c$. Since $a$ is false, $c$ is false, meaning clause (v) is violated. The algorithm will return "Not Satisfiable"

I am aware that the algorithm appears confusing. Please feel free to ask for clarification.

From comments I now realize that there is no known efficient general satisfiability algorithm. I'm still interested in feedback about my algorithm. Does it work? How does it compare with common algorithms?

• What makes you think that there is no algorithmic solution to general satisfiability? There absolutely are algorithms for doing this; none of them are known to have worst-case polynomial runtimes, though. What you are describing seems like a well-known resolution-based satisfiability algorithm. – templatetypedef Aug 15 '12 at 3:14
• @templatetypedef The Wikipedia article seemed to suggest that no solution exists. By any chance could you refer me to the well known algorithm? – user1422 Aug 15 '12 at 3:17
• @Riddler what the Wikipedia article actually says is "SAT was the first known example of an NP-complete problem. That briefly means that there is no known algorithm that efficiently solves all instances of SAT" It also has an "Algorithms for solving SAT" section. – mootinator Aug 15 '12 at 3:18
• There are definitely algorithmic solutions to general satisfiability since there are brute force solutions (assigning all combinations of True/False values to the variables and seeing if any of the resulting expressions evaluate to True). – chm052 Sep 5 '12 at 22:32
• The problem is that you generate an exponential number of new instances from the empty ORs in the worst case. – Elliot Gorokhovsky Feb 27 '15 at 21:50

Problem 1

The case of $(x\rightarrow y \vee \overline y)$ should be a "non conditional variable" with respect to $x$ (ie. that $\overline x$ should now be inserted into $W$). If this is not true, then your algorithm needs an extra step to infer this. Assuming $(x\rightarrow y \vee \overline y)$ is a "non conditional variable", we continue.

Problem 2

NOTE: this is one problem I noticed; there may very well be other problems.

The problem is with the "empty OR implication" split into two algorithms, is that in its current form, the split does not cover all cases. In particular:

You start with $(x \vee c \rightarrow y)$, then $c$ is removed and we are left with an empty OR implication of $(x \vee [] \rightarrow y)$. You suggest now splitting it into two new problems and solving each of them; one with $x=T\wedge y=T$ and one where $y=T$. But this does not cover all cases. What about the case when $x=F\vee y=F$. However, your algorithm never considers the possibility that $y$ is false.

I think you might be able to fix this by formulating the two new problems as one with $y$ and one with $\overline x$.

Problem 3

What happens when you are left with a bunch of clauses in the form:

$$(a\wedge b \rightarrow c)$$

or

$$(a \rightarrow b \vee c)$$

After reducing everything, these clauses will remain, and you won't be able to test their satisfiability easily.

Analysis

Note: This "O" notation, $\mathcal{O}(something)$ etc., is called Big O notation. $\Omega(something)$ is called Big-omega.

Supposing the algorithm did work in general, it would run in time of $\Omega(2^m)$ worst case, $m$ being the number of variables. The reason is, each splitting of problem into problems of similar size means that the algorithm runs in exponential time. To visualize this concept, look at the following image of a full binary tree (image from here):

Now imagine the original problem is the node on top. We split the problem into two problems on the second level, but they are of similar size (we only get rid of one variable, $x$ or $y$ from the empty OR implication, so we will still have lots of empty OR implications to do each level). We will potentially have to split the problem $\mathcal{O}(m)$ times to get rid of $m$ variables. This means we will have to deal with a tree with $m$ levels. A tree with $m$ levels has $2^m$ leaf nodes (nodes at the bottom). This is called exponential time, and is informally somewhat on-par with all known boolean satisfiability algorithms. But so is brute force: there are $2^m$ possible assignments of the variables, so by brute force you can guess each assignment and check for satisfiability with similar performance!

• I guess you mean $\Omega(.)$? – Raphael Sep 13 '12 at 6:29
• TBH I am not sure if $\Omega$ is appropriate, because in best case, the algorithm can be solved quickly. What I meant was that the upper-bound was worse than (or at least as bad as) $\mathcal{O}(2^m)$. I don't know the proper way to state this. The main point of the O-notation though, is to rid us of the constants. If there is a better way to express it, feel free to edit. – Realz Slaw Sep 13 '12 at 12:23
• Can this be expressed as "the worst case is $\Omega(2^m)$"? – Realz Slaw Sep 13 '12 at 12:29
• Once you qualify "worst-case", this is what we talk about, no best-case involved. "worse than $O(.)$" (whatever "worse than this upper bound" means) is indeed what $\Omega(.)$ (a lower bound) says; see also here. In this case, worst-case runtime in $\Omega(2^m)$ seems to be what you want to say. Similarly, you want $\Theta(m)$ or $\Omega(m)$ in the last paragraph. – Raphael Sep 13 '12 at 12:34

Before you feel you have a "new" SAT algorithm, please review the standard/classic backtracking/search algorithm in the literature for the problem dating to ~1962, the Davis–Putnam–Logemann–Loveland algorithm. most backtracking/recursive algorithms for the problem will likely end up looking somewhat similar to this algorithm, although it can take quite a while to demonstrate this equivalence.

Serious analysis would involve benchmarking your algorithm against examples (or random instances) vs DPLL.

And so it is helpful merely to summarize how your algorithm differs from it. without reviewing your code, odds are:

• The algorithm has a bug in it. either returning false positives or negatives (ie algorithm returns "formula is satisfiable" when it is not or vice versa, respectively). this can be usually caught by very thorough testing of a large range of randomly generated formulas and checking against another known correct algorithm/implementation eg DPLL.
• Your algorithm is not as good as DPLL.
• If it is as good as DPLL or "better", it is generally due to branching and variable selection heuristics/strategies and the distribution of instances under testing.

The algorithm can be easily understood by an intelligent undergraduate however it seems rarely taught at the undergraduate level or in undergraduate textbooks, or perhaps not even often referenced, possibly leading to a mistaken view or impression that basic SAT algorithms are not well understood etc.

Also recently just ran across this "live" site called ToughSat by Yuen and Bebel for generating hard instances for use with benchmarking, some based on factoring [one of the classic SAT hard instance generation methods]. there are others eg DIMACs that store archives of hard instances although it may no longer be online.