DPLL algorithm definition - algorithm

I am having some problems understanding the DPLL algorithm and I was wondering if anyone could explain it to me because I think my understanding is incorrect.
The way I understand it is, I take some set of literals and if some every clause is true the model is true but if some clause is false then the model is false.
I recursively check the model by looking for a unit clause, if there is one I set the value for that unit clause to make it true, then update the model. Removing all clauses that are now true and remove all literals which are now false.
When there are no unit clauses left, I chose any other literal and assign values for that literal which make it true and make it false, then again remove all clauses which are now true and all literals which are now false.

DPLL requires a problem to be stated in disjunctive normal form, that is, as a set of clauses, each of which must be satisfied.
Each clause is a set of literals {l1, l2, ..., ln}, representing the disjunction of those literals (i.e., at least one literal must be true for the clause to be satisfied).
Each literal l asserts that some variable is true (x) or that it is false (~x).
If any literal is true in a clause, then the clause is satisfied.
If all literals in a clause are false, then the clause is unsatisfiable and hence the problem is unsatisfiable.
A solution is an assignment of true/false values to the variables such that every clause is satisfied. The DPLL algorithm is an optimised search for such a solution.
DPLL is essentially a depth first search that alternates between three tactics. At any stage in the search there is a partial assignment (i.e., an assignment of values to some subset of the variables) and a set of undecided clauses (i.e., those clauses that have not yet been satisfied).
(1) The first tactic is Pure Literal Elimination: if an unassigned variable x only appears in its positive form in the set of undecided clauses (i.e., the literal ~x doesn't appear anywhere) then we can just add x = true to our assignment and satisfy all the clauses containing the literal x (similarly if x only appears in its negative form, ~x, we can just add x = false to our assignment).
(2) The second tactic is Unit Propagation: if all but one of the literals in an undecided clause are false, then the remaining one must be true. If the remaining literal is x, we add x = true to our assignment; if the remaining literal is ~x, we add x = false to our assignment. This assignment can lead to further opportunities for unit propagation.
(3) The third tactic is to simply choose an unassigned variable x and branch the search: one side trying x = true, the other trying x = false.
If at any point we end up with an unsatisfiable clause then we have reached a dead end and have to backtrack.
There are all sorts of clever further optimisations, but this is the core of almost all SAT solvers.
Hope this helps.

The Davis–Putnam–Logemann–Loveland (DPLL) algorithm is a, backtracking-based search algorithm for deciding the satisfiability of propositional logic formulae in conjunctive normal form also known as satisfiability problem or SAT.
Any boolean formula can be expressed in conjunctive normal form (CNF) which means a conjunction of clauses i.e. ( … ) ^ ( … ) ^ ( … )
where a clause is a disjunction of boolean variables i.e. ( A v B v C’ v D)
an example of boolean formula expressed in CNF is
(A v B v C) ^ (C’ v D) ^ (D’ v A)
and solving the SAT problem means finding the combination of values for the variables in the formula that satisfy it like A=1, B=0, C=0, D=0
This is a NP-Complete problem. Actually it is the first problem which has been proven to be NP-Complete by Stepehn Cook and Leonid Levin
A particular type of SAT problem is the 3-SAT which is a SAT in which all clauses have three variables.
The DPLL algorithm is way to solve SAT problem (which practically depends on the hardness of the input) that recursively creates a tree of potential solution
Suppose you want to solve a 3-SAT problem like this
(A v B v C) ^ (C’ v D v B) ^ (B v A’ v C) ^ (C’ v A’ v B’)
if we enumerate the variables like A=1 B=2 C=3 D=4 and se negative numbers for negated variables like A’ = -1 then the same formula can be written in Python like this
[[1,2,3],[-3,4,2],[2,-1,3],[-3,-1,-2]]
now imagine to create a tree in which each node consists of a partial solution. In our example we also depicted a vector of the clauses satisfied by the solution
the root node is [-1,-1,-1,-1] which means no values have been yet assigned to the variables neither 0 nor 1
at each iteration:
we take the first unsatisfied clause then
if there are no more unassigned variables we can use to satisfy that clause then there can’t be valid solutions in this branch of the search tree and the algorithm shall return None
otherwise we take the first unassigned variable and set it such it satisfies the clause and start recursively from step 1. If the inner invocation of the algorithm returns None we flip the value of the variable so that it does not satisfy the clause and set the next unassigned variable in order to satisfy the clause. If all the three variables have been tried or there are no more unassigned variable for that clause it means there are no valid solutions in this branch and the algorithm shall return None
See the following example:
from the root node we choose the first variable (A) of the first clause (A v B v C) and set it such it satisfies the clause then A=1 (second node of the search tree)
the continue with the second clause and we pick the first unassigned variable (C) and set it such it satisfies the clause which means C=0 (third node on the left)
we do the same thing for the fourth clause (B v A’ v C) and set B to 1
we try to do the same thing for the last clause we realize we no longer have unassigned variables and the clause is always false. We then have to backtrack to the previous position in the search tree. We change the value we assigned to B and set B to 0. Then we look for another unassigned value that can satisfy the third clause but there are not. Then we have to backtrack again to the second node
Once there we have to flip the assignment of the first variable (C) so that it won’t satisfy the clause and set the next unassigned variable (D) in order to satisfy it (i.e. C=1 and D=1). This also satisfies the third clause which contains C.
The last clause to satisfy (C’ v A’ v B’) has one unassigned variable B which can be then set to 0 in order to satisfy the clause.
In this link http://lowcoupling.com/post/72424308422/a-simple-3-sat-solver-using-dpll you can find also the python code implementing it

Related

How to set mutually exclusive probabilities in Problog?

A person X can either be inpatient or outpatient.
Given the fact location(X,outpatient) how can Problog infer that the probability of location(X,inpatient) is 0?
For example I want a side effect of:
person(1).
location(1,inpatient).
dependent(1,opioids).
receive(1,clonidine).
query(detoxification(1,opioids,success)).
to be an inference that location(1,outpatient) has zero probability.
If I write location(X,outpatient);location(X,inpatient)., all queries return both with a probability of 1.
If I write P::location(X,outpatient);(1-P)::location(X,inpatient). that gives an error because I haven't specified a value for P. If I specify a value for P, that value is never updated (as expected because Prolog treats variables as algebraic variables and I haven't told Problog to update P.
If I write location(X,outpatient) :- \+ location(X,inpatient). I create a negative cycle, which I have to if I am to specify the inverse goal.
One solution:
P::property(X,location,inpatient);(1-P)::property(X,location, outpatient) :-
inpatient(X),
P is 1.
P::property(X,location,outpatient);(1-P)::property(X,location, inpatient) :-
outpatient(X),
P is 1.
P::inpatient(X);(1-P)::outpatient(X) :-
property(X,location,inpatient),
P is 1.
P::outpatient(X);(1-P)::inpatient(X) :-
property(X,location,outpatient),
P is 1.
This binds inpatient/1 to property/3 for the property of location with value inpatient.

Is nonexistence queriable in Datalog?

Suppose I've defined a few values for a function:
+(value[1] == "cats")
+(value[2] == "mice")
Is it possible to define a function like the following?
(undefined[X] == False) <= (value[X] == Y)
(undefined[X] == True) <= (value[X] does not exist)
My guess is that it can't, for two reasons:
(1) Queries are guaranteed to terminate in Datalog, and you could query for undefined[X] == True.
(2) According to Wikipedia, one of the ways Datalog differs from Prolog is that Datalog "requires that every variable appearing in a negative literal in the body of a clause also appears in some positive literal in the body of the clause".
But I'm not sure, because the terms involved ("terminate", "literal", "negative") have so many uses. (For instance: Does negative literal mean f[X] == not Y or does it mean not (f[X] == Y)? Does termination mean that it can evaluate a single expression like undefined[3] == True, or does it mean it would have found all X for which undefined[X] == True?)
Here another definition of "safe".
A safety condition says that every variable in the body of a rule must occur in at least one positive (i.e., not negated)
atom.
Source: Datalog and Recursive Query Processing
And an atom (or goal) is a predicate symbol (function) along with a list of terms as arguments. (Note that “term” and “atom” are used differently here than they are in Prolog.)
The safety problem is to decide whether the result of a given Datalog program can be guaranteed to be finite even when some source relations are infinite.
For example, the following rule is not safe because the Y variable appears only in a negative atom (i.e. not predicate2(Z,Y)).
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y) .
To meet the condition of safety the Y variable should appear in a positive predicate too:
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y), predicate3(Y) .

