What is the Prolog interpreter doing during the process of deduction (replying to a query or searching to achieve a goal)?
A Prolog program is consulted and the facts and rules in the program are loaded into the knowledge database.
When a query or goal is given, the Prolog interpreter seaches the knowledge database from top to bottom to find any facts or rules match with the query or goal.
If a match is found, the search for answers to the query succeeds or the goal is true. The values of any variables found are given.
If the user asks for further solutions (e.g by entering a semicolon in some Prolog interpreter), the Prolog interpreter continues searching. It keeps track of the facts and the rules which have been searched. When it can find no more solutions, it says no and the search ends.
The Prolog interpreter starts with the goal/query and works backward by identifying the facts and the rules (in the knowledge database) from which the goal can be derived. This can be done by the expansion of a goal by applying a rule and the reduction of a goal by applying a fact. You will see the process of deduction in the example below.
Unification is the derivation of a new rule from a given rule through the binding of variables.
In order to match a goal or a query, any variable encountered is substituted with the value of an appropriate constant (called binding).
Sometimes there are more than one fact/rule which can be applied to a goal/query. In this case, the fact/rule which appears first in the knowledge database will be applied first. The other applicable facts or rules will be applied later such that all possible solutions are found. This process is known as backtracking.
We will use the following program and some queries to explain the process of deduction.
Note: In each step of the process of deduction, there may be more than one subgoals to be processed. In this case, only the first subgoal is considered. If there is a rule that can be applied to it, it is replaced by those subgoals found in the applied rule. If it satisfies a fact, it is removed. If no rules or facts can be applied, we have to backtrack.
Level | Results of deduction | Rules or facts to be applied | Bindings of variables | |
---|---|---|---|---|
Original goal | can_use(judy, vb).
|
P = judy SW = vb |
||
1 | access(judy, Comp), can_run(Comp, vb).
|
Comp = comp1 | ||
2 | can_run(comp1, vb). | - |
||
3 | spec(comp1, CompType, MemAvail), runs(CompType, vb, MemNeeded), MemAvail >= MemNeeded. |
CompType = pc MemAvail = 32 |
||
4 | runs(pc, vb, MemNeeded), 32 >= MemNeeded. |
MemNeeded = 16 | ||
5 | 32 >=16.
|
Satisfied! Output: yes |
||
Overall output | yes |
This goal demonstrates backtracking.
Level | Results of deduction | Rules or facts to be applied | Bindings of variables | |
---|---|---|---|---|
Original goal | can_use(david, prolog). | P = david SW = prolog |
||
1 | access(david, Comp), can_run(Comp, prolog).
|
Comp = comp1 | ||
2 | can_run(comp1, prolog). | - |
||
3 | spec(comp1, CompType, MemAvail), runs(CompType, prolog, MemNeeded), MemAvail >= MemNeeded. |
CompType = pc MemAvail = 32 |
||
4 | runs(pc, prolog, MemNeeded), 32 >= MemNeeded.
|
Failed! Backtracks. | ||
3 | spec(comp1, CompType, MemAvail), runs(CompType, prolog, MemNeeded), MemAvail >= MemNeeded.
|
Failed! Backtracks. | ||
2 | can_run(comp1, prolog). | Failed! Backtracks. | ||
1 | access(david, Comp), can_run(Comp, prolog).
|
Comp = comp2 | ||
2 | can_run(comp2, prolog). | - |
||
3 | spec(comp2, CompType, MemAvail), runs(CompType, prolog, MemNeeded), MemAvail >= MemNeeded. |
CompType = mac MemAvail = 128 |
||
4 | runs(mac, prolog, MemNeeded), 128 >= MemNeeded. |
MemNeeded = 128 | ||
5 | 128 >= 128. | Satisfied! Output: yes |
||
Overall output | yes |
This query demonstrates how backtracking is done to find all answers.
Level | Results of deduction | Rules or facts to be applied | Bindings of variables | |
---|---|---|---|---|
Original query | can_use(judy, X). | P = judy | ||
1 | access(judy, Comp), can_run(Comp, X). | Comp = comp1 | ||
2 | can_run(comp1, X). | - |
||
3 | spec(comp1, CompType, MemAvail), runs(CompType, X, MemNeeded), MemAvail >= MemNeeded. |
CompType = pc MemAvail = 32 |
||
4 | runs(pc, X, MemNeeded), 32 >= MemNeeded. |
Fact 4 | X = movie_edit MemNeeded = 96 |
|
5 | 32 >= 96. | Failed! Backtracks. |
||
4 | runs(pc, X, MemNeeded), 32 >= MemNeeded. |
Fact 5 | X = vb MemNeeded = 16 |
|
5 | 32 >= 16.
|
Satisfied! |
||
4 | runs(pc, X, MemNeeded), 32 >= MemNeeded. |
Fact 6 | X = cpp MemNeeded = 28 |
|
5 | 32 >= 28. | Satisfied! Output: X = cpp Then backtracks. |
||
4 | runs(pc, X, MemNeeded), 32 >= MemNeeded. |
Failed! Backtracks. | ||
3 | spec(comp1, CompType, MemAvail), runs(CompType, X, MemNeeded), MemAvail >= MemNeeded. |
Failed! Backtracks. | ||
2 | can_run(comp1, X). | Failed! Backtracks. | ||
1 | access(judy, Comp), can_run(Comp, X). | Failed! Backtracks. | ||
Original query | can_use(judy, X). | Failed! Since the top level is reached, all answers are found. |
||
Overall output | x = vb x = cpp |
Backtracking has to be performed before concluding that there is no answer to a query.
Level | Results of deduction | Rules or facts to be applied | Bindings of variables |
---|---|---|---|
Original query | can_use(X, movie_edit). | SW = movie_edit | |
1 | access(X, Comp), can_run(Comp, movie_edit). | X = judy Comp = comp1 |
|
2 | can_run(comp1, movie_edit). | - |
|
3 | spec(comp1, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
CompType = pc MemAvail = 32 |
|
4 | runs(pc, movie_edit, MemNeeded), 32 >= MemNeeded. |
Fact 4 | MemNeeded = 96 |
5 | 32 >= 96. | Failed! Backtracks. | |
4 | runs(pc, movie_edit, MemNeeded), 32 >=MemNeeded. |
Failed! Backtracks. | |
3 | spec(comp1, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
Failed! Backtracks. | |
2 | can_run(comp1, movie_edit). | Failed! Backtracks. | |
1 | access(X, Comp), can_run(Comp, movie_edit). | X = peter Comp = comp3 |
|
2 | can_run(comp3, movie_edit). | - |
|
3 | spec(comp3, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
CompType = pc MemAvail = 64 |
|
4 | runs(pc, movie_edit, MemNeeded), 64 >= MemNeeded. |
Fact 4 | MemNeeded = 96 |
5 | 64 >= 96. | Failed! Backtracks. | |
4 | runs(pc, movie_edit, MemNeeded), 64 >=MemNeeded. |
Failed! Backtracks. | |
3 | spec(comp3, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
Failed! Backtracks. | |
2 | can_run(comp3, movie_edit). | Failed! Backtracks. | |
1 | access(X, Comp), can_run(Comp, movie_edit). | X = david Comp = comp1 |
|
2 | can_run(comp1, movie_edit). | - |
|
3 | spec(comp1, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
CompType = pc MemAvail = 32 |
|
4 | runs(pc, movie_edit, MemNeeded), 32 >= MemNeeded. |
Fact 4 | MemNeeded = 96 |
5 | 32 >= 96. | Failed! Backtracks. | |
4 | runs(pc, movie_edit, MemNeeded), 32 >=MemNeeded. |
Failed! Backtracks. | |
3 | spec(comp1, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
Failed! Backtracks. | |
2 | can_run(comp1, movie_edit). | Failed! Backtracks. | |
1 | access(X, Comp), can_run(Comp, movie_edit). | X = david Comp = comp2 |
|
2 | can_run(comp2, movie_edit). | - |
|
3 | spec(comp2, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
CompType = mac MemAvail = 128 |
|
4 | runs(mac, movie_edit, MemNeeded), 128 >= MemNeeded. |
Failed! Backtracks. |
|
3 | spec(comp2, CompType, MemAvail), runs(CompType, movie_edit, MemNeeded), MemAvail >= MemNeeded. |
Failed! Backtracks. | |
2 | can_run(comp2, movie_edit). | Failed! Backtracks. | |
1 | access(X, Comp), can_run(Comp, movie_edit). | Failed! Backtracks. | |
Original query | can_use(X, movie_edit). | Failed. The top level is reached and no answers have been
found. Output: no |
|
Overall output | no |