Search code examples
prologbacktrackingnon-repetitive

In Prolog how can I cut redundant answers


I am working on a dictionary-like program with prolog, and my code goes like this:

define(car,vehicle).
define(car,that).
define(car,has).
define(car,four).
define(car,wheels).
define(wheels,round).
define(wheels,object).
define(wheels,used).
define(wheels,in).
define(wheels,transportation).


defined(X):-define(X,_).

anotherdefined(X):- \+ undefined(X).
undefined(X):- \+define(X,_).        

I am trying to write a defined/1 predicate which will give me:

?-defined(X).
X = car ;
X = wheels ;
false.

Yet, my defined/1 gives me X=car. five times (naturally) for everytime it counters define(car,_). and my anotherdefined/1 gives me only true. What is the method to stop prolog backtracking to the other instances of define(car,_).,and skip to define(wheels,_).?

Edit: I have written the following lines to get the result I want with givedefinedword/1,

listdefined(X):-findall(Y,defined(Y),Z),sort(Z,X).
givedefinedword(X):-listdefined(List),member(X,List).

However since I wanted an efficient predicate (which I will use in many others) it beats the purpose. This predicate does too much process.

Or, Would it be better to use a predicate that modifies the code? say prepares a list of defined words, and modifies it when new definitions are added.

Thanks.


Solution

  • If you change define to relate items and lists, like

    definelist(car, [vehicle, that, has, four, wheels]).
    % etc.
    defined(X) :- definelist(X, _).
    

    then defined will no longer produce duplicates, nor require linear space.

    Of course, a query define(X, Y) must now be performed as definelist(X, L), member(Y, L). If you want this to be efficient as well, you may need to duplicate all definitions.