capacity(1, N) :- N>=0.0, N=<350.0. capacity(2, N) :- N>=0.0, N=<180.0. capacity(3, N) :- N>=0.0, N=<50.0. |
delay capacity(T,N) if var(T);var(N). capacity(1, N) :- N>=0.0, N=<350.0. capacity(2, N) :- N>=0.0, N=<180.0. capacity(3, N) :- N>=0.0, N=<50.0. |
:- lib(ic). delay capacity(T, N) if var(T), var(N). capacity(T, N) :- nonvar(N), !, N >= 0, ( N =< 50.0 -> T :: [1,2,3] ; N =< 180.0 -> T :: [1,2] ; N =< 350.0 -> T = 1 ; fail ). capacity(1, N) :- N$>=0.0, N$=<350.0. capacity(2, N) :- N$>=0.0, N$=<180.0. capacity(3, N) :- N$>=0.0, N$=<50.0. |
A disadvantage of the above implementation is that when the predicate wakes up, it can be either because T was instantiated, or because C was instantiated. An extra check (nonvar(N)) is needed to distinguish the two cases. Alternatively, we could have created two agents (delayed goals), each one specialised for one of these cases:?- capacity(T, C). There is 1 delayed goal. Yes (0.00s cpu) ?- capacity(3, C). C = C{0.0 .. 50.0} Yes (0.00s cpu) ?- capacity(T, C), C = 100. T = T{[1, 2]} C = 100 Yes (0.00s cpu)
capacity(T, N) :- capacity_forward(T, N), capacity_backward(T, N). delay capacity_forward(T, _N) if var(T). capacity_forward(1, N) :- N$>=0.0, N$=<350.0. capacity_forward(2, N) :- N$>=0.0, N$=<180.0. capacity_forward(3, N) :- N$>=0.0, N$=<50.0. delay capacity_backward(_T, N) if var(N). capacity_backward(T, N) :- N >= 0, ( N =< 50.0 -> T :: [1,2,3] ; N =< 180.0 -> T :: [1,2] ; N =< 350.0 -> T = 1 ; fail ). |