# SWI-Prolog sCASP -- replicating Event Calculus examples

I have been experimenting with the sCASP system – in particular trying to reproduce results from:

Joaquın Arias, Manuel Carro, Zhuo Chen, Gopal Gupta
Modeling and Reasoning in Event Calculus using Goal-Directed Constraint Answer Set Programming
(accessed from https://arxiv.org/pdf/2106.14566.pdf)

sCASP is extremely impressive and I look forward to applying it to real-world domains.

I have tried both the stable (9.0.4) and development (9.1.6) versions of SWI-Prolog and in both, using sCASP (version: 0.9.0), I get the same results.

For the simple light problem in figure 4 of the paper my code is:

``````/* bec_fig_04_light.pl

Steve Moyle 2023

Experiments with the Event Calculus using sCASP on SWI-Prolog version 9.0.4.

Attempting to reproduce results from:
Joaquın Arias, Manuel Carro, Zhuo Chen, Gopal Gupta
Modeling and Reasoning in Event Calculus using Goal-Directed Constraint Answer Set Programming
(accessed from https://arxiv.org/pdf/2106.14566.pdf)
*/

:- use_module(library(scasp)).

% BASIC EVENT CALCULUS (BEC) THEORY

:- discontiguous holdsAt/2.
:- discontiguous '-holdsAt'/2.

% BEC1 - StoppedIn(t1,f,t2)
stoppedIn(T1, Fluent, T2) :-
T1 #< T, T #< T2,
terminates(Event, Fluent, T),
happens(Event, T).

stoppedIn(T1, Fluent, T2) :-
T1 #< T, T #< T2,
releases(Event, Fluent, T),
happens(Event, T).

% BEC2 - StartedIn(t1,f,t2)
startedIn(T1, Fluent, T2) :-
T1 #< T, T #< T2,
initiates(Event, Fluent, T),
happens(Event, T).

startedIn(T1, Fluent, T2) :-
T1 #< T, T #< T2,
releases(Event, Fluent, T),
happens(Event, T).

% BEC3 - HoldsAt(f,t)
holdsAt(Fluent2, T2) :-
initiates(Event, Fluent1, T1),
happens(Event, T1),
trajectory(Fluent1, T1, Fluent2, T2),
not stoppedIn(T1, Fluent1, T2).

% BEC4 - HoldsAt(f,t)
holdsAt(Fluent, T) :-
0 #< T,
initiallyP(Fluent),
not stoppedIn(0, Fluent, T).

% BEC5 - not HoldsAt(f,t)
-holdsAt(Fluent, T) :-
0 #< T,
initiallyN(Fluent),
not startedIn(0, Fluent, T).

% BEC6 - HoldsAt(f,t)
holdsAt(Fluent, T2) :-
T1 #< T2,
initiates(Event, Fluent, T1),
happens(Event, T1),
not stoppedIn(T1, Fluent, T2).

% BEC7 - not HoldsAt(f,t)
-holdsAt(Fluent, T2) :-
T1 #< T2,
terminates(Event, Fluent, T1),
happens(Event, T1),
not startedIn(T1, Fluent, T2).

% End of BEC

% Encoding of Event Calculus narrative from Figure 4 from in paper (page 19)

% Actions
happens(turn_on, 2).
happens(turn_off, 4).
happens(turn_on, 5).

initiates(turn_on, on, _T).

terminates(turn_off, on, _T).
terminates(turn_off, red, _T).
terminates(turn_off, green, _T).

trajectory(on, T1, red, T2) :-
T2 #>= T1,
T2#<T1 + 1.

trajectory(on, T1, green, T2) :-
T2 #>= T1 + 1.

releases(turn_on, red, _T).
releases(turn_on, green, _T).

/* End of bec_fig_04_light.pl  */
``````

I get matching answers to the paper for:

``````?- ? holdsAt(on, 3).

Warning: scasp_predicate `'user:initiallyN'/1' does not exist
Warning: scasp_predicate `'user:initiallyP'/1' does not exist
:
``````

But for

``````?- ? -holdsAt(on, 4.5).

Warning: scasp_predicate `'user:initiallyN'/1' does not exist
Warning: scasp_predicate `'user:initiallyP'/1' does not exist
ERROR: Type error: `rational' expected, found `4.5' (a float)
:
``````

In the paper (page 23) the query should succeed. The paper has a footnote (7, page 23) that states that 4.5 is automatically converted to a rational so the constraint solver can deal with it.

``````?- ? holdsAt(F, 3).
:
``````

Works as expected from the paper.

Note that a positive literal query with a float works as expected (NB: this is not from the paper).

``````? holdsAt(on, 4.5).

Warning: scasp_predicate `'user:initiallyN'/1' does not exist
Warning: scasp_predicate `'user:initiallyP'/1' does not exist
false.
``````

The paper contains a second Event Calculus example using the same Basic Event Calculus (BEC) framework. In the following code I have removed the BEC from the top (it is the same as the first code above).

``````% Fig. 5: Encoding of an Event Calculus narrative with continuous change

:- discontiguous happens/2.
:- discontiguous initiates/3.
:- discontiguous terminates/3.

max_level(10) :- not max_level(16).
max_level(16) :- not max_level(10).

initiallyP(level(0)).

happens(overflow,_T).
happens(tapOn,5).

initiates(tapOn,filling,_T).
terminates(tapOff,filling,_T).
initiates(overflow,spilling,T):-
max_level(Max),
holdsAt(level(Max), T).

releases(tapOn,level(0),T):-
happens(tapOn,T).
trajectory(filling,T1,level(X2),T2):-
T1 #< T2,
X2 #= X + 4/3*(T2-T1),
max_level(Max),
X2 #=< Max,
holdsAt(level(X),T1).
trajectory(filling,T1,overlimit,T2):-
T1 #< T2,
X2 #= X + 4/3*(T2-T1),
max_level(Max),
X2 #> Max,
holdsAt(level(X),T1).

trajectory(spilling,T1,leak(X),T2):-
holdsAt(filling, T2),
T1 #< T2,
X #= 4/3*(T2-T1).
``````

Replicating queries from section 4.1 Deduction (Page 23 of the paper)

``````?- ? holdsAt(level(H),15/2).
Warning: scasp_predicate `'user:initiallyN'/1' does not exist
H = 10r3,
``````

Works as expected, whilst the following does not.

``````?- ? holdsAt(level(10/3),T).
Warning: scasp_predicate `'user:initiallyN'/1' does not exist
ERROR: Type error: `rational' expected, found `10/3' (a compound)
:
``````

In the paper (page 23), `T=15/2`.

Question: What is it about floats/rationals and or positive or negative queries that is causing my issues?

Overall, I remain super impressed with sCASP and am excited about its development.

Best wishes,

Steve

PS: I can provide stack traces if this cannot be easily reproduced.