Prolog - Explain trace steps in English

岁酱吖の 提交于 2019-12-24 11:48:09

问题


plays(alice, leadguitar).
plays(noah, drums).
plays(mike, leadguitar).
plays(mike, drums).
plays(katie, baseguitar).
plays(drew, leadguitar).
plays(drew, baseguitar).

duetwith(Person1,Person2):- 
    plays(Person1,L),
    plays(Person2,L), 
    Person1 \= Person2.

I write a new rule called combo that determines whether or not three people can make a combo with a drummer, a base guitar, and a lead guitar.

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

Can drew, alice, and mike make a combo?

combo(mike,alice,drew).

true so the answer is yes they can make a combo.

I need help understanding the steps the program takes to answer the above query in prolog. Any help with a list of steps is greatly appreciated so I can gain a deeper understanding of each step Prolog takes.

Here is an example of a list of steps Prolog takes for a different example just to give an idea of what I am looking for.

In the case of talkswith(bob,allen), the engine took the following steps:

  1. In

    talkswith(Person1,Person2):- speaks(Person1,L), speaks(Person2,L), Person1 \= Person2.

replace every occurrence of Person1 with bob and Person2 with allen to get

talkswith(bob,allen) :- 
    speaks(bob,L),
    speaks(allen,L),
    bob \= allen.
  1. Let’s see if we can find a value for L that makes the right side true. Start with speaks(bob,L). What can L be? Here are our facts:

    1. speaks(allen, russian).
    2. speaks(bob, english).
    3. speaks(mary, russian).
    4. speaks(mary, english).
  2. In fact 1, the first slot isn’t bob, so that won’t work. In fact 2, the first slot is bob, so let’s try L = englishin speaks(allen,L), bob \= allen. Now we are asking speaks(allen,english), bob\= allen.

  3. Back to the knowledge base. Does speaks(allen,english) match a fact? Not fact 1, not fact 2, not fact 3, not fact 4. This fails.
  4. Now we back up to step 2. Fact 2 didn’t work out, so let’s try fact 3. No, that isn’t bob. Fact 4 isn’t bob either. We can’t find a value for L that works, so the search failed.

回答1:


replace every occurrence of Person1 with bob

Prolog uses syntactic unification which never does replacement. A free variable can only be bound once to a value. If it looks like a variable is being changed more than once, it is not. There can be many stack frames and for each stack frame a new set of variables can be created.


Trace is somewhat helpful but I need to translate that into the form of the example above with the steps written out and explained in plain English.

For these facts

plays(alice, leadguitar).
plays(noah, drums).
plays(mike, leadguitar).
plays(mike, drums).
plays(katie, baseguitar).
plays(drew, leadguitar).
plays(drew, baseguitar).

and this predicate

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

and this query

combo(mike,alice,drew).

First read SWI-Prolog Debugging and Tracing Programs

Run the query with trace, unify port enabled and leashing off.

?- visible(+unify).
true.

?- leash(-all).
true.

?- trace.
true.

[trace] ?- combo(mike,alice,drew).
   Call: (8) combo(mike, alice, drew)
   Unify: (8) combo(mike, alice, drew)
   Call: (9) plays(mike, _7040)
   Unify: (9) plays(mike, leadguitar)
   Exit: (9) plays(mike, leadguitar)
   Call: (9) plays(alice, _7040)
   Unify: (9) plays(alice, leadguitar)
   Exit: (9) plays(alice, leadguitar)
   Call: (9) plays(drew, _7040)
   Unify: (9) plays(drew, leadguitar)
   Exit: (9) plays(drew, leadguitar)
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(drew, _7040)
   Unify: (9) plays(drew, baseguitar)
   Exit: (9) plays(drew, baseguitar)
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(mike, _7040)
   Unify: (9) plays(mike, drums)
   Exit: (9) plays(mike, drums)
   Call: (9) plays(alice, _7040)
   Unify: (9) plays(alice, leadguitar)
   Exit: (9) plays(alice, leadguitar)
   Call: (9) plays(drew, _7040)
   Unify: (9) plays(drew, leadguitar)
   Exit: (9) plays(drew, leadguitar)
   Call: (9) drums\=leadguitar
   Exit: (9) drums\=leadguitar
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(drew, _7040)
   Unify: (9) plays(drew, baseguitar)
   Exit: (9) plays(drew, baseguitar)
   Call: (9) drums\=leadguitar
   Exit: (9) drums\=leadguitar
   Call: (9) leadguitar\=baseguitar
   Exit: (9) leadguitar\=baseguitar
   Call: (9) drums\=baseguitar
   Exit: (9) drums\=baseguitar
   Exit: (8) combo(mike, alice, drew)
true.

Call: (8) combo(mike, alice, drew)

Prolog looks for a predicate that matches the query. When Prolog looks for a predicate it searches by predicate name, in this case combo, and arity, in this case 3 and finds only one predicate with one clause. Prolog also searches for predicates in the order they appear in the source code. There is more to it (indexing) but that level of detail is not needed to explain this simple query.


Unify: (8) combo(mike, alice, drew)

Once Prolog has found a clause/fact based on predicate name and arity it checks that the query and head of the clause or fact can be unified.

mike unifies with Person1. Person1 is now bound to mike.
alice unifies with Person2. Person2 is now bound to alice.
drew unifies with Person3. Person3 is now bound to drew.


Call: (9) plays(mike, _7040)

If the previous statement unifies, then the next statement is called. Each statement is a query in itself. So running the query plays(mike,X). as a stand alone query is the same as this statement in the clause. There are many facts for plays/2 and two of them match plays(mike,X). Prolog uses the first one it finds, however since there are more than one, a choice point is made. We will call this specific choice point plays(mike,X) - cp1 and refer back a specific choice point when a corresponding REDO is encountered.


Unify: (9) plays(mike, leadguitar)

Once Prolog has found a clause/fact based on predicate name and arity it checks that the query and head of the clause can be unified.

plays unifies with plays
mike unifies with mike
_7040 unifies with leadguitar. _7040 is bound to leadguitar.


Exit: (9) plays(mike, leadguitar)

This is just completing the ports of the Prolog box model. It shows the result of Call: (9) plays(mike, _7040). No unification takes place for this statement.


Call: (9) plays(alice, _7040)
Unify: (9) plays(alice, leadguitar)
Exit: (9) plays(alice, leadguitar)

Same pattern for alice. Alice has only one fact so not choice points generated for her.


Call: (9) plays(drew, _7040)
Unify: (9) plays(drew, leadguitar)
Exit: (9) plays(drew, leadguitar)

Same pattern for drew. Since drew has two facts for plays(drew,X). a choice point is generated. plays(drew,X) - cp1


Call: (9) leadguitar\=leadguitar

This is the fourth statement X \= Y with X is bound to leadguitar and Y is bound to leadguitar


Fail: (9) leadguitar\=leadguitar

Since leadguitar is not different from leadguitar this query fails. Upon failure Prolog goes back to the last choice point (Redo) and tries to find another solution.


Redo: (9) plays(drew, _7040)

Remember the last choice point created, plays(drew,X) - cp1. Since something failed the query is tried with another possible solution. Since the first choice point for plays(drew,X) failed with X being leadguitar, the second fact is used, plays(drew,baseguitar).


Unify: (9) plays(drew, baseguitar)

Just shows that the second fact for plays(drew,X) is being used.


Exit: (9) plays(drew, baseguitar)

It shows the result of Redo: (9) plays(drew, _7040).


The remainder is just more copy/paste of what has been done already and changing out the statements, variables, bound values, etc.


This answer is similar, but has more detail.


Of note is this question

I write a new rule called combo that determines whether or not three people can make a combo with a drummer, a base guitar, and a lead guitar.

is not answered by this query

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

because if these facts are added

plays(alice, flute).
plays(noah, cello).
plays(mike, trumpet).

this query

?- combo(alice,noah,mike).
true ;
true .

says true but alice, noah and mike are not playing the leadguitar, drums, and baseguitar.



来源:https://stackoverflow.com/questions/53470483/prolog-explain-trace-steps-in-english

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!