Re: suspending until several variables are all instantiated

From: Andrew Eremin <a.eremin_at_icparc.imperial.ac.uk>
Date: Mon 05 Sep 2005 05:17:05 PM GMT
Message-ID: <431C7D91.7030906@icparc.imperial.ac.uk>
Matthew,

> suspend(C is A+B, 1, A->inst),
>
> will suspend until A is instantiated, is it possible to suspend until 
> several variables are instantiated (for example both A and B) as this 
> is required for certain constraints?
>
> suspend(C is A+B, 1, [A->inst, B->inst]),
>
> and
>
> suspend(C is A+B, 1, [A, B]->inst),
>
> both seem to suspend until either A or B are instantiated, resulting 
> in an instantiation fault in some cases.
>
> Thanks,
> Matthew

You cannot specify that a suspended predicate wakes only when both
variables become instantiated, in the way that you want. You need to
define your own predicate that wakes if either variable becomes
instantiated but immediately resuspends itself if the other is not. This
is discussed in detail in the Advanced Control Features section of the
User Manual, but I'll outline briefly what is needed.

In this case, you need to do define your own predicate, let's call it
my_plus/3, and suspend it pending instantiation of the variables as you
did above. Now, when my_plus/3 is woken on instantiation of either A or
B, the first thing it should do is check whether both are now
instantiated. If they are it will succeed with C being unified with the
result; if not it will resuspend itself until the remaining variable is
instantiated:

Version 5.8 #82, Wed Feb 16 00:08 2005
[eclipse 1]: [user].
  my_plus(A,B,C) :-
     ( var(A) ->
         % B must have been instantiated to cause this waking
         suspend(my_plus(A, B, C), 1, A->inst)
     ; var(B) ->
         % A must have been instantiated to cause this waking
         suspend(my_plus(A, B, C), 1, B->inst)
     ;
         C is A + B
     ).
            user       compiled traceable 536 bytes in 0.00 seconds

Yes (0.00s cpu)
[eclipse 2]: suspend(my_plus(A, B, C), 1, [A, B]->inst).

A = A
B = B
C = C


Delayed goals:
         my_plus(A, B, C)
Yes (0.00s cpu)
[eclipse 3]: suspend(my_plus(A, B, C), 1, [A, B]->inst), A = 1.

A = 1
B = B
C = C


Delayed goals:
         my_plus(1, B, C)
Yes (0.00s cpu)
[eclipse 4]: suspend(my_plus(A, B, C), 1, [A, B]->inst), A = 1, B = 2.

A = 1
B = 2
C = 3
Yes (0.00s cpu)

Now, each time the goal my_plus wakes and resuspends itself a new
suspension is created. In order to support this type of checking and
resuspending the same goal, demon predicates are provided. Essentially,
you declare a predicate to be a demon, and whenever a suspension for
that goal is woken, it is automatically resuspended. If all the
pre-conditions for which the goal is waiting have not been satisfied,
nothing needs to be done. When all the pre-conditions have been
satisfied and the goal has been executed you normally wish for the
suspension to be killed: this must now be done explicitly. In order to
do this we need to provide the Suspension as an extra argument to the
predicate. So:

Version 5.8 #82, Wed Feb 16 00:08 2005
[eclipse 1]: [user].
   :- demon my_plus/4.
   my_plus(A,B,C,Susp) :-
     ( var(A) ->
         true
     ; var(B) ->
         true
     ;
         C is A + B,
         kill_suspension(Susp)
     ).
  user       compiled traceable 300 bytes in 0.00 seconds

Yes (0.00s cpu)
[eclipse 2]: suspend(my_plus(A,B,C,Susp),1,[A,B]->inst,Susp).

A = A
B = B
C = C
Susp = 'SUSP-_309-susp'


Delayed goals:
         my_plus(A, B, C, 'SUSP-_309-susp')
Yes (0.00s cpu)
[eclipse 3]: suspend(my_plus(A,B,C,Susp),1,[A,B]->inst,Susp), A = 1.

A = 1
B = B
C = C
Susp = 'SUSP-_337-susp'


Delayed goals:
         my_plus(1, B, C, 'SUSP-_337-susp')
Yes (0.00s cpu)
[eclipse 4]: suspend(my_plus(A,B,C,Susp),1,[A,B]->inst,Susp), A = 1, B = 2.

A = 1
B = 2
C = 3
Susp = 'SUSP-_365-dead'
Yes (0.00s cpu)


-- 
Andrew Eremin
Research Associate                   Tel: +44 (0)20 7594 8446
IC-Parc, Imperial College London     Fax: +44 (0)20 7594 8432
London SW7 2AZ                       Email: a.eremin@icparc.imperial.ac.uk
Received on Tue Sep 06 19:55:00 2005

This archive was generated by hypermail 2.1.8 : Wed 16 Nov 2005 06:07:39 PM GMT GMT