0
votes

How do I get for the following Prolog program

and(1,1,1).
and(1,0,0).
and(0,1,0).
and(0,0,0).

respective the following answer

?- and(A,B,C).
A=1, B=1, C=1;
A=1, B=0, C=0;
A=0, B=1, C=0;
A=0, B=0, C=0.

When I try to run the program above I get the following result

?- and(A,B,C).
A = B, B = C, C = 0 ;
A = C, C = 0,
B = 1 ;
A = 1,
B = C, C = 0 ;
A = B, B = C, C = 1.

It seems to be correct, but I don´t want to have variables in my answer, which abbreviates my expected answer.

If I run the example for GNU Prolog, I get only atom´s as a answer for a Variable and not a reference to a Variable itself. That´s what I want for swi-prolog too:

GNU Prolog 1.4.5 (64 bits)
Compiled Feb  5 2017, 10:30:08 with gcc
By Daniel Diaz
Copyright (C) 1999-2016 Daniel Diaz
| ?- und(A,B,C).

A = 1
B = 1
C = 1 ? ;

A = 1
B = 0
C = 0 ? ;

A = 0
B = 1
C = 0 ? ;

A = 0
B = 0
C = 0

This example is also in this PDF file on page 10.

I´m running SWI-Prolog version 7.4.2 for amd64 on Ubuntu 17.10

Thanks!

//edit: corrected result for logical-AND. //edit2: Added example from GNU Prolog, how results should be.

1
I'm not sure I understand why SWI's output is posing a problem, but if you want formatted output, you should look at SWI Prologs output writing and formatting predicates. Then you would all and(A, B, C), show_results(A, B, C). and just write show_results/3 to suit your whims. - lurker
In the PDF you reference, the first two arguments are the input of the gate and the third argument is the result. According to this argument ordering your facts and/3 describe logical OR. - tas
@lurker I search for a way to tell swi-prolog to output only the atom´s / object´s and not to re-use variables. In fact what swi-prolog does, is not really readable. - Friedrich Schmidt

1 Answers

3
votes

Firstly, as already mentioned in the comments, your predicate and/3 does not describe logical AND as in the PDF you referenced. The definition on page 10 is:

and(0,0,0).
and(0,1,0).
and(1,0,0).
and(1,1,1).

Secondly, if it's only about the output of the most general query, you can write a wrapper-predicate of arity 1 that displays the two arguments and the result as a triplet:

and(A-B-C) :-
   and(A,B,C).

If you query and/1 with a single variable, you get an output that looks similar to the one in your post:

?- and(X).
X = 0-0-0 ;
X = 0-1-0 ;
X = 1-0-0 ;
X = 1-1-1.

If you query and/1 with three variables, you get the same answer as with the most general query for and/3:

?- and(A-B-C).
A = B, B = C, C = 0 ;
A = C, C = 0,
B = 1 ;
A = 1,
B = C, C = 0 ;
A = B, B = C, C = 1.

?- and(A,B,C).
A = B, B = C, C = 0 ;
A = C, C = 0,
B = 1 ;
A = 1,
B = C, C = 0 ;
A = B, B = C, C = 1.

EDIT

In the above examples you can observe how every answer, that Prolog provides, consists of a substitution for every variable that occurs in the query, such that those substitutions satisfy the relation. This is the property used in the "trick" above when querying and/1 with the argument X: there's only one variable to provide answer-substitutions for. You can take this one step further by defining an output predicate of arity 0. Then Prolog can only answer true in the case of success because there are no variables in the query to provide substitutions for and you can use predicates like format/2 to create an output to your liking. For example:

andoutput :-
   and(A,B,C),
   format('A = ~d, B = ~d, C = ~d~n', [A,B,C]).

Querying this predicate yields the desired output:

?- andoutput.
A = 0, B = 0, C = 0    % <- output by format/2
true ;                 % <- Prolog's answer
A = 0, B = 1, C = 0    % <- output by format/2
true ;                 % <- Prolog's answer
A = 1, B = 0, C = 0    % <- output by format/2
true ;                 % <- Prolog's answer
A = 1, B = 1, C = 1    % <- output by format/2
true.                  % <- Prolog's answer

Note the difference between the output generated by your predicate and the answers provided by Prolog. If you prefer an output more similar to GNU-Prolog's answers you could define something like this:

andoutput2 :-
   and(A,B,C),
   format('~nA = ~d~nB = ~d~nC = ~d~n', [A,B,C]).

?- andoutput2.
         % <- output by format/2
A = 0    % <- output by format/2
B = 0    % <- output by format/2
C = 0    % <- output by format/2
true ;   % <- Prolog's answer
         % <- output by format/2
A = 0    % <- output by format/2
B = 1    % <- output by format/2
C = 0    % <- output by format/2
true ;   % <- Prolog's answer
         % <- output by format/2
A = 1    % <- output by format/2
B = 0    % <- output by format/2
C = 0    % <- output by format/2
true ;   % <- Prolog's answer
         % <- output by format/2
A = 1    % <- output by format/2
B = 1    % <- output by format/2
C = 1    % <- output by format/2
true.    % <- Prolog's answer

However, keep in mind that this is just formatted output and does in no way change Prolog's way to provide answers. So for every predicate that you'd like to answer in an individualized way, you have to provide an output-predicate. To see more options for generating output check the documentation on formatted write.