Abort evaluation of boolean RPN expression

I have a few boolean expression in RPN-Format like this:
{0} {1} {2} AND OR // equals: {0} or {1} and {2}
Computing the boolean variables {x} is very expensive. And obviously there is no need to compute {1} and {2} if {0} is already true, since the expression will alway evaluation to true in this case.
How can I detect beforehand which boolean variables I have to evaluate first to abort the evaluation of the expression with as few variables evaluated as possible?
I want to know which variables with a definite value will evaluate the whole expression to be true or false.
You should prefer to evaluate expressions where the expected number of sub-expression evaluations is lower.
a and (b or c or d)
You should first evaluate a - since if it false - you're done
a or (b and c and d)
Again, you should first evaluate a - since if it is true - you're done
(a or b) and (c or d or e)
First, evaluate (a or b) - since if it is false - you're done
etc.
To implement:
Build a tree where the root is an or if your expression has the form "expr or expr or expr or ...". Alternatively if your expression has the form "expr and expr and expr and ..." - the root should be an and.
Build the sub-trees recursively. The levels or the trees are and / or alternatively. The number of children or each node varies (2 or more except leafs).
Evaluate recursively by selecting the sub-tree with the minimal number of children and evaluate it first.
Algorithm
One approach is to first expand the boolean expression, and then factorize.
The common factors will tell you which variables can force the expression to be false.
Then you can invert the expression and repeat to find the variables that will force the expression to be true.
Example 1
This should become clearer with an example, I'll write + for OR and . for AND:
0 + 1.2
this is already expanded. There is no common factor so there is no way a single variable can force this to be true.
Next we invert and expand using De Morgan's laws:
!(0 + 1.2)
= !0.!(1.2)
= !0.(!1 + !2)
This has a factor of !0, i.e. if 0 is false, we can conclude that the whole expression is false.
Example 2
1.2 + 1.3
= 1.(2 + 3)
so if 1 is false, the whole expression is false.
!(1.2 + 1.3)
=!(1.2).!(1.3)
=(!1 + !2).(!1 + !3)
=!1 + !2.!1 + !2.!3
This has no common factor so there is no one variable that can force the expression to be true.
Convert your expression into a minimized sum-of-product form.
This can be done by using a Karnaugh-Veitch map for small expressions. More involved methods are described here.
In your example, you get one term a (your {0}) with a single literal and a second term cb ({1}{2} in your notation) with two literals. For every input variable, count the terms affected by this variable.
A simple count would not take into account that terms may be large (many literals) or small (few literals). Therefore, you might weight the terms with the number of Karnaugh cells covered by the respective cell.
The counting result (a:1x4, b:1x2, c:1x2) tells you which variable should be evaluated first. The evaluation ends, once a single term becomes true or all terms are evaluated to false.

