Find all solutions to a predicate
I'm trying to define a predicate开发者_运维技巧 that receives a single term with free variables and returns a list of mappings of those variables, so for example if the database is
a(0,1).
a(1,1).
the expected output would be
?- eval(a(X,1),Maps).
Maps = [[[X,0]],[[X,1]]].
?- eval(a(X,Y),Maps).
Maps = [[[X,0],[Y,1]],[[X,1],[Y,1]]].
I've been trying to accomplish this by using findall/3
, but I can't figure out a way to ask for the free variables and their possible values. If it helps, I'm using swiprolog.
Thanks.
Here is a solution to a similar problem. Instead of a list of answers represented as a list with entries [V,term]
for each variable, the query goal_answers(Goal, Answerp)
finds a pair Vars-Terms
.
goal_answerp(Goal, Answerp) :-
term_variables(Goal, Vars),
findall(Vars, Goal, Substs),
Answerp = Vars-Substs.
?- goal_answerp(a(X,1), Ms).
Ms = [X]-[[0],[1]].
?- goal_answerp(a(X,Y), Ms).
Ms = [X,Y]-[[0,1],[1,1]].
[Edit] To get the answers back in the original format use library(lambda)
:
?- goal_answerp(a(X,1), Vs-Dss),
maplist(Vs+\Ds^VDs^maplist(\V^D^[V,D]^true,Vs,Ds,VDs),Dss,VDss).
Vs = [X], Dss = [[0],[1]], VDss = [[[X,0]],[[X,1]]].
?- goal_answerp(a(X,Y), Vs-Dss),
maplist(Vs+\Ds^VDs^maplist(\V^D^[V,D]^true,Vs,Ds,VDs),Dss,VDss).
Vs = [X,Y], Dss = [[0,1],[1,1]], VDss = [[[X,0],[Y,1]],[[X,1],[Y,1]]].
There is an issue with what you want to do. The user-friendly name you give to the variables (e.g. X, Y) is known to the top level parser, but is "lost" inside your program. This snippet will list all the bindings but the variables will have generic names:
find_mappings(Template, Mappings):-
term_variables(Template, Vars),
find_mappings1(Vars, Mapping),
findall(Mapping, Template, Mappings).
find_mappings1([], []).
find_mappings1([Var|Vars], [[Name,Var]|Mappings]):-
term_to_atom(Var, Name),
find_mappings1(Vars, Mappings).
?- find_mappings(a(X,Y), L).
L = [[['_G385', 0], ['_G386', 1]], [['_G385', 1], ['_G386', 1]]].
You might prefer to add another argument to your procedure to receive the proper names of your variables:
find_mappings(Template, Names, Mappings):-
term_variables(Template, Vars),
find_mappings1(Vars, Names, Mapping),
findall(Mapping, Template, Mappings).
find_mappings1([], [], []).
find_mappings1([Var|Vars], [Name|Names], [[Name,Var]|Mappings]):-
find_mappings1(Vars, Names, Mappings).
?- find_mappings(a(X,Y), ['X', 'Y'], L).
L = [[['X', 0], ['Y', 1]], [['X', 1], ['Y', 1]]].
I don't have an interpreter in front of me, but I imagine you could do this for this particular setup with your 'a' predicate.
var(X),
var(Y),
findall(U,
( a(XSol,YSol), U=[[X,XSol], [Y,YSol]] ),
Maps).
(The var's might be unnecessary) I don't know why you'd want to do use this approach to any problem though...
Check out unifiable/3 for potentially a better way to do something like this.
精彩评论