not sure this is exactly what you want, anyway get_var/2 could be useful to you.
apply_fdx(X, KV) :-
setof(K, get_var(X, K), Ks),
pairs_keys_values(KV, Ks, Vs),
Vs ins -100 .. 100,
make_fdx(X, KV, FDx),
FDx,
label(Vs).
get_var(X, K) :- X =.. [var,K].
get_var(X, K) :- X =.. [_|As], member(E, As), get_var(E, K).
make_fdx(equal(L,R), KV, Lf #= Rf) :-
make_fdx(L, KV, Lf), make_fdx(R, KV, Rf).
make_fdx(add(A, B), KV, Af + Bf) :-
make_fdx(A, KV, Af),
make_fdx(B, KV, Bf).
make_fdx(add(A, B, C), KV, Af + Bf + Cf) :-
make_fdx(A, KV, Af),
make_fdx(B, KV, Bf),
make_fdx(C, KV, Cf).
make_fdx(var(K), KV, V) :- memberchk(K-V, KV).
make_fdx(num(N), _, N).
yields
?- apply_fdx(equal(add(num(2),var(x)),add(num(3),var(x),var(y))), Vs).
Vs = [x- -100, y- -1] ;
Vs = [x- -99, y- -1] .
etc etc.
If you could start with a normalized syntax tree (i.e. add with 2 arguments instead of 3), make_fdx/3 could be made simpler.
equal
, but the way you have it should work fine. If you havevar(x)
and are consistent, there's nothing wrong with that. So, ` add(A,B) = add(num(2),var(x)), add(C,D,E) = add(num(3),var(x),var(y)), D = B.` will be true. - lurker