Main control decisions: Rule/Fact Order and Goal Order.
Rules/Facts
Goals
Rule/fact order: Given a program with a collection of facts and rules, in which order do you choose to pick a rule/fact to unify.
Goal order: Given a set of goals in a query to resolve, which goal do you choose
Rule/fact order and goal order influence program behaviour.
<-------X-------->
+-------------------------------+
| | S | |
+-------------------------------+
<--------------Z---------------->
prefix X of Z and suffix S of X.
The corresponding prolog rules are:
append([],Q,Q).
append([H | P], Q, [H | R]) :- append(P, Q, R).
prefix(X,Z) :- append(X,Y,Z).
suffix(Y,Z) :- append(X,Y,Z).
Usually produce the same result:
?- prefix(S,[a,b,c,d]), suffix(S,[a,b,c]).
?- suffix(S,[a,b,c]), prefix(S,[a,b,c,d]).
Their answers however differ in other cases:
?- prefix(X,[b]), suffix([a],X).
?- suffix([a],X), prefix(X,[b]).
Recall the definition append
.
append([],Q,Q).
append([H | P], Q, [H | R]) :- append(P, Q, R).
Consider the definition appen2
which reorders the rules from append
.
appen2([H | P], Q, [H | R]) :- appen2(P, Q, R).
appen2([],Q,Q).
Consider the query:
?- append(X,[c],Z) {5}.
?- appen2(X,[c],Z) {1}.
We can precisely define the influence of rule orders and goal orders by describing an abstract interpreter for logic programs.
First, we will start off with some definitions of ideas that we have informally seen earlier.
A substitution is a finite set of pairs of terms $\{X_1/t_1, \ldots, X_n/t_n\}$ where each $t_i$ is a term and each $X_i$ is a variable such that $X_i \neq t_i$ and $X_i \neq X_j$ if $i \neq j$.
The empty substitution is denoted by $\epsilon$.
For example, $\sigma = \{X/[1,2,3], Y/Z, Z/f(a,b)\}$ is substitution.
Is this a valid substitution?
$$ \{X/Y,Y/X,Z/Z,A/a1,A/a2,m/n\} $$Is this a valid substitution?
$$ \sigma = \{X/Y,Y/X,Z/Z,A/a1,A/a2,m/n\} $$No.
The application of substitution $\sigma$ to a variable $X$, written as $X\sigma$ is defined
$$ X\sigma = \begin{cases} t \text{ if } X/t \in \sigma \\ X \text{ otherwise} \end{cases} $$Let $\sigma$ be a substitution $\{X_1/t_1, \ldots, X_n/t_n\}$ and $E$ a term or a formula. The application $E\sigma$ of $\sigma$ to $E$ is obtained by simultaneously replacing every occurrence of $X_i$ in E with $t_i$.
Given $\sigma = \{X/[1,2,3], Y/Z, Z/f(a,b)\}$ and $E = f(X,Y,Z)$, $E\sigma = f([1,2,3],Z,f(a,b))$.
Now, $E\sigma$ is known as an instance of $E$.
At the core of how Prolog computes is Unification, which is based on Substitution.
There are 3 rules for unification:
Which of these unify?
Which of these unify?
Let $S$ and $T$ be two terms. A substitution $\sigma$ is a unfier for $S$ and $T$ if $S\sigma$ and $T\sigma$ are syntactically equal.
Let $S = f(X,Y)$ and $T = f(g(Z),Z)$. Let $\sigma = \{X/g(Z), Y/Z\}$. $\sigma$ is a unfier for $S$ and $T$.
A pair of terms may have more than one unifier. For example, for the terms $f(X,X)$ and $f(Y,Z)$, the unifiers $\theta = \{X/Y,Z/Y\}$ and $\sigma = \{X/Z,Y/Z\}$ are both unifiers.
What is a unifier of $f(P,P,Q)$ and $f(Q,R,a)$
What is a unifier of $f(P,P,Q)$ and $f(Q,R,a)$
Input: Two terms $X$ and $Y$ to be unified and a unifier $\theta$.
Output: $\theta$, a unifier that unifies $X$ and $Y$ or raises FAIL exception.
Example: unify( $f(P,P,Q)$, $f(Q,R,a)$ ) = $\{P/a,Q/a,R/a\}$.
unify(X,Y,𝜃) =
X = X𝜃
Y = Y𝜃
case
X is a variable that does not occur in Y:
return (𝜃{X/Y} ∪ {X/Y}) /*replace X with Y in the substitution terms of 𝜃 add X/Y to 𝜃*/
Y is a variable that does not occur in X:
return (𝜃{Y/X} ∪ {Y/X}) /*replace Y with X in the substitution terms of 𝜃 add Y/X to 𝜃*/
X and Y are indentical constants or variables:
return 𝜃
X is f(X1,...,Xn) and Y is f(Y1,...,Yn):
return (fold_left (fun 𝜃 (X,Y) -> unify(X,Y,𝜃))
𝜃 [(X1,Y1),...,(Xn,Yn)])
otherwise:
raise FAIL
}
let unify(X,Y) = unify(X,Y,ϵ)
Input: A goal Goal and a program P
Output: An instance of Goal that is a logical consequence of P.
Resolvent (a list) used for maintaining goals or subgoals that the interpreter needs to solve.
Input: A goal Goal and a program P
Output: An instance of Goal that is a logical consequence of P.
Algorithm: run(P,Goal)
L: G = Goal
Initialise resolvent to G.
while (the resolvent is not empty) {
choose a goal A from the resolvent //random goal
choose a (renamed) clause A' <- B1,...,Bn from P
such that A and A' unify with a unifier 𝜃 // random rule
(if no such goal and clause exist, exit the while loop).
replace A by B1,...,Bn in the resolvent
apply 𝜃 to the resolvent and G
}
If the resolvent is empty, then output G, else goto L.
Consider the program:
plus(1,3,4).
plus(2,2,4).
even(2).
and the goal plus(X,Y,4), even(X)
.
plus(2,2,4)
and plus(1,3,4)
unify with plus(X,Y,4)
. plus(2,2,4)
ensures that the second goal even(X)
is satisfied. plus(2,2,4)
, which will lead to success without failure.Consider the program:
plus(1,3,4).
plus(2,2,4).
even(2).
odd(1).
and the goal plus(X,Y,4), even(X)
.
OTOH, if the second goal even(X)
is chosen as the first to resolve, then it will only unify with even(2)
, which will change the other goal to plus(2,Y,4)
which leaves only one choice.
Non-determinism is essential for correctness.
Which of these unify?
Consider the query
append([],Q,Q).
append([H | P], Q, [H | R]) :- append(P, Q, R).
?- append([],E,[a,b|E]).
goes down an infinite search path.
Exercise: Trace by hand to verify why.
Consider the query
?- append([],E,[a,b | E]).
append([],Q,Q)
, we will unify E = [a,b | E]
, whose solution is E = [a,b,a,b,a,b,...]
.E
appears on the RHS term.You can explicitly turn on occurs check in SWI Prolog.
?- set_prolog_flag(occurs_check,true).
?- append([],E,[a,b | E]).
You can explicitly turn occurs check in SWI Prolog to an error.
?- set_prolog_flag(occurs_check,error).
?- append([],E,[a,b | E]).