Next: sparse_bitset, Previous: set_unordlist, Up: Top [Contents]
%--------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %--------------------------------------------------% % Copyright (C) 1994-2007 The University of Melbourne. % Copyright (C) 2014-2021, 2024 The Mercury team. % This file is distributed under the terms specified in COPYING.LIB. %--------------------------------------------------% % % File: solutions.m. % Main author: fjh. % Stability: medium. % %--------------------------------------------------% %--------------------------------------------------% :- module solutions. :- interface. :- import_module bool. :- import_module list. :- import_module set. %--------------------------------------------------% % solutions/2 collects all the solutions to a predicate and returns % them as a list in sorted order, with duplicates removed. % solutions_set/2 returns them as a set. unsorted_solutions/2 returns % them as an unsorted list with possible duplicates; since there are % an infinite number of such lists, this must be called from a context % in which only a single solution is required. % :- pred solutions(pred(T), list(T)). :- mode solutions(in(pred(out) is multi), out(non_empty_list)) is det. :- mode solutions(in(pred(out) is nondet), out) is det. :- func solutions(pred(T)) = list(T). :- mode solutions(in(pred(out) is multi)) = out(non_empty_list) is det. :- mode solutions(in(pred(out) is nondet)) = out is det. :- func solutions_set(pred(T)) = set(T). :- mode solutions_set(in(pred(out) is multi)) = out is det. :- mode solutions_set(in(pred(out) is nondet)) = out is det. :- pred solutions_set(pred(T), set(T)). :- mode solutions_set(in(pred(out) is multi), out) is det. :- mode solutions_set(in(pred(out) is nondet), out) is det. :- pred unsorted_solutions(pred(T), list(T)). :- mode unsorted_solutions(in(pred(out) is multi), out(non_empty_list)) is cc_multi. :- mode unsorted_solutions(in(pred(out) is nondet), out) is cc_multi. :- func aggregate(pred(T), func(T, A) = A, A) = A. :- mode aggregate(in(pred(out) is multi), in(func(in, in) = out is det), in) = out is det. :- mode aggregate(in(pred(out) is nondet), in(func(in, in) = out is det), in) = out is det. % aggregate/4 generates all the solutions to a predicate, % sorts them and removes duplicates, then applies an accumulator % predicate to each solution in turn: % % aggregate(Generator, AccumulatorPred, Acc0, Acc) <=> % solutions(Generator, Solutions), % list.foldl(AccumulatorPred, Solutions, Acc0, Acc). % :- pred aggregate(pred(T), pred(T, A, A), A, A). :- mode aggregate(in(pred(out) is multi), in(pred(in, in, out) is det), in, out) is det. :- mode aggregate(in(pred(out) is multi), in(pred(in, di, uo) is det), di, uo) is det. :- mode aggregate(in(pred(out) is nondet), in(pred(in, di, uo) is det), di, uo) is det. :- mode aggregate(in(pred(out) is nondet), in(pred(in, in, out) is det), in, out) is det. % aggregate2/6 generates all the solutions to a predicate, % sorts them and removes duplicates, then applies an accumulator % predicate to each solution in turn: % % aggregate2(Generator, AccumulatorPred, AccA0, AccA, AccB0, AccB) <=> % solutions(Generator, Solutions), % list.foldl2(AccumulatorPred, Solutions, AccA0, AccA, AccB0, AccB). % :- pred aggregate2(pred(T), pred(T, A, A, B, B), A, A, B, B). :- mode aggregate2(in(pred(out) is multi), in(pred(in, in, out, in, out) is det), in, out, in, out) is det. :- mode aggregate2(in(pred(out) is multi), in(pred(in, in, out, di, uo) is det), in, out, di, uo) is det. :- mode aggregate2(in(pred(out) is nondet), in(pred(in, in, out, di, uo) is det), in, out, di, uo) is det. :- mode aggregate2(in(pred(out) is nondet), in(pred(in, in, out, in, out) is det), in, out, in, out) is det. % unsorted_aggregate/4 generates all the solutions to a predicate % and applies an accumulator predicate to each solution in turn. % Declaratively, the specification is as follows: % % unsorted_aggregate(Generator, AccumulatorPred, Acc0, Acc) <=> % unsorted_solutions(Generator, Solutions), % list.foldl(AccumulatorPred, Solutions, Acc0, Acc). % % Operationally, however, unsorted_aggregate/4 will call the % AccumulatorPred for each solution as it is obtained, rather than % first building a list of all the solutions. % :- pred unsorted_aggregate(pred(T), pred(T, A, A), A, A). :- mode unsorted_aggregate(in(pred(out) is multi), in(pred(in, in, out) is det), in, out) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is multi), in(pred(in, in, out) is cc_multi), in, out) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is multi), in(pred(in, di, uo) is det), di, uo) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is multi), in(pred(in, di, uo) is cc_multi), di, uo) is cc_multi. :- mode unsorted_aggregate(in(pred(muo) is multi), in(pred(mdi, di, uo) is det), di, uo) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is nondet), in(pred(in, di, uo) is det), di, uo) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is nondet), in(pred(in, di, uo) is cc_multi), di, uo) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is nondet), in(pred(in, in, out) is det), in, out) is cc_multi. :- mode unsorted_aggregate(in(pred(out) is nondet), in(pred(in, in, out) is cc_multi), in, out) is cc_multi. :- mode unsorted_aggregate(in(pred(muo) is nondet), in(pred(mdi, di, uo) is det), di, uo) is cc_multi. % unsorted_aggregate2/6 generates all the solutions to a predicate % and applies an accumulator predicate to each solution in turn. % Declaratively, the specification is as follows: % % unsorted_aggregate2(Generator, AccumulatorPred, !Acc1, !Acc2) <=> % unsorted_solutions(Generator, Solutions), % list.foldl2(AccumulatorPred, Solutions, !Acc1, !Acc2). % % Operationally, however, unsorted_aggregate2/6 will call the % AccumulatorPred for each solution as it is obtained, rather than % first building a list of all the solutions. % :- pred unsorted_aggregate2(pred(T), pred(T, A, A, B, B), A, A, B, B). :- mode unsorted_aggregate2(in(pred(out) is multi), in(pred(in, in, out, in, out) is det), in, out, in, out) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is multi), in(pred(in, in, out, in, out) is cc_multi), in, out, in, out) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is multi), in(pred(in, in, out, di, uo) is det), in, out, di, uo) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is multi), in(pred(in, in, out, di, uo) is cc_multi), in, out, di, uo) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is nondet), in(pred(in, in, out, in, out) is det), in, out, in, out) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is nondet), in(pred(in, in, out, in, out) is cc_multi), in, out, in, out) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is nondet), in(pred(in, in, out, di, uo) is det), in, out, di, uo) is cc_multi. :- mode unsorted_aggregate2(in(pred(out) is nondet), in(pred(in, in, out, di, uo) is cc_multi), in, out, di, uo) is cc_multi. % This is a generalization of unsorted_aggregate which allows the % iteration to stop before all solutions have been found. % Declaratively, the specification is as follows: % % do_while(Generator, Filter, !Acc) :- % unsorted_solutions(Generator, Solutions), % do_while_2(Solutions, Filter, !Acc). % % do_while_2([], _, !Acc). % do_while_2([X | Xs], Filter, !Acc) :- % Filter(X, More, !Acc), % ( % More = yes, % do_while_2(Xs, Filter, !Acc) % ; % More = no % ). % % Operationally, however, do_while/4 will call the Filter % predicate for each solution as it is obtained, rather than % first building a list of all the solutions. % :- pred do_while(pred(T), pred(T, bool, T2, T2), T2, T2). :- mode do_while(in(pred(out) is multi), in(pred(in, out, in, out) is det), in, out) is cc_multi. :- mode do_while(in(pred(out) is multi), in(pred(in, out, di, uo) is det), di, uo) is cc_multi. :- mode do_while(in(pred(out) is multi), in(pred(in, out, di, uo) is cc_multi), di, uo) is cc_multi. :- mode do_while(in(pred(out) is nondet), in(pred(in, out, in, out) is det), in, out) is cc_multi. :- mode do_while(in(pred(out) is nondet), in(pred(in, out, di, uo) is det), di, uo) is cc_multi. :- mode do_while(in(pred(out) is nondet), in(pred(in, out, di, uo) is cc_multi), di, uo) is cc_multi. %--------------------------------------------------% %--------------------------------------------------%
Next: sparse_bitset, Previous: set_unordlist, Up: Top [Contents]