Jacek
Jacek

Reputation: 1108

Enumerate solutions in Prolog

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

Answers (1)

CapelliC
CapelliC

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

Related Questions