Hi Kuniaki Mukai,
I made a choice operator, which could solve your problem.
I don't know yet how to solve it in the multi-variate output
case. But the choice operator works in the uni-variate
output case.
Lets recap what quantifier like operators are known in
the literature. These can be all defined in terms of Shannon
co-factors, which I write A[X/0] and A[X/1].
Read these co-factors as setting X to 0 in the formul A,
and setting X to 1 in the formula A. So in the literature is
found the following:
exists X A(X) :<=> A[X/0] + A[X/1] /* disjunction */
forall X A(X) :<=> A[X/0] * A[X/1] /* conjunction */
d A(X) / dX :<=> A[X/0] # A[X/1] /* xor */
So based on the rather longer previous post here, unfortunately
this post is even longer, which already explained my choice function,
which prefers zeros, I simply defined a new quantifier:
choice X A(X) :<=> ~A[X/0] * A[X/1] /* difference */
Here is your example, first use the existence quantifier
to determine the precondition when your formula is
satisifiable, it turns out always:
?- sat(X^((~Y+(~Z+X)*(Z+ ~X))*(Y+(~Z+ ~X)*(Z+X)))).
Yes
Now as a next step, find a formula for X, based on Y,Z.
This is as simple as applying the choice operator now,
which will give you Y=:=Z as a result:
?- current_op(X,Y,_:!).
X = 200,
Y = xfy
?- sat(X!((~Y+(~Z+X)*(Z+ ~X))*(Y+(~Z+ ~X)*(Z+X)))).
Y = Z
Lets see whether this is really the solution. Note there can be
more solutions. The choice operator will only give one special
form of turning the multi-valued BDD tree into a single valued
BDD tree. So lets substitute back Y=:=Z for X, and lets see
what your original formula then says. I did this manually by
just rewriting the formula:
?- sat((~Y+(~Z+(Y=:=Z))*(Z+ ~(Y=:=Z)))*(Y+(~Z+ ~(Y=:=Z))*(Z+(Y=:=Z)))).
Yes
Another trick, known to Markus Triska as well, is to compute the
substitution via the use of the existential quantifier:
?- sat(X^(X=:=(Y=:=Z)*(~Y+(~Z+X)*(Z+ ~X))*(Y+(~Z+ ~X)*(Z+X)))).
Yes
I see one use case here of the new operator (!)/2, and the
choice it implemets for BDD trees. I guess we have just invented
an operator for the don't care problem. But I guess
it cannot enumerate all formulas that could be substituted
into the original formula. I also don't see that solve_boole_in_rozdd
does some backtracking and give different formulas.
So maybe the use case is quite limited. I think it solves the don't care
problem, but further research would be needed whether we really
need it for equations, such a strict choice.
Of course a sketch for multiple output variables would be also needed.
I have some scribbles how to do it with just this new choice operator
and nothing else more, but didn't try it yet...
Bye
P.S.: Here is the source code:
/* the existence quantifier tree_exists(A,X,R),
gives the normal form R of X^A, aka exists X A */
tree_exists(zero, _, R) :- !,
R = zero.
tree_exists(one, _, R) :- !,
R = one.
tree_exists(node3(Y,_,A,B), X, R) :- Y < X, !,
tree_exists(A, X, C),
tree_exists(B, X, D),
tree_make(C, D, Y, R).
tree_exists(node3(X,_,A,B), X, R) :- !,
tree_or(A, B, R).
tree_exists(N, _, N).
/* the choice quantifier tree_choice(A,X,R),
gives the normal form R of X!A, aka choice X A */
tree_choice(zero, _, R) :- !,
R = zero.
tree_choice(one, _, R) :- !,
R = zero.
tree_choice(node3(Y,_,A,B), X, R) :- Y < X, !,
tree_choice(A, X, C),
tree_choice(B, X, D),
tree_make(C, D, Y, R).
tree_choice(node3(X,_,A,B), X, R) :- !,
tree_not(B, C),
tree_and(A, C, R).
tree_choice(_, _, zero).