swi-prolog truth assignment?

So I have this exercise that I'm stuck on:
A formula is:
tru
fls
variable(V) iff V is an atom.
or(Flist) iff every element in the list is a formula
there are implies, and, neg too. the form looks similar.
We can represent a truth assignment (an assignment of values to variables) by a Prolog list of the form [Var1/Value1, Var2/Value2,...VarN/ValueN]. Write a predicate sub(?F,?Asst,?G) which succeeds iff G is a formula which is a result of substituting the variables of F with corresponding values from the assignment Asst. (You can assume that the truth assignment A is at least partially instantiated).
E.g.
sub(variable(x), [x/tru], tru).
true
sub(or([variable(a),variable(b)]), [a/tru,b/fls], G).
G = or(tru,fls)
true
I've tried
sub(variable(x),[x/value],G):-
G = variable(value).
But it just returns false.
Edit: Sorry I didn't make the question clear, Can someone explain to me if there's a way to assign values associated with variables in a list to another variable? I think it has something to do with unification.
Variables are placeholders.
Beware of case sensitivity: Prolog variable names start with an uppercase character or underscore, atoms with a lowercase character.
Your code snippet of sub/3 assumes that the list of
key-value pairs has exactly a length of one ([x/value]).
By using member/2 the lists can have arbitrary length.
When handling n-ary logical connectives like and / or, you probably want a short-circuit implementation that returns as soon as possible. Like so:
sub(tru,_,tru).
sub(fls,_,fls).
sub(variable(X),Assoc,Value) :-
member(X/Value,Assoc).
sub(or([]),_,fls).
sub(or([X|Xs]),Assoc,V) :-
sub(X,Assoc,T),
( T = tru, V = tru % short-circuit logical-or
; T = fls, sub(or(Xs),Assoc,V)
).

