CLIPS & Prolog
Download
Please download the following files containing simple knowledge bases about a family:
Knowledge Bases
Both files have corresponding content:
In addition, files contain a single rule defining the child relation.
1. Loading The Facts
After downloading the files, they have to be loaded into corresponding Knowledge Bases (KB):
CLIPS:
(load family_en.clp)
If everything was loaded correctly, you should a feedback similar to:
Defining deffacts: initial-facts
Defining defrule: child +j
TRUE
The TRUE is the most important part of this feedback. If FALSE appears, it means that loading failed.
Prolog:
[family].
The succesful loading should display something similar to:
% family compiled 0.01 sec, 9,232 bytes
true.
Notice the true again.
2. Display the KB
To view the contents of the KB, enter:
3. Inference
CLIPS uses the forward-chaining. The inference is implemented as a loop, that checks what rules can be executed based on the current state of the KB. Then the found rules are executed and the cycle repeats. The loop ends when it fails to find a rule to execute. The input of the forward-chaining algorithm is the set of facts in the knowledge base.
To check what rules are ready to be run, type
(agenda)
What rules are ready to run?
What facts trigger these rules?
How to explain the result?
To run the inference process, type
(run)
In Prolog we use backward-chaining and the process is inverted. The input of this algorithm is target — fact that we want to infer. We may say that this a goal-oriented approach. Let's ask:
What women are included in the knowledge base:
woman(X).
With the ;
key, we can continue to list all the possible answers of the inference. If you want to interrupt, press „enter”.
What pairs of type (mom, child) are included in the KB:
mother(Mom, Child).
What children does Dariusz have?
father(dariusz, Child).
What are the names of all the fathers:
father(Father, _).
What sons does Dariusz have:
father(dariusz, Son), man(Son).
4. How to use Rules
Both files contain a rule defines who/what is a child.
CLIPS failed to start this rule (previous point). In Prolog, we can query using this rule:
child(X, Y).
Run the above query and …
describe what happened?
Has the situation been analogous to that in CLIPS?
Does the rule in CLIPS failed because of the same reason?
5. Creating Rules
In order to run the child rule, we have to define:
In CLIPS: a rule that adds a parent to the knowledge base (changing the knowledge base will trigger the next inference cycle):
(defrule parent
(or (mother ?x ?y) (father ?x ?y))
=>
(assert (parent ?x ?y))
)
In Prolog: a rule defining a relationship (child, parent):
parent(X, Y) :-
father(X, Y).
parent(X, Y) :-
mother(X, Y).
It is worth noting that in the case of Prolog, we define two rules. One can assume that there is a conjuction (OR) between these two rules.
Repeat steps:
How many facts are there in the CLIPS database?
What are the active rules in CLIPS?
Why is the child rule inactive?
5.1. Adding Knowledge to the KB
5.1.1. Son and daughter
We can try now to supplement the current KB with new rules, that define other relationships:
5.1.2. Marriage
The knowledge base can also be supplemented by a rule defining marriage. With existing facts and rules, you can define that two people are married if:
are different sex,
have a common child.
This rule will cause the inference to omit the childless couples. In order to define the proper notion of marriage, KB would have to be supplemented with additional facts (what facts?)
5.1.3. Other
Knowing that the concepts brother is defined as follow:
CLIPS:
(defrule brother
(siblings ?x ?y)
(man ?x)
=>
(assert (brother ?x ?y))
)
Prolog:
brother(X, Y) :-
siblings(X, Y),
man(X).
Define the following rules:
siblings(X,Y) — two different people with a common parent;
sister(X,Y)
grandfather(X,Y)
grandmother(X,Y)
grandparent(X,Y) — tip: use OR
cousins(X,Y) — two different people with a common grandparent. You can check this rule in Prolog with a query:
cousins(X,Y), parent(R,X), parent(R, Y)
, it should return false
aunt(X,Y) and uncle(X,Y) in terms of sister, brother and parent.
half-orphan(X) — a person with only one parent. TIP: celina is the only half-orphan in the KB
widow(X) (and widower(X)) — assume that all the single-parents are single because of the spouse's death. TIP: tobiasz is the only widower in the KB, there are no widows. In CLIPS you may check results of the following rule:
(defrule widower
...
=>
(assert (widower ?x))
(printout t ?x " is widower" crlf)
)
. Do you get the expected result?
6. Tracking the execution of the program
Since CLIPS doesn't correctly find the widowers, it is necessary to track the execution of the program:
6.1. Tracking the facts
Allows you to track operations on facts: add, delete, change of the value.
In the first step, we will start observing the
widower rule to see what triggers it:
(watch rules widower)
We reset the fact base:
(reset)
Restart the inference:
(run)
Now we see the triggers and indexes of facts from which we started.
Now check which fact triggered the inference:
(facts)
6.2. Rule tracking
Allows tracking of rules: firing, activation.
Because we did learn nothing interesting tracing the fact, we will follow the
widow rule and all the rules it depends on:
parent,
marriage:
(unwatch all)
(watch rules marriage widow parent)
Now we reset the fact base:
(reset)
Restart the inference:
(run)
What is the reason behind the malfunction of the widower rule?
How can we fix it?
6.3. Tracking in Prolog
Prolog allows you to follow the program. To do so, you set the so-called. trace point.
Trace points:
?- trace, woman(K), parent(K, _).
trace/1 - sets the trace point at the indicated predicate,
trace/2 - modifies trace point of the specific events (call, redo, exit, fail), eg:
remove the trace point from the specified predicate
something/1 trace(something/1, -all)
set a trace point tracking only calls to the specified predicates
something of arbitrary arity.
trace(something, call +)
Predicate debugging/0
lists all the set trace points.
The debug/0
predicate activates debug mode.
Predicate nodebug/0
disactivates debug mode.
Check following code:
?- trace(parent).
[debug] ?- trace(mother).
[debug] ?- trace(father)
[debug] ?- parent(dariusz, tomasz).
[debug] ?- nodebug.