Reputation: 1108
I wanted to enumerate solutions of a non-deterministic goal nondet_goal
as pairs (Index, Value)
where Index
is the index of each value returned. I managed to do it using nb_setval
, nb_getval
like this:
nb_setval(g_idx, 0),
findnsols(3, (Idx, Val), (nondet_goal(Val), nb_getval(g_idx, Idx), Idx1 is Idx + 1, nb_setval(g_idx, Idx1)), Out).
A quick test case may look like this:
L = [a,b,c,d,e],
nb_setval(g_idx, 0),
findnsols(3, (Idx, It), (member(It, L), nb_getval(g_idx, Idx), Idx1 is Idx + 1, nb_setval(g_idx, Idx1)), Out).
Which produces the intended output:
Out = [(0, a), (1, b), (2, c)] ;
Out = [(3, d), (4, e)].
I'm wondering whether there is a better way to get values and indices. Ideally, if it doesn't need to generate a complete list of all solutions. Any help appreciated.
Cheers, Jacek
Upvotes: 1
Views: 519
Reputation: 60034
I would 'encapsulate' your code, that's already working well - except for reentrancy. So, let's start choosing a name for this abstraction:
enumerate_indexed_solutions(G, S, L) :-
nb_setval(g_idx, 0),
findnsols(3, I-S, (
G,
nb_getval(g_idx, I), I1 is I + 1, nb_setval(g_idx, I1)
), L).
which yields:
?- enumerate_indexed_solutions(member(V,[a,b,c,d,e]),V,L).
L = [0-a, 1-b, 2-c] ;
L = [3-d, 4-e].
edit:
enumerate_indexed :- nb_setval(g_idx, 0).
enumerate_indexed(I) :-
nb_getval(g_idx, I), I1 is I + 1, nb_setval(g_idx, I1).
enumerate_indexed_solutions(G, S, L) :-
enumerate_indexed,
findnsols(3, I-S, (G, enumerate_indexed(I)), L).
Upvotes: 2