[mercury-users] About unification and AI

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Apr 26 07:05:09 AEST 2004

On 23-Apr-2004, Maurizio Colucci <seguso.forever at tin.it> wrote:
> demon:-

Rather than using assertions that update a global database which is
implicitly visible everwhere, in Mercury you would explicitly pass the
database as an argument.

So in Mercury, this would be

	demon(Database0, Database) :-
	demon(!Database) :-

>         % try all the matchings between events and rules...
> 	forall( (rule(Pre, Inf),
> 		 member(P, Pre),
> 		 eventDef(_, E),
> 		 P = E), % this unification binds variables globally! 
>                          % P, Pre, Inf are all changed!
> 		(   remove2(P, Pre, Pre2), % obvious
> 		    ifThePreconditionsAreAllSatisfiedThenAssertTheConsequences(
>                       Pre2, 
>                       (Pre, Inf)))).

In Mercury, you would use aggregate or unsorted_aggregate
(from the std_util module) instead of forall/2.

	demon(Database0, Database) :-
		(pred((P,Pre,Inf,RuleVars)::out) is nondet :-
		    rule(Pre, Inf, RuleVars0, Database0),
		    member(P, Pre),
		    eventDef(_, E, Database0),
		    unify(P, E, RuleVars0, RuleVars)),
		(pred((P_,Pre_,Inf_,RuleVars_)::in, Db0::in, Db::out) is det :-
		    remove2(P_, Pre_, Pre2),
                        Pre2, (Pre_, Inf_), RuleVars_, Db0, Db)),

Here "RuleVars" is a varset which holds the bindings of the variables in the
rule, and unify/4 is the one from samples/interpreter.m (which really ought
to go in the Mercury standard library).

> ifThePreconditionsAreAllSatisfiedThenAssertTheConsequences([], Rule):-
> 	assertAllInferencesAndDerivations(Rule).
> ifThePreconditionsAreAllSatisfiedThenAssertTheConsequences(
> 		Pre, Rule):-
> 	forall(	(  member(P, Pre),
> 		   eventDef(_, Ev),
> 		   P=Ev), % Inference has been instantiated too.
> 		( remove2(P, Pre, Pre2),
> 		  ifThePreconditionsAreAllSatisfiedThenAssertTheConsequences(Pre2,  Rule))).

This would be handled similarly to the one above.

> ifThePreconditionsAreAllSatisfiedThenAssertTheConsequences(_, _):-
> 	abort(ifThePreconditionsAreAllSatisfiedThenAssertTheConsequences-failed).

This would be unnecessary in Mercury -- just declare the procedure as
"det" (or "cc_multi" if you're using unsorted_aggregate), and then the
compiler will ensure that it can't fail.

> assertAllInferencesAndDerivations(Rule):-
> 	Rule = (Preconditions, Inferences),
> 	integrityCheck(ground(Preconditions)),
> 	(   thisStuffIsAlreadyAsserted(Rule)->true
> 	;	    
> 	(   free_variables(Inferences, FreeVars), % The power of prolog :-)

In Mercury, you could use

	assertAllInferencesAndDerivations(Rule, RuleVars, Db0, Db):-
		(   thisStuffIsAlreadyAsserted(Rule, Db0)->true
		(   free_variables(Inferences, RuleVars, FreeVars),


	:- func free_variables(term, varset) = list(var).
	free_variables(Term, VarSet) = FreeVars :-
		BoundVars = map.keys(varset.get_bindings(VarSet)),
		FreeVars = list.delete_all(term.vars(Term), BoundVars).

> 	    bindEachFreeVarToANewConstant(FreeVars),

In Mercury, you could use 

 	    bindEachFreeVarToANewConstant(FreeVars, Db0, Db),

where the database type would have a field that records the next
available constant.

Fergus Henderson                    |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe

More information about the users mailing list