Saturday, April 23, 2016

Set Intersection predicate Prolog using not

Leave a Comment

I am trying to build a simple predicate which get as inputs two lists and the results is a third one consisting of the intersection of the first two. I have decided to do using logical statement. I am pretty sure my logic is correct but my predicate is not working. Any ideas?:

element(X,[H|T]) :-        X=H    ;       element(X,T).  intersection(L1,L2,R) :-     not((         element(A,L1),         not(element(A,L2))     )),     not((         element(A,L1),         not(element(A,R))     )). 

Please do not post alternative methods I am wondering why this one returns FALSE every time.

2 Answers

Answers 1

The problem is that not/1 merely negates the outcome of your element/2. It doesn't cause element/2 to backtrack to find other instantiations for which the enclosing not/1 will be true.

Consider the following program.

a(1). a(2).  b(1). b(2). b(3). 

And the following queries:

  1. b(X), not(a(X)).
  2. not(a(X)), b(X).

The first one yields X = 3 while the second one yields false. That is because the first query first instantiates X with 1, then with 2, then with 3, until finally not(a(X)) succeeds.
The second query first instantiates X with 1, a(1) succeeds, so not(a(1)) fails. There is no backtracking done!

Answers 2

Your definition is correct. For the ground case. What is a bit unusual is that the intersection is the first and not the last argument.

It is a bit too general, though - like many Prolog predicates (think of append([], non_list, non_list). Apart from lists, your definition admits also terms that are neither lists nor partial lists:

?- intersection(non_list,[1,2|non_list],[3,4|non_list]) 

To make it really useful safe, use it like so:

?- when(ground(intersection(I, A, B), intersection(I, A, B)). 

or so:

?- (  ground(intersection(I, A, B))    -> intersection(I, A, B)    ;  throw(error(instantiation_error, interaction(I, A, B)))    ). 

As a minor remark, rather write (\+)/1 in place of not/1.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment