I'm trying to completely remove the choice points of my logical or/3 predicate that relates two logical variables and associates it with a third that can be either true or 'u' (unknown) (and when it's false, the predicate should fail).
Edit: adequated descriptions of the logical predicates to my own needs.
The simple predicate works:
or(A,B,true) :-
A = true, B = true ; A = true, B = false ; A = false, B = true.
or(A,B,u) :-
A = u, B = u; A = u, B = false ; A = false, B = u.
but yields multiple unnecessary choice points like:
?- or(A,false,C).
A = C, C = true ;
A = C, C = u ;
false.
I tried using if_/3 and reif package but i always end up with a choice point somewhere. This is one of the iterations I managed to make, but it still has a useless choice point in the end:
or3(A, B, C) :-
if_( C = u
, if_( A = u
, ( B = u ; B = false)
, ( A = false, B = u )
),
if_( C = true
, if_( A = true
, ( B = true ; B = false)
, ( A = false, B = true )
)
, false
)
).
?- or3(A,false,C).
Correct to: "tri_logic:or3(A,false,C)"? yes
A = C, C = u ;
A = C, C = true ;
false.
I also tried directly using =/3 and ;/3 to implement a version that only works for true values, but the results were even pretty much the same:
or3(A,B,C) :-
=( C, true, T),
;( ( A = true, B = true ), ( A = true, B = false ), T1 ),
;( T1=true, ( A = false, B = true), T).
?- or3(A,false,C).
Correct to: "tri_logic:or3(A,false,C)"? yes
A = C, C = u ;
A = C, C = true ;
false.
What am I missing here?
I'm trying to completely remove the choice points of my logical or/3 predicate that relates two logical variables and associates it with a third that can be either true or 'u' (unknown) (and when it's false, the predicate should fail).
Edit: adequated descriptions of the logical predicates to my own needs.
The simple predicate works:
or(A,B,true) :-
A = true, B = true ; A = true, B = false ; A = false, B = true.
or(A,B,u) :-
A = u, B = u; A = u, B = false ; A = false, B = u.
but yields multiple unnecessary choice points like:
?- or(A,false,C).
A = C, C = true ;
A = C, C = u ;
false.
I tried using if_/3 and reif package but i always end up with a choice point somewhere. This is one of the iterations I managed to make, but it still has a useless choice point in the end:
or3(A, B, C) :-
if_( C = u
, if_( A = u
, ( B = u ; B = false)
, ( A = false, B = u )
),
if_( C = true
, if_( A = true
, ( B = true ; B = false)
, ( A = false, B = true )
)
, false
)
).
?- or3(A,false,C).
Correct to: "tri_logic:or3(A,false,C)"? yes
A = C, C = u ;
A = C, C = true ;
false.
I also tried directly using =/3 and ;/3 to implement a version that only works for true values, but the results were even pretty much the same:
or3(A,B,C) :-
=( C, true, T),
;( ( A = true, B = true ), ( A = true, B = false ), T1 ),
;( T1=true, ( A = false, B = true), T).
?- or3(A,false,C).
Correct to: "tri_logic:or3(A,false,C)"? yes
A = C, C = u ;
A = C, C = true ;
false.
What am I missing here?
Share Improve this question edited Mar 16 at 15:06 Luiz asked Mar 14 at 17:39 LuizLuiz 1497 bronze badges 10- What do you mean by "unnecessary" or "useless" choice point? In each example, of the 2 distinct instantiations of the unbound variables that satisfy the query that you get, which would be unnecessary/useless, and how did you choose? – Scott Hunter Commented Mar 14 at 17:47
- @ScottHunter the false at the end means Prolog is meaninglessly searching for answers and not finding any, i would like to remove this behaviour as it's pointless. – Luiz Commented Mar 14 at 21:15
- There's no point in receiving no answer in a Prolog query, it should just give me all the valid answer, and only if my query does not find any answer it should report false, as in, 'invalid query'. – Luiz Commented Mar 14 at 21:16
- 1 For clarification: the first sentence of this question ends in "that can be either true, false or 'u' (unknown)". These are all successes, from a constraint perspective, rather than failure. If "false" meant constraint failure then "false" could not possibly be a value. – brebs Commented Mar 16 at 12:49
- 1 @Luiz false should be a value, for the normal usage of reification in which the result is a variable. If false is constraint failure, then the code must now additionally check for constraint failure, which is pointlessly awkward when it can just be a value (as in e.g. memberd_t). – brebs Commented Mar 16 at 15:18
2 Answers
Reset to default 3To prevent unwanted choicepoints, both parameters must be considered simultaneously. Whereas if_
considers a single value.
Can use the relational aspect of Prolog - list the possibilities:
% Using table to improve determinism
:- table and_or/4.
% Bool (or u), Bool (or u), AND, OR
and_or(true, true, true, true).
and_or(false, true, false, true).
and_or(u, true, u, true).
and_or(true, false, false, true).
and_or(false, false, false, false).
and_or(u, false, false, u).
and_or(true, u, u, true).
and_or(false, u, false, u).
and_or(u, u, u, u).
The table directive in swi-prolog is being used here to prevent unwanted choicepoints by indexing the and_or
lookup.
Then, it's simply a case of performing the lookup:
andt(A, B, T) :-
and_or(A, B, T, _).
ort(A, B, T) :-
and_or(A, B, _, T).
Examples:
?- andt(true, u, T).
T = u. % No unwanted choicepoint
?- ort(true, u, T).
T = true. % No unwanted choicepoint
The unwanted choice point can also be removed with the ISO built-in setof/3
.
% @brebs' table
and_or(true, true, true, true).
and_or(false, true, false, true).
and_or(u, true, u, true).
and_or(true, false, false, true).
and_or(false, false, false, false).
and_or(u, false, false, u).
and_or(true, u, u, true).
and_or(false, u, false, u).
and_or(u, u, u, u).
andt(A, B, T) :-
setof(t, X^and_or(A, B, T, X), _).
ort(A, B, T) :-
setof(t, X^and_or(A, B, X, T), _).
?- andt(true, u, T).
T = u.
?- ort(true, u, T).
T = true.