Content Summary
Rule order
Target Order
Terminate
Prolog is the first more successful logical programming language. The intrinsic implementation of the logic programming language is simple and attractive: The programmer's job is simply to describe the problem; the programmer should write down the declarative specifications (using the language's logic)
(i.e., a knowledge base) to describe interesting states, facts, and relationships; a programmer should not tell the computer how to do it, and he asks questions to get information, and the logical programming language gives the answer.
However, the above is the ideal situation, the prolog itself is indeed through some important characteristics, in this direction in the effort. But Prolog is not, repeat once, not a complete logical programming language. If you're just thinking in terms of declarative aspects,
Prolog application, then it will be very difficult to use it in practice. As we learned in our previous chapters, Prolog the results of the query in a unique way: it searches the repository from top to bottom, matching the target of each clause from left to right, and
through backtracking is recovered from the error selection. These procedural aspects have an important impact on how your queries actually work. We've seen some examples in their declarative and procedural mismatches (remember P:-P?). ), Next, we
will continue to see that it is easy to define a program that is logically the same, but very different in implementation, in Prolog. Let us consider the following scenario.
Please recall our definition of "younger generation" program, here we call descend1.pl:
Child (Anne, Bridget). Child (Bridget, Caroline). Child (Caroline, Donna). Child (Donna, Emily). Descend (X, Y):- Child (x, y) . Descend (x, y):-Child (X, z), descend (z, y).
Here we make an adjustment, and call the new program for descend2.pl:
Child (Anne, Bridget). Child (Bridget, Caroline). Child (Caroline, Donna). Child (Donna, Emily). Descend (X, Y):- Child (x, z), descend (z, y). Descend (x, y):-Child (x, y).
The changes here just change the order of some of the two rules. So if you just understand it from a purely logical definition, nothing has changed. But does this change make a difference to the program? Yes, but not obviously.
For example, if you query all the cases, you will see that the first answer to descend1.pl is:
X = Anne
Y = Bridget
However, Descend2.pl's first answer was:
X = Anne
Y = Emily
But the two programs generate the same answer, but the order is inconsistent. This is a common denominator. Briefly, changing the order of the rules in the Prolog program does not change the behavior of the program.
We continue, on the basis of descend2.pl, to make a little bit of change, to become descend3.pl:
Child (Anne, Bridget). Child (Bridget, Caroline). Child (Caroline, Donna). Child (Donna, Emily). Descend (X, Y):- descend (z, y), child (X, Z). Descend (x, y):-Child (x, y).
Please note the differences. Here we adjust the order of the targets in a rule rather than adjusting the order of the rules. Now, if we understand purely from a logical definition, and there is no difference, this and the previous two definitions
is the same meaning. But the behavior of the program has changed radically. For example, if we make a query:
?-Descend (Anne, Emily).
Prolog will error (similar to "out of local stack"). Prolog into the dead loop, why? To satisfy query descend (Anne, Emily), Prolog will use the first rule. This means that the next goal is to satisfy the query:
Descend (W1, Emily).
The new variable W1 is introduced here. But to meet this new goal, Prolog will use the first rule, which means that the next target will be: Descend (W2, Emily), which introduces a new variable W2. Of course, it will be recycled into the next
A new target descend (W3, Emily), then descend (W4, Emily), and so on. That is, the change in the order of the target causes the program to crash. Using standard terminology, here we have a classic example of a left recursive rule,
that is, the main part of the skeleton of a rule is the same as the head of the rule at the left end. As our example shows, this rule can result in non-terminating computations. Target order, especially left recursion, becomes the source of all evil when it cannot be terminated .
Also, here is a reminder of the order of the rules. We mentioned earlier that changes in the order of rules will only affect the order of the results of their queries. However, this conclusion is not applicable in the non-terminating procedure. To illustrate this point, please refer to the "younger generation"
The fourth modification of the code, called descend4.pl:
Child (Anne, Bridget). Child (Bridget, Caroline). Child (Caroline, Donna). Child (Donna, Emily).
Descend (x, y):-Child (x, y).
descend (x, y):- descend (z, y), child (X, z).
This program only adjusts the order of the rules on the basis of descend3.pl. Now this program has the same declarative meaning as other previous programs, but there are some procedural differences. First of all, it is clear that, and descend1.pl and
The descend2.pl is significantly different because descend4.pl contains the rules for left recursion, which does not terminate the calculation when some queries are made. For example, if we make the following query, we will not be able to terminate the calculation:
?-Descend (Anne, Emily).
But descend4.pl is also different in procedural and descend3.pl. The difference in rule order results in this discrepancy. For example, descend3.pl is querying:
?-Descend (Anne, Bridget).
Will not terminate, but descend4.pl will have results in this query. Because it will first use non-recursive rules, and find the answer, terminating the calculation. So in a non-terminating program, a change in the order of the rules will result in finding some additional
Solve Solutions. However, the change in the order of the target, rather than the change in rule order, makes the program completely different. In order to ensure that computations can be terminated, we must pay attention to the target order of the rule backbone section. Because the order of the rules is adjusted, no
Change the nature of non-terminating programs--you can find up to a few additional solutions.
To summarize, the above four variants of the "juniors" program describe the same problem, but the implementation is different. descend1.pl and descend2.pl are relatively small in their implementations: they generate the same solution,
But the order is different. However, descend3.pl and descend4.pl differ in their procedural differences from the previous two, because their rules have different order of goals. Specifically, these two versions contain a left recursive rule that results in a non-terminating calculation
Behavior. descend3.pl and descend4.pl differ in rule order, meaning that in some cases descend4.pl can terminate the calculation, but descend3.pl cannot.
So how do we build a useful prolog program? Usually you first need to define the whole idea (blueprint) through declarative thinking, that is, to think about how to accurately describe the problem. This is the first way to solve the problem, but also the soul of logical programming.
but once you have completed this part of the work, you must check your plan in conjunction with the specific implementation of Prolog. In particular, you need to check the order of the targets in the rule to ensure that the calculation terminates. Rule never writes the skeleton of the rule to the leftmost target and the rule head
In the same situation, the target that triggers the recursion should be written to the far right of the trunk, that is, the recursive target appears behind all non-recursive targets. Doing so will give Prolog the most opportunity to find the answer without recursion.
Learn Prolog now Translations-Chapter III-Recursion-second section, rule order, target order, termination