2

I am new to Prolog and trying to learn it. I want to achieve something like a>b and b>c then a>c which is Transitive relation.

I have a set of following rules.

bigger(elephant,horse).
bigger(horse,ant).
bigger(ant, bacteria).
bigger(bacteria,virus).

We know that elephant is bigger than virus. What I want to achieve is that when I use smaller(ant,elephant) it should return true. The rule smaller(X,Y) I tried to use is

smaller(Y,X) :-
    bigger(X,Z),
   (bigger(Z,Y);
    Z=Y).
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Harwee
  • 1,601
  • 2
  • 21
  • 35
  • 4
    See [tag:transitive-closure], and specifically the [definition](http://stackoverflow.com/q/26946133/1613573). – mat Dec 18 '15 at 17:38
  • @lurker that is working because it's the second rule and doesn't work for `smaller(virus,elephant)` – Harwee Dec 18 '15 at 17:43
  • 1
    As @mat points out, you need transitive closure. So if you break it into two clauses, you'd have: `smaller(X, Y) :- bigger(Y, X).` and `smaller(X, Y) :- bigger(Z, X), smaller(Z, Y).` – lurker Dec 18 '15 at 17:49
  • But that gives out two responses `true` and `false` – Harwee Dec 18 '15 at 17:55
  • 2
    The first result `true` means it succeeded in the query for the first result. The subsequent `false` means it didn't find any more solutions (there was a choice point). – lurker Dec 18 '15 at 17:59
  • Got it, and are there any good books or tutorials to learn Prolog from – Harwee Dec 18 '15 at 18:02
  • 2
    Several good books. *The Art of Prolog* by Sterling & Shapiro, *The Craft of Prolog* by O'Keefe, *Programming in Prolog* by Clocksin & Mellish. There are some online tutorials which are fairly basic, but you can learn some things from them. Just Google "Prolog tutorial". – lurker Dec 18 '15 at 18:08

1 Answers1

2

You can perhaps use big_fact/2 to describe the database:

big_fact(elephant,horse).
big_fact(horse,ant).
big_fact(ant, bacteria).
big_fact(bacteria,virus).

Then you can use bigger/2 as a transitive closure:

bigger(X,Y) :-
    big_fact(X,Y).
bigger(X,Z) :-
    big_fact(X,Y),
    bigger(Y,Z).

If you run this in , it generates:

?- bigger(X,Y).
X = elephant,
Y = horse ;
X = horse,
Y = ant ;
X = ant,
Y = bacteria ;
X = bacteria,
Y = virus ;
X = elephant,
Y = ant ;
X = elephant,
Y = bacteria ;
X = elephant,
Y = virus ;
X = horse,
Y = bacteria ;
X = horse,
Y = virus ;
X = ant,
Y = virus ;
false.

?- bigger(virus,Y).
false.

?- bigger(ant,Y).
Y = bacteria ;
Y = virus ;
false.

?- bigger(X,horse).
X = elephant ;
false.

?- bigger(X,bacteria).
X = ant ;
X = elephant ;
X = horse ;
false.

?- bigger(elephant,bacteria).
true ;
false.

So it is a transitive closure.

You can then define smaller/2 by means of bigger/2:

smaller(X,Y) :-
    bigger(Y,X).
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555