How does a Resolution algorithm work for propositional logic?

I haven't been able to understand what the resolution rule is in propositional logic. Does resolution simply state some rules by which a sentence can be expanded and written in another form?
Following is a simple resolution algorithm for propositional logic. The function returns the set of all possible clauses obtained by resolving it's 2 input. I can't understand the working of the algorithm, could someone explain it to me?
function PL-RESOLUTION(KB,α) returns true or false
inputs: KB, the knowledge base, a sentence α in propositional logic, the query, a
sentence in propositional logic
clauses <--- the set of clauses in the CNF representation of KB ∧ ¬α
new <--- {}
loop do
for each Ci, Cj in clauses do
resolvents <----- PL-RESOLVE(Ci, Cj)
if resolvents contains the empty clause then return true
new <--- new ∪ resolvents
if new ⊆ clauses then return false
clauses <---- clauses ∪ new
It's a whole topic of discussion but I'll try to explain you one simple example.
Input of your algorithm is KB - set of rules to perform resolution. It easy to understand that as set of facts like:
Apple is red
If smth is red Then this smth is sweet
We introduce two predicates R(x) - (x is red) and S(x) - (x is sweet). Than we can written our facts in formal language:
R('apple')
R(X) -> S(X)
We can substitute 2nd fact as ¬R v S to be eligible for resolution rule.
Caluclating resolvents step in your programs delete two opposite facts:
Examples: 1) a & ¬a -> empty. 2) a('b') & ¬a(x) v s(x) -> S('b')
Note that in second example variable x substituted with actual value 'b'.
The goal of our program to determine if sentence apple is sweet is true. We write this sentence also in formal language as S('apple') and ask it in inverted state. Then formal definition of problem is:
CLAUSE1 = R('apple')
CLAUSE2 = ¬R(X) v S(X)
Goal? = ¬S('apple')
Algorithm works as follows:
Take clause c1 and c2
calculate resolvents for c1 and c2 gives new clause c3 = S('apple')
calculate resolvents for c3 and goal gives us empty set.
That means our sentence is true. If you can't get empty set with such resolutions that means sentence is false (but for most cases in practical applications it's a lack of KB facts).
Consider clauses X and Y, with X = {a, x1, x2, ..., xm} and Y = {~a, y1, y2, ..., yn}, where a is a variable, ~a is its negation, and the xi and yi are literals (i.e., possibly-negated variables).
The interpretation of X is the proposition (a \/ x1 \/ x2 \/ ... \/ xm) -- that is, at least one of a or one of the xi must be true, assuming X is true. Likewise for Y.
We assume that X and Y are true.
We also know that (a \/ ~a) is always true, regardless of the value of a.
If ~a is true, then a is false, so ~a /\ X => {x1, x2, ..., xm}.
If a is true, then ~a is false. In this case a /\ Y => {y1, y2, ..., yn}.
We know, therefore, that {x1, x2, ..., xm, y1, y2, ..., yn} must be true, assuming X and Y are true. Observe that the new clause does not refer to variable a.
This kind of deduction is known as resolution.
How does this work in a resolution based theorem prover? Simple: we use proof by contradiction. That is, we start by turning our "facts" into clauses and add the clauses corresponding to the negation of our "goal". Then, if we can eventually resolve to the empty clause, {}, we will have reached a contradiction since the empty clause is equivalent to falsity. Because the facts are given, this means that our negated goal must be wrong, hence the (unnegated) goal must be true.
resolution is a procedure used in proving that argument which are expressible in predicate logic are correct
resolution lead to refute theorem proving technique for sentences in propositional logic.
resolution provides proof by refutation. i.e. to show that it is valid,resolution attempts to show that the negation of the statement produces a contradiction with a known statement
algorithm:
1). convert all the propositions of axioms to clause form
2). negate propositions & convert result to clause form
3)resolve them
4)if the resolvent is the empty clause, then contradiction has been found

Resources