Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compound boolean expressions in Prolog

In Prolog, how do you implement compound logical predicates like (A and B) or (C and D)?

This may seem like a simple question but many approachable online tutorials are not detailed enough on boolean expressions. I assume you can't just write:

test(A, B, C, D) :- cond(A), cond(B); cond(C), cond(D).

so how would you do it?

like image 408
donnyton Avatar asked Jan 21 '12 07:01

donnyton


2 Answers

As noted by others, your original example

test(A, B, C, D) :- cond(A), cond(B); cond(C), cond(D).

is perfectly valid (assuming the parse is as you intended it). Didn't you try it?

A Primer

Logical AND

foo :- a , b .

Logical OR

foo :- a ; b .

Combined

foo :- a , b ; c , d .

The above parses as:

foo :- ( a , b ) ; ( c , d ) .

Use parentheses to indicate a different desired binding:

foo :- a , ( b ; c ) , d .

Even better, eschew the ; OR operator and break alternatives up into separate clauses. Sequence is much easier for people to comprehend than branching tree structures. Breaking alternation up into multiple clauses simplifies testing/debugging and improves comprehension. Therefore, prefer

foo :- a , b .
foo :- c , d .

over

foo :- a , b ; c , d .

and prefer

foo :- a , bar , d .

bar :- b .
bar :- c .

over

foo :- a , ( b ; c ) , d .

Possibly most importantly, breaking things up into multiple clauses like this makes later maintenance easier. With a structure like:

foo :- a , b ; c , d .

what do you do when you add another case? What about when it expands to 50 alternatives?

Each additional alternative increases the number of code paths through the clause, thus making testing and comprehension more difficult. To get complete code coverage in testing, a lot of alternative paths must be individually tested.

With the equivalent structure

foo :- a , b .
foo :- c , d .

Adding alternatives is simply a matter of adding additional clause or clauses, each of which can be tested in isolation.

A professional programmer writes first for the people who will, several years down the line, need to comprehend, change and fix that code (hint: that person might be yourself).

like image 136
Nicholas Carey Avatar answered Nov 10 '22 11:11

Nicholas Carey


A simple alternative for conjunctions is to use substatements. For disjunctions, use multiple lines. Your example:

test(A, B, C, D) :- test1(A, B).
test(A, B, C, D) :- test2(C, D).
test1(A, B) :- A, B.
test2(C, D) :- C, D.

What about (A or B) and (C or D)?

other(A, B, C, D) :- other1(A, B), other2(C, D).
other1(A, B) :- A.
other1(A, B) :- B.
other2(C, D) :- C.
other2(C, D) :- D.

Note that this is only mentioned as an alternative to joel76's answer.

like image 1
Patrick87 Avatar answered Nov 10 '22 11:11

Patrick87