35
36:- module(count,
37 [ proof_count/2, 38 proof_count/3, 39 answer_count/3, 40 answer_count/4, 41 answer_set/3, 42 answer_set/4, 43 answer_pair_set/5, 44 unique_solution/2 45 ]). 46:- use_module(library(nb_set)). 47:- use_module(library(rbtrees)). 48:- use_module(library(nb_rbtrees)).
67:- meta_predicate
68 proof_count(0, -),
69 proof_count(0, +, -),
70 answer_count(?, 0, -),
71 answer_count(?, 0, +, -),
72 answer_set(?, 0, -),
73 answer_set(?, 0, +, -),
74 answer_pair_set(?, 0, +, +, -),
75 unique_solution(0, -).
87proof_count(Goal, Count) :-
88 proof_count(Goal, infinite, Count).
89
90proof_count(Goal, Max, Count) :-
91 State = count(0),
92 ( Goal,
93 arg(1, State, N0),
94 N is N0 + 1,
95 nb_setarg(1, State, N),
96 N == Max
97 -> Count = Max
98 ; arg(1, State, Count)
99 ).
107answer_count(T, G, Count) :-
108 answer_count(T, G, infinite, Count).
109
110answer_count(T, G, Max, Count) :-
111 empty_nb_set(Set),
112 C = c(0),
113 ( G,
114 add_nb_set(T, Set, true),
115 arg(1, C, C0),
116 C1 is C0+1,
117 nb_setarg(1, C, C1),
118 C1 == Max
119 -> Count = Max
120 ; arg(1, C, Count)
121 ).
133answer_set(T, G, Ts) :-
134 findall(T, G, Raw),
135 sort(Raw, Ts).
136
137answer_set(T, G, Max, Ts) :-
138 empty_nb_set(Set),
139 State = count(0),
140 ( G,
141 add_nb_set(T, Set, true),
142 arg(1, State, C0),
143 C is C0 + 1,
144 nb_setarg(1, State, C),
145 C == Max
146 -> true
147 ; true
148 ),
149 nb_set_to_list(Set, Ts).
157answer_pair_set(P, G, MaxKeys, MaxPerKey, Groups) :-
158 P = K-V,
159 ( MaxPerKey = inf
160 -> true
161 ; TooMany is MaxPerKey+1,
162 dif(New, values(TooMany))
163 ),
164 rb_empty(Tree),
165 State = keys(0),
166 ( G,
167 add_pair(Tree, K, V, New),
168 New == new_key,
169 arg(1, State, C0),
170 C is C0+1,
171 nb_setarg(1, State, C),
172 C == MaxKeys
173 -> true
174 ; true
175 ),
176 groups(Tree, Groups).
177
178add_pair(T, K, V, New) :-
179 nb_rb_get_node(T, K, N),
180 !,
181 nb_rb_node_value(N, NV),
182 NV = k(Count, VT),
183 ( nb_rb_get_node(VT, V, _)
184 -> New = false
185 ; NewCount is Count + 1,
186 New = values(NewCount),
187 nb_rb_insert(VT, V, true),
188 nb_setarg(1, NV, NewCount)
189 ).
190add_pair(T, K, V, new_key) :-
191 rb_one(V, true, RB),
192 nb_rb_insert(T, K, k(1, RB)).
193
194rb_one(K, V, Tree) :-
195 rb_empty(T0),
196 rb_insert(T0, K, V, Tree).
197
198groups(Tree, Groups) :-
199 rb_visit(Tree, Pairs),
200 maplist(expand_values, Pairs, Groups).
201
202expand_values(K-k(_Count,T), K-Vs) :-
203 rb_keys(T, Vs).
216unique_solution(Goal, Solution) :-
217 State = state(false, _),
218 ( Goal,
219 ( arg(1, State, false)
220 -> nb_setarg(1, State, true),
221 nb_setarg(2, State, Solution),
222 fail
223 ; arg(2, State, Answer),
224 Answer =@= Solution
225 -> fail
226 ; !, fail 227 )
228 ; arg(1, State, true),
229 arg(2, State, Solution)
230 )
This module provides various ways to count solutions
This module is based on a similar collection introduces in the first ClioPatria release. Most names have been changed to describe the semantics more accurately.
The predicates in this library provide space-efficient solutions, avoiding findall/setof. Most predicates come with a variant that allows limiting the number of answers.