user2559578
user2559578

Reputation: 153

How to use the cut operator?

I've been learning and I came across a problem. I understood the cut operator from the tutorials but I'm trying to solve a problem and I cannot understand the solution.

Problem:

If the car color is red, made in Italy, then it's a Ferrari. If it's red but made in Germany (or any other country. could be more than one), it's Benz. If it's not red and is big, it's ford. If it's not red and not big, it's Toyota.

That is:

red & Italy: Ferrari
red & Germany (or not Italy): Benz
not red & big: ford
not red & not big: Toyota

Given some facts for a particular car object:

color(cx, red).
speed(cx, 220).
make(cx, italy).
type(cx, sport).

I want to write a predicate brand(X, name) that will return the brand of the particular car objects, like:

brand(X, ferrari):-
   color(X,red), make(X,T), T=italy.
brand(X, benz) :-
   color(X,red), not(make(X,italy)).
brand(X, ford) :-
   not(color(X,red)), size(X,big).
brand(X, toyota) :-
   not(color(X,red)), not(size(X,big)).

Question is how (and where) do I use the cut operator here so that it doesn't check the same property (eg: here "make") twice? I can't seem to wrap my head around this.

If I check for red and then for make, if the make turns out not italy, how do I write the brand(X, brand_name) for a set of facts for car object "ck" such that it doesn't check the make again? It appears impossible to me.

Upvotes: 0

Views: 786

Answers (1)

mat
mat

Reputation: 40768

The short answer: Don't.

Almost invariably, using !/0 will lead to loss of valid solutions.

Always keep in mind that Prolog programs are typically much more general than programs in other languages. In particular, keep in mind that users can always post the most general query, which in your case is:

?- brand(X, Y).

If you have !/0 in this definition, then yes, you will likely "check only once", but on the other hand, you will fail to generate all valid answers.

One good way out is to use if_/3 from library(reif). For example, in your case, you can write the facts as:

color(cx, red, true).
speed(cx, 220, true).
make(cx, italy, true).
type(cx, sport, true).

And now you can write:

car_type(C, Type) :-
        if_(color(C,red),
            if_(make(C, italy), Type=ferrari, Type=bentz),
            if_(type(C, big), Type=ford, Type=toyota)).

Importantly, the most general query will still work even if there are multiple solutions:

?- car_type(C, Type).
C = cx,
Type = ferrari.

Upvotes: 3

Related Questions