Given the following facts and predicates:
sound(time1).
sound(time2).
sun(time3).
relax(X):-sound(X),!,sun(X).
relax(_):-sun(_).
When executing relax(S).
I'd expect to get S=time1
due to the !
, that says (correct me if I'm wrong), that if 'X' is satisfied , then stop the backtracking.
Here is the trace:
3 ?- trace.
true.
[trace] 3 ?- relax(S).
Call: (6) relax(_G1831) ? creep
Call: (7) sound(_G1831) ? creep
Exit: (7) sound(time1) ? creep
Call: (7) sun(time1) ? creep
Fail: (7) sun(time1) ? creep
Fail: (6) relax(_G1831) ? creep
false.
So why does Prolog also checks sun(time1)
, even though that it met the exclamation mark after being satisfied by sound(X)
(because sound(time1)
is a fact).
Prolog provides a predicate that performs this function. It is called the cut, represented by an exclamation point (!). The cut effectively tells Prolog to freeze all the decisions made so far in this predicate. That is, if required to backtrack, it will automatically fail without trying other alternatives.
! symbol represents the cut . You can read more about cut here. Also, an example in prolog can be found here.
Because of the problems of negation-as-failure, negation in Prolog is represented in modern Prolog interpreters using the symbol \+ , which is supposed to be a mnemonic for not provable with the \ standing for not and the + for provable.
As its name suggests, fail/0 is a special symbol that will immediately fail when Prolog encounters it as a goal. That may not sound too useful, but remember: when Prolog fails, it tries to backtrack . Thus fail/0 can be viewed as an instruction to force backtracking.
To clarify this even more, if somebody still struggles how exclamation operator works (like i did), here is an example:
sound(time3).
sound(time1).
sun(time1).
relax(X):-sound(X),!,sun(X).
For this certain example, if you ask Prolog for ?-relax(S).
this results into false. We can describe Prolog working like this:
In opposition like I said in 4. without ! operator it results into success.
sound(time3).
sound(time1).
sun(time1).
relax(X):-sound(X),sun(X).
Feel free to correct me if I am wrong at some point.
The !
sign prevents backtracking of the clauses to the right of it to the left, it's like a one-way gate so that it won't backtrack beyond the cut.
When sound(time1)
is true, the next clause sun(time1)
will be evaluated, and only then prolog will find that sun(time1)
is false
(by searching the knowledge base, it doesn't actually know that it's a fact).
Then, because of the cut, prolog won't try values time2
and time3
in the first clause.
More about cut:
Prolog evaluates the clauses of a predicate left to right. It binds a value to a variable in the leftmost clause. If the clause is true
, it moves to the next one. If it's false
, prolog tries other values as well.
If any of the clauses cannot be satisfied by any value, it would be false
, and so will be the whole predicate (because the clauses are joined by AND).
The whole thing works as a depth-first traversal of a tree, where the clauses are the nodes and the edges represent different values of its variable. If the traversal finds a clause to be false
, it would return to its preceding clause and try a different value.
Here comes the cut. If you put a cut (!
) between two clauses, it would mean that if the clause after a cut becomes false
, trying new values will go on ONLY IF the evaluation runs AFTER the cut. It means the values of the variables used before the cut are locked, and they cannot be changed when the evaluation crosses the cut.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With