We can now implement resolution of two particular clauses as follows:
We can now implement resolution of two particular clauses as follows:
%% Cell type:code id:33fc6271 tags:
%% Cell type:code id:33fc6271 tags:
``` prolog
``` prolog
:-use_module(library(lists)).
:-use_module(library(lists)).
resolve(Clause1,Clause2,Resolvent):-
resolve(Clause1,Clause2,Resolvent):-
select(Lit1,Clause1,R1),negate(Lit1,NLit1),
select(Lit1,Clause1,R1),negate(Lit1,NLit1),
select(NLit1,Clause2,R2),
select(NLit1,Clause2,R2),
append(R1,R2,Resolvent).
append(R1,R2,Resolvent).
```
```
%% Cell type:markdown id:1d426bb1 tags:
%% Cell type:markdown id:1d426bb1 tags:
The above predicate uses the predicate ```select/3``` from ```library(lists)```, which can be used to select an element from a list and returns a modified list with the element removed:
The above predicate uses the predicate ```select/3``` from ```library(lists)```, which can be used to select an element from a list and returns a modified list with the element removed:
As you can see, the number of new clauses can grow considerably when applying resolution.
As you can see, the number of new clauses can grow considerably when applying resolution.
Below we study the DPLL algorithm to check satisfiability of a formula in CNF, using a simple form of resolution (where one clause is a single literal and the other clauses comes from the CNF of the problem).
Below we study the DPLL algorithm to check satisfiability of a formula in CNF, using a simple form of resolution (where one clause is a single literal and the other clauses comes from the CNF of the problem).
%% Cell type:markdown id:d32921c9 tags:
%% Cell type:markdown id:d32921c9 tags:
### DPLL Algorithm
### DPLL Algorithm
We now present bit by bit the DPLL algorithm as a Prolog program
We now present bit by bit the DPLL algorithm as a Prolog program
manipulating the above clause database.
manipulating the above clause database.
The algorithm works by selecting a literal and then making it true and checking whether this leads to a solution.
The algorithm works by selecting a literal and then making it true and checking whether this leads to a solution.
If not, the algorithm backtracks and makes the negated version of the literal true and tries to find a solution.
If not, the algorithm backtracks and makes the negated version of the literal true and tries to find a solution.
%% Cell type:code id:26924712 tags:
%% Cell type:code id:26924712 tags:
``` prolog
``` prolog
becomes_true(TrueLit,Clause):-
becomes_true(TrueLit,Clause):-
member(TrueLit,Clause).
member(TrueLit,Clause).
```
```
%% Cell type:markdown id:17dd1525 tags:
%% Cell type:markdown id:17dd1525 tags:
The above checks if making a given literal true makes the second argument, a clause, true (i.e., the clause is satisfied):
The above checks if making a given literal true makes the second argument, a clause, true (i.e., the clause is satisfied):
%% Cell type:code id:7d90c4ad tags:
%% Cell type:code id:7d90c4ad tags:
``` prolog
``` prolog
?-becomes_true(pos(b),[neg(a),pos(b)]).
?-becomes_true(pos(b),[neg(a),pos(b)]).
```
```
%% Output
%% Output
%% Cell type:code id:d4b4e71f tags:
%% Cell type:code id:d4b4e71f tags:
``` prolog
``` prolog
?-becomes_true(neg(a),[neg(a),pos(b)]).
?-becomes_true(neg(a),[neg(a),pos(b)]).
```
```
%% Output
%% Output
%% Cell type:markdown id:62e13b8d tags:
%% Cell type:markdown id:62e13b8d tags:
The code below simplifies a clause given a literal ```TrueLit``` that has just become true.
The code below simplifies a clause given a literal ```TrueLit``` that has just become true.
This is done using resolution:
This is done using resolution:
%% Cell type:code id:3b9c87e4 tags:
%% Cell type:code id:3b9c87e4 tags:
``` prolog
``` prolog
simplify(TrueLit,Clause,SimplifedClause):-
simplify(TrueLit,Clause,SimplifedClause):-
negate(TrueLit,FalseLit),
negate(TrueLit,FalseLit),
delete(Clause,FalseLit,SimplifedClause).% Resolution with TrueLit if possible
delete(Clause,FalseLit,SimplifedClause).% Resolution with TrueLit if possible
```
```
%% Cell type:markdown id:e8cee74e tags:
%% Cell type:markdown id:e8cee74e tags:
The code uses the ```delete/3``` predicate from ```library(lists)```. Unlike select it also succeeds when the element is not in the list:
The code uses the ```delete/3``` predicate from ```library(lists)```. Unlike select it also succeeds when the element is not in the list:
%% Cell type:code id:0abd90f6 tags:
%% Cell type:code id:0abd90f6 tags:
``` prolog
``` prolog
?-delete([a,b,c],d,R).
?-delete([a,b,c],d,R).
```
```
%% Output
%% Output
%% Cell type:code id:cc81b404 tags:
%% Cell type:code id:cc81b404 tags:
``` prolog
``` prolog
?-delete([a,b,c],a,R).
?-delete([a,b,c],a,R).
```
```
%% Output
%% Output
%% Cell type:markdown id:53d21e85 tags:
%% Cell type:markdown id:53d21e85 tags:
The above code simplifies a clause by resolution:
The above code simplifies a clause by resolution:
%% Cell type:code id:57df05f0 tags:
%% Cell type:code id:57df05f0 tags:
``` prolog
``` prolog
?-simplify(pos(c),[pos(a),neg(c)],SC).
?-simplify(pos(c),[pos(a),neg(c)],SC).
```
```
%% Output
%% Output
%% Cell type:markdown id:4c3eae55 tags:
%% Cell type:markdown id:4c3eae55 tags:
If no resolution is possible the clause is returned unchanged:
If no resolution is possible the clause is returned unchanged:
%% Cell type:code id:a36a54a4 tags:
%% Cell type:code id:a36a54a4 tags:
``` prolog
``` prolog
?-simplify(pos(b),[pos(a),neg(c)],SC).
?-simplify(pos(b),[pos(a),neg(c)],SC).
```
```
%% Output
%% Output
%% Cell type:markdown id:441c4145 tags:
%% Cell type:markdown id:441c4145 tags:
We can now define the whole procedure to set a literal ```Lit``` to true (```Clauses|{Lit}```) by
We can now define the whole procedure to set a literal ```Lit``` to true (```Clauses|{Lit}```) by
- removing all clauses which have become true (and no longer need to be checked)
- removing all clauses which have become true (and no longer need to be checked)
- simplifying the remaining clauses with resolution if possible.
- simplifying the remaining clauses with resolution if possible.
%% Cell type:code id:95fcf64b tags:
%% Cell type:code id:95fcf64b tags:
``` prolog
``` prolog
set_literal(Lit,Clauses,NewClauses):-
set_literal(Lit,Clauses,NewClauses):-
exclude(becomes_true(Lit),Clauses,Clauses2),
exclude(becomes_true(Lit),Clauses,Clauses2),
maplist(simplify(Lit),Clauses2,NewClauses).
maplist(simplify(Lit),Clauses2,NewClauses).
```
```
%% Cell type:markdown id:f0a8731d tags:
%% Cell type:markdown id:f0a8731d tags:
The predicate ```exclude/3``` from ```library(lists)``` is a higher-order predicate. It maps its first argument (a predicate) over the second argument (a list) and excludes all elements where the predicate succeeds.
The predicate ```exclude/3``` from ```library(lists)``` is a higher-order predicate. It maps its first argument (a predicate) over the second argument (a list) and excludes all elements where the predicate succeeds.
```exclude``` will perform these two calls and hence remove the second clause and keep the first one:
```exclude``` will perform these two calls and hence remove the second clause and keep the first one:
%% Cell type:code id:56175b0d tags:
%% Cell type:code id:56175b0d tags:
``` prolog
``` prolog
?- becomes_true(pos(a),[neg(b)]).
?- becomes_true(pos(a),[neg(b)]).
?- becomes_true(pos(a),[pos(a),pos(c)]).
?- becomes_true(pos(a),[pos(a),pos(c)]).
```
```
%% Output
%% Output
%% Cell type:markdown id:52063b72 tags:
%% Cell type:markdown id:52063b72 tags:
The predicate ```maplist/3``` from ```library(lists)``` is another higher-order predicate. It maps its first argument (a predicate) over the elements in the second and third arguments (both lists).
The predicate ```maplist/3``` from ```library(lists)``` is another higher-order predicate. It maps its first argument (a predicate) over the elements in the second and third arguments (both lists).