Freelancer
Freelancer

Reputation: 844

How to query Rules in prolog?

I have the following code:

word(aa, a, a).
word(ab, a, b).
word(ac, a, c).
word(ad, a, d).

word(bb, b, b).
word(bc, b, c).
word(bd, b, d).


word(cc, c, c).
word(cd, c, d).

word(dd, d, d).
word(dc, d, c).

null(a).

crossword(A, B, C, D) :-
    word(A, AC, AD),
    word(B, BC, BD),

    word(C, AC, BC),
    word(D, AD, BD),
    A \== B,
    B \== C,
    A \== C,
    B \== D,
    C \== D,

    writeln(A-B-C-D),
    null(b).

This is a prolog code that is used for getting all the possible ways of filling a 2x2 table of words like this:

enter image description here

I want to know how I can query this code for getting all the answers.and I can't figure out what are null(a) and null(b) used for?

Upvotes: 0

Views: 808

Answers (1)

lurker
lurker

Reputation: 58224

Here's a breakdown of the existing code.

word(aa, a, a).
...
word(dd, d, c).
word(dc, d, c).

These define word facts which appear to list valid "words". The extra 2nd and 3rd arguments appear to be redundant because (a) they are easily derivable from the first argument, and (b) they aren't used anywhere in the shown program (it's unclear from the excerpt whether there are other portions of this program). It's also unclear why both cd and dc are listed, but this symmetrical relationship isn't given for other "words".

null(a).

This is a fact that says something like "a is null", but the semantics are unclear given the limited context.

crossword(A, B, C, D) :-

This is a predicate, crossword/4, which accepts 4 arguments. The reason for having these arguments is unclear (see below).

    word(A, AC, AD),
    word(B, BC, BD),

    word(C, AC, BC),
    word(D, AD, BD),

The above 4 lines of code gather 4 word facts. There's a dependency that you can see in the use of AC, AD, etc, in which it is ensuring that one pair of words is across, while the other pair of words are what you get when those same words are read downward on the board.

    A \== B,
    B \== C,
    A \== C,
    B \== D,
    C \== D,

The above 5 lines of code ensure that there are some differences between the gathered word facts. Again, the semantics are unclear since it allows A and D to be the same word (perhaps it's not otherwise possible, given the other constraints). If any of these tests for inequality fail, then backtracking will occur back to the word/3 queries above to gather at least one different word fact and Prolog will retry the inequality checks.

    writeln(A-B-C-D),

This writes out the current quad of "words" that have satisfied all of the above inequalities.

    null(b).

This tests (queries) the fact null(b) which will fail since null(b) isn't established as either a fact or derivable from any given rule for null(X). When it fails, Prolog will backtrack again all the way back to gathering another set of word facts through the word/3 queries.

When all combinations of word/3 queries have been exhausted (each of them provides one of the several word facts as a solution) then the entire crossword/4 predicate fails and ends, after having displayed all the possibilities with writeln. Thus, when you issue a query, crossword(A, B, C, D)., it keeps iterating and displaying each potential solution, per the above, with writeln until no more solutions exist and it ultimately fails (meaning, no more solutions).

As I mentioned in a comment, the code is a bit oddly formulated. For example, the use of null(b) as an invalid fact to cause the code to keep iterating by backtracking. Perhaps the original intent was to change the fact null(a) to null(b) to "turn off the iterations" when desired. Sort of like an "iteration flag". It's uncertain based upon the information given.

Another way to structure the code would be simply:

crossword(A, B, C, D) :-
    word(A, AC, AD),
    word(B, BC, BD),
    word(C, AC, BC),
    word(D, AD, BD),
    A \== B,
    A \== C,
    B \== C,
    B \== D,
    C \== D.

When this is queried with crossword(A, B, C, D), Prolog will give you each solution individually until it finds no more, or you tell it to stop. You can collect all the results at once in a list with setof:

setof(A-B-C-D, crossword(A, B, C, D), Solutions).

Upvotes: 1

Related Questions