Home > Archive > Prolog > July 2004 > Writing Mercury's aggregate/4 in prolog
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Writing Mercury's aggregate/4 in prolog
|
|
| seguso 2004-07-14, 8:57 pm |
| Hello,
My Prolog program has a predicate producer/4. producer/4 takes as input a
rule and a database of facts, and returns a new database of facts that may
or may not have been changed:
producer(Pre, Rule, Facts, Facts2):-
% ... the precondition is found in the facts...
Facts2 = [NewFact | Facts]. % assert a new fact
producer(Pre, Rule, Facts, Facts):-
% ... the precondition is not found in the facts. Leave Facts unchanged
Now I want to write run_step/3 that takes a _list_ of rules, and runs a
producer on each rule. Each producer should run with the database of facts
output by the previous one!
Instead of writing an explicit recursive loop, I'd like to write like in
Mercury:
run_step(Facts, Rules, Facts2):-
aggregate( member(rule(Precond, Inference), Rules),
producer(Precond, rule(Precond, Inference)),
Facts,
Facts2).
I tried to write aggregate/4, but I can't. I believe I have to use
free_variables/2, but I need some help.
Thanks a lot :-)
--
Best Regards,
Maurizio Colucci
Please remove the uppercase letters "S,P,A,M":
seSgPuAsMo.forever@tin.it
| |
| Georgios Tagalakis 2004-07-15, 3:58 am |
| [snip]
> I tried to write aggregate/4, but I can't. I believe I have to use
> free_variables/2, but I need some help.
You can find a definition of aggregate/4 in Prolog here:
www.sics.se/~alf/prolog/akl/environment/aggregate.pl
--- Georgios Tagalakis
| |
| seguso 2004-07-15, 8:57 am |
| Georgios Tagalakis wrote:
> [snip]
>
> You can find a definition of aggregate/4 in Prolog here:
> www.sics.se/~alf/prolog/akl/environment/aggregate.pl
>
> --- Georgios Tagalakis
Thank you, but... do you call this prolog?
aggregate(Generator,Collect,Unit,Aggrega
te)
:-
true
, (akl:'COLLECTOR'(A,Aggregate),
akl:aggregate_aux(Generator,Collect,Unit
,A)).
%akl. aggregate_aux(arg(0),arg(1),arg(2),arg(3
))
aggregate_aux(G,Collect,_0,A)
:-
true
, akl:'ORDER'(apply(G,[X]),A,A1,A2,apply(C
ollect,[X,A2,A1])).
--
Best Regards,
Maurizio Colucci
Please remove the uppercase letters "S,P,A,M":
seSgPuAsMo.forever@tin.it
| |
| seguso 2004-07-15, 3:59 pm |
| Here it is: thanks to Alan Baljeu!
aggregate(Generator, Aggregator, Initial, Final) :-
setof(Fact, call(Generator, Fact), Facts),
fold_in(Aggregator, Facts, Initial, Final).
fold_in(_Aggregator, [], Final, Final).
fold_in(Aggregator, [F|Facts], Initial, Final) :-
call(Aggregator, F, Initial, Intermediate),
fold_in(Aggregator, Facts, Intermediate, Final).
Unfortunately it doesn't seem to be useful for my program :-(
in my program I must iterate over all possible _unifications_, not on all
possible _solutions_ of a predicate. And for each unification I must add
an _instantiated_ term to a list of terms.
The problem is: aggregate/4 requires a "generator" that generates solutions.
In my case, the "generator" is complete_matchings/2 (see below), which
generates _unifications_, not solutions. And unifications are _implicit_ in
prolog, so I cannot modify complete_matchings/2 to make it return the
unifications it generates.
It seems that I cannot reuse prolog's unification engine to create an
inferential engine. (at least, without using assert).
complete_matching(Facts, []).
complete_matching(Facts, Preconds):-
member(P, Preconds),
member(eventDef(_, Ev), Facts),
P = Ev,
remove2(P, Preconds, Pre2),
complete_matching(Facts, Pre2).
--
Best Regards,
Maurizio Colucci
Please remove the uppercase letters "S,P,A,M":
seSgPuAsMo.forever@tin.it
| |
| vannoord@let.rug.nl 2004-07-15, 3:59 pm |
| seguso <look@in.signature> wrote:
> Unfortunately it doesn't seem to be useful for my program :-(
> in my program I must iterate over all possible _unifications_, not on all
> possible _solutions_ of a predicate. And for each unification I must add
> an _instantiated_ term to a list of terms.
> The problem is: aggregate/4 requires a "generator" that generates solutions.
> In my case, the "generator" is complete_matchings/2 (see below), which
> generates _unifications_, not solutions. And unifications are _implicit_ in
> prolog, so I cannot modify complete_matchings/2 to make it return the
> unifications it generates.
> It seems that I cannot reuse prolog's unification engine to create an
> inferential engine. (at least, without using assert).
I don't quite understand what you mean, but perhaps you need the
functionality of copy_term/2 which is either built-in or in a library
for several Prologs.
Gj
--
Gertjan van Noord Alfa-informatica, RUG, Postbus 716, 9700 AS Groningen
vannoord at let dot rug dot nl http://www.let.rug.nl/~vannoord
| |
| Georgios Tagalakis 2004-07-15, 8:59 pm |
|
"seguso" <look@in.signature> wrote in message
news:sSrJc.1229$5D1.27790@news4.tin.it...
> Georgios Tagalakis wrote:
>
>
> Thank you, but... do you call this prolog?
Address your complains to the author of the code. If you ask me whether I've
found that code useful and helpful to get the idea behind aggregate and
rewrite/reuse it as I needed for my program, then the reply is "yes". If you
ask me whether I like this programming style, the reply is "no". You can use
it you can leave it. This is certainly not my concern.
--- Georgios Tagalakis
> aggregate(Generator,Collect,Unit,Aggrega
te)
> :-
> true
> , (akl:'COLLECTOR'(A,Aggregate),
> akl:aggregate_aux(Generator,Collect,Unit
,A)).
>
> %akl. aggregate_aux(arg(0),arg(1),arg(2),arg(3
))
> aggregate_aux(G,Collect,_0,A)
> :-
> true
> , akl:'ORDER'(apply(G,[X]),A,A1,A2,apply(C
ollect,[X,A2,A1])).
>
>
> --
> Best Regards,
> Maurizio Colucci
> Please remove the uppercase letters "S,P,A,M":
> seSgPuAsMo.forever@tin.it
| |
| Ralph Becket 2004-07-16, 3:57 am |
| seguso <look@in.signature> wrote in message news:<jJiJc.3671$OR2.154143@news3.tin.it>...
> Hello,
>
> My Prolog program has a predicate producer/4. producer/4 takes as input a
> rule and a database of facts, and returns a new database of facts that may
> or may not have been changed:
>
> producer(Pre, Rule, Facts, Facts2):-
> % ... the precondition is found in the facts...
> Facts2 = [NewFact | Facts]. % assert a new fact
> producer(Pre, Rule, Facts, Facts):-
> % ... the precondition is not found in the facts. Leave Facts unchanged
>
>
> Now I want to write run_step/3 that takes a _list_ of rules, and runs a
> producer on each rule. Each producer should run with the database of facts
> output by the previous one!
>
> Instead of writing an explicit recursive loop, I'd like to write like in
> Mercury:
>
> run_step(Facts, Rules, Facts2):-
> aggregate( member(rule(Precond, Inference), Rules),
> producer(Precond, rule(Precond, Inference)),
> Facts,
> Facts2).
Mercury's aggregate predicate is defined to have the following
semantics:
aggregate(P, Q, A0, A) :-
solutions(P, Xs),
foldl(Q, Xs, A0, A).
where solutions(P, Xs) binds Xs to the sorted, duplicate-free list
of solutions to P.
You can write this in Prolog as
aggregate(X, P, Q, A0, A) :-
setof(X, P, Xs),
foldl(Q, Xs, A0, A).
where X is the free variable in P which P binds to a solution and
foldl is given the obvious definition:
foldl(_, [], A, A).
foldl(Q, [X | Xs], A0, A) :-
call(Q, X, A0, A1),
foldl(Q, Xs, A1, A).
call(Closure, X1, X2, X3) :-
Closure =.. [PredName | Args0],
append(Args0, [X1, X2, X3], Args),
Goal =.. [PredName | Args],
Goal.
EXAMPLE:
If I have
p(7).
p(5).
p(3).
p(2).
cons(X, Xs, [X | Xs]).
then
?- aggregate(X, p(X), cons, [], A).
A = [7,5,3,2]
Et voila.
HOWEVER...
What I *think* you're really asking for is a version
of Mercury's unsorted_aggregate(P, Q, A0, A) that
"interleaves" the foldl of Q as each solution is
generated by P.
To do this you need some classic sordid Prologery:
unsorted_aggregate(X, P, Q, A0, A) :-
set_unsorted_aggregate_state(A0),
(
P,
unsorted_aggregate_state(A1),
call(Q, X, A1, A2),
set_unsorted_aggregate_state(A2),
fail
;
unsorted_aggregate_state(A)
).
:- dynamic(unsorted_aggregate_state/1).
set_unsorted_aggregate_state(X) :-
retractall(unsorted_aggregate_state(_)),
asserta(unsorted_aggregate_state(X)).
Ugh. After years of Mercury, that sort of thing leaves
a nasty taste in the mouth.
EXAMPLE
?- unsorted_aggregate(X, p(X), cons, [], A).
A = [2, 3, 5, 7]
Note the different order of the members of A.
CAVEAT
This definition of unsorted_aggregate isn't quite
sound: it doesn't work for nested calls. Fixing
this is straightforward and is left as an exercise
for the reader.
-- Ralph
| |
| seguso 2004-07-16, 8:58 pm |
| Ralph, thank you very much for your constant help. :-)
> You can write this in Prolog as
>
> aggregate(X, P, Q, A0, A) :-
> setof(X,Â_P,Â_Xs),
> foldl(Q,Â_Xs,Â_A0,Â_A).
>
> where X is the free variable
"the" free variable? What if P contains two free variables?
> in P which P binds to a solution and
> foldl is given the obvious definition:
I believe X can be obtained from P with
free_variables(P, X).
So you don't need to pass X to aggregate/5 explicitely. It becomes
aggregate/4.
> foldl(_, [],Â_Â_Â_Â_Â_Â_Â_A,Â_Â_A).
> foldl(Q, [X | Xs], A0, A) :-
> call(Q,Â_X,Â_A0,Â_A1),
> foldl(Q,Â_Xs,Â_A1,Â_A).
>
--
Best Regards,
Maurizio Colucci
Please remove the uppercase letters "S,P,A,M":
seSgPuAsMo.forever@tin.it
| |
| Ralph Becket 2004-07-22, 3:57 am |
| seguso <look@in.signature> wrote in message news:<cTXJc.10925$OR2.614731@news3.tin.it>...
> Ralph, thank you very much for your constant help. :-)
>
>
> "the" free variable? What if P contains two free variables?
Okay, "where X is a term possibly containing free variables in P".
I was presenting aggregate with a setof-like interface. If you
want a Mercury style interface you can just code up call/2 (same
as call/4, but with two fewer parameters) and use that instead.
>
> I believe X can be obtained from P with
>
> free_variables(P, X).
(1) This is expensive.
(2) You may not want all free variables in P.
(3) As with setof, you may want to impose some further structure on
the solutions to P.
-- Ralph
|
|
|
|
|