0% found this document useful (0 votes)
41 views17 pages

Rule Based Programming: 3rd Year, 2nd Semester

Prolog Tutorial Prolog Tutorial Prolog Tutorial Prolog Tutorial Prolog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog Tutorial

Uploaded by

Dany Daniel
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views17 pages

Rule Based Programming: 3rd Year, 2nd Semester

Prolog Tutorial Prolog Tutorial Prolog Tutorial Prolog Tutorial Prolog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog TutorialProlog Tutorial

Uploaded by

Dany Daniel
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Rule Based Programming

3rd year, 2nd semester

Horn clauses
Deductive systems
PROLOG inference engine
PROLOG cuts and recursion
Propositional logic
The syntax of propositional logic: you can prove a well formed formula 𝜎: (p→r) as a
consequence of a set of formulas F: (p→r)∧(r→ q) using implicit properties/rules
(deductive reasoning): F ⊢ 𝜎

The semantics of propositional logic: you can prove that a well formed formula is TRUE if
a set of F of formulas are TRUE: F ⊨ 𝜎 . This might not be equivalent to F ⊢ 𝜎 !

If the logical system is sound then we can say that if F ⊢ 𝜎 then F ⊨ 𝜎. If the logical system
is complete then we can say that if F ⊨ 𝜎 then F ⊢ 𝜎.

A system (model) is sound if you can’t use it to prove something that is wrong.
Consider a deduction system built to check whether any statement is TRUE or
FALSE. If every claim made by the system is accurate (is provable following logical
reasoning from the known facts) then the system is sound.

A system is complete if it can prove as true or false every statement. If for all possible
statements the system answers TRUE or FALSE, the system is complete.

A system can be sound and not complete: assign value of TRUE only to tautologies. A
system can be complete and not sound: assign value of TRUE to every input
statement.

A parallel can be made to statistical evaluation metrics: if a system has 100%


accuracy, it’s sound. If it has 100% recall, it’s complete.
Gödel theorems
First completeness theorem: If a formula is logically valid then there is a finite deduction (a formal proof) of the
formula. This means that we can solve anything is exponential time (SAT problem).

Proving that you can prove the validity of a formula (check the truth value of a formula for a model - assignment of
values for variables - in the truth table) in polynomial time would make you the most famous student of our faculty
ever. Every problem can be described as a formula, checking the correct answer can be done in polynomial time (P
problems). If that answer can also be proved (deducted from the available data) in polynomial time, then P=NP (see
Artificial Intelligence course 2).

First incompleteness theorem: Any consistent formal system F within which a certain amount of elementary arithmetic
can be carried out is incomplete; i.e., there are statements of the language of F which can neither be proved nor
disproved in F. Thus no (useful) open world deductive system is complete. Example: “This statement is false.”

Is there a way to use first-order logic for inference rules to build a deduction engine, well formed formulas to model a
knowledge base, and still get a complete system? Logic programming requires a sound and complete system,
otherwise it’s just CLIPS.

A system (model) is sound if you can’t use it to prove something that is wrong.
Consider a deduction system built to check whether any statement is TRUE or
FALSE. If every claim made by the system is accurate (is provable following logical
reasoning from the known facts) then the system is sound.

A system is complete if it can prove as true or false every statement. If for all possible
statements the system answers TRUE or FALSE, the system is complete.

A system can be sound and not complete: assign value of TRUE only to tautologies. A
system can be complete and not sound: assign value of TRUE to every input
statement.

A parallel can be made to statistical evaluation metrics: if a system has 100%


accuracy, it’s sound. If it has 100% recall, it’s complete.
Horn clauses (I)
A formula using at most one non-negated (positive) symbol: r∨¬p
Almost every WFF can be written as a Horn clause. r∨¬p is a rewrite of p→r
Almost every, but not all: ((p∧q)∧(p→q))→q

A definite clause is a Horn clause with exactly one positive symbol.


A goal is a Horn clause with all symbols negated.

Definite clauses are rules in PROLOG. (¬p1∨¬p2∨¬p3∨...∨¬pn∨q)


Goals are queries in PROLOG. (¬p1∨¬p2∨¬p3∨...∨¬pn)
Atoms (symbols) are facts in PROLOG. (p)
Horn clauses (II)
p1∧p2∧p3∧...∧pn→q is equivalent to ¬p1∨¬p2∨¬p3∨...∨¬pn∨q which is a definite
clause

¬p1∨¬p2∨¬p3∨...∨¬pn∨q reads as:


If neither ¬p1 nor ¬p2 nor ¬p3 nor … nor ¬pn nor q are true, the result is false. Which means
that if at least one is true, the result is true. Check all conditions until you find one that is
true, in which case the result is false. If all have been tested and no check succeeded, the
result is true.

A goal has all symbols negated, thus ¬p1∨¬p2∨¬p3∨...∨¬pn succeeds (is true) only if
none of the checks succeeds, thus none of p1, p2, p3,... pn can be found (asserted) as false.
Inference rules over Horn clauses
OK, now what?

Two inference rules are sound and complete over Horn clauses:
● Resolution:
A∨B, ¬B∨C
A∨C
● Modus ponens:
B→A, B
A
These two inference rules are the basis of PROLOG’s inference engine. As long as A, B and
C are Horn clauses and the query can be deducted by applying unit resolution and modus
ponens, that deduction is logically valid and the system is sound and complete.
SLD deduction
SLD (Selective Linear Definite) clause resolution is the main inference rule in PROLOG, an adaptation of unit
resolution specific for Horn clauses.

mortal(X) :- human(X).
human(socrates).

?- mortal(Who).
Who=socrates
Yes

Why?
Because human(X)→ mortal(X) is equivalent to mortal(X)∨¬human(X) . But we also know that human(socrates). If X
is unified with socrates (and it has to be in order to infer something from both assertions), then we know that
mortal(socrates)∨¬human(socrates)∧human(socrates). Since ¬human(socrates)∧human(socrates) is false, this
means that mortal(socrates) is true.
Backchain deduction
This is the actual algorithm run by the PROLOG inference engine (the equivalent of RETE for CLIPS). This is a
backward chaining algorithm, as opposed to forward chaining in CLIPS.

Solve (q1,q2,q3,...,qn)
\\the list of queries (goals)
{
if n=0 return TRUE;
\\if no queries remain to be checked stop with TRUE
else
foreach k in KB
\\for each rule in the KB described as a definite Horn clause
if (k=(q1,¬p1, ¬p2, ¬p3,...,¬pm) ) with the first goal on the left side
and (Solve(p2, p3,...,pm,q2,q3,...,qn))
return TRUE; \\add the conditions of that rule to the list of goals to be
endfor; proven and call recursively this function for all goals except
return FALSE; the first one
}
The PROLOG inference engine
If the KB has no applicable inference rules for the input set of goals, the algorithm will never stop. Why? Because the
deduction has to be sound and can’t assert any knowledge it cannot actually prove - open world assumption.
HOWEVER: PROLOG doesn’t actually do this, it adopts “negation as failure” meaning that it will stop with FALSE if
no further inference can be applied and the goal was not proven - closed world assumption.

Also, the PROLOG inference engine doesn’t perform occur-checks (doesn’t check if a variable is unified with a
field/formula in which it appears). For example,

?- X=f(X)
TRUE
X=f(**)

which is false. The output should be false, but since inferences can still be applied and the goal was not proven (thus
“negation as failure” doesn’t work), to avoid infinite loops, PROLOG marks the solution as **. This is the main issue
with PROLOG proofs, and has to be carefully managed: https://core.ac.uk/download/pdf/82595056.pdf
p(X)
PROLOG engine at work 1 3
2
1. p(a). TRUE
2. p(X) :- q(X), r(X). q(X),r(X) u(x)
X=a
3. p(X) :- u(X).
4. q(X) :- s(X). 4 10
5. r(a). TRUE
6. r(b). s(X),r(X)
X=d
7. s(a). 7 9
8
8. s(b).
9. s(c). r(a) r(b) r(c)
10. u(d).
5 6 5 5,6
6
?-p(X)
TRUE FALSE FALSE
X=a TRUE
X=b

Starting from the goal, it looks for facts or rules with the goal on the left
side. It finds 3 cases (first 3 lines in the code) and follows each of them.
The first (1) leads to immediate truth since it can unify X with a. The
seconds leads to another goal to be searched (the recursive call to the
backchain function), which is q(X),r(X). It can’t find an unnification for q,
so it looks for rules with q in the left side. It finds line 4 and sets a new
goal: s(X),r(X). If it unifies X with a (line 7), it can also satisfy r(X) - line
5 and it outputs TRUE. If it unifies X with b (line 8), then the unification
is not satisfied by the same fact (line 5) but by another (line 6). If it unifies
X with c (line 9) it cannot validate r(c) and fails.
Lets see it working
ancestor(X,Y) :- child_of(X,Y).
ancestor(X,Z) :- ancestor(_Y,Z), child_of(X,_Y).

Or

ancestor(X,Z) :- ancestor(_Y,Z), child_of(X,_Y). ancestor(X,Y) :-


child_of(X,Y).

Try both to see how the order influences the inference engine.
To see all recursions use:

?- trace.
PROLOG cuts
p :- q1,…, qk, !, qk+1, …, qn.

?- A.

Tries to check A by unifying it with p and testing q1,…, qk, !, qk+1, …, qn. If q1,…, qk are satisfied (up
to !), the unification is locked to p. No other possible branches are made in the backchain algorithm (it will not go
back to alternative recursions). The checks after ! are performed normally.

For example, if we replace line 2 in the previous example with p(X) :- q(X),!, r(X), then only the first
answer found in that branch is provided. After it unifies X with a it reaches ! and no longer checks other alternatives
for unification in q(X).

Careful usage of cuts is recommended. It can make the inference engine significantly faster but it skips some branches
which might have the expected result.
PROLOG lists (I)
To use lists add elements between brackets:

[1,2,3,4]

Define sublists between parenthesis:

[(1,2),(3,4)] is a matrix with two lines and two columns

Length of a list:

size([],0).
size([H|T],N+1) :- size(T,N).

?- size([1,2,3,4],N).
PROLOG lists (II)
List membership:

member(X,[X|_]).
member(X,[_|T]) :- member(X,T).

?- member(2,[1,2,3,4]).

Reverse a list:

rev(List, Reversed) :- rev(List, [], Reversed).


rev([], Reversed, Reversed).
rev([Head|Tail], Rest, Reversed) :- rev(Tail, [Head|Rest], Reversed).

?- rev([1,2,3,4],R).
PROLOG lists (III)
Sorting a list with (a kind of) bubblesort:

bsort(X,Y) :- perm(X,Y), sorted(Y).


sorted([]).
sorted([X|[]]).
sorted([X|[Y|Z]]) :- X @=< Y, sorted([Y|Z]).
perm([],[]).
perm([X|Y],[U|V]) :- delete(U,[X|Y],Z), perm(Z,V).
delete(X,[X|Y],Y).
delete(X,[Y|Z],[Y|W]) :- delete(X,Z,W).

?- bsort([1,5,4,2],S).

X @=< Y is true only if X<Y


PROLOG negation
not(X=Y)

The above is true only if X=Y cannot be proven, not if X=Y is explicitly false.

Alternative: X\+Y

Alternative for difference in unified values:

not-equals(X, Y)

Remember that PROLOG uses “negation-as-failure”, this is likely to cause problems when checking negatives!
Next week
Built-in goals

Graphs

PROLOG good practices

Sample problems

You might also like