// ---------------------------------------------------------------------- // definition of propositions: // atomic propositions // ap : type. // // ctl propositions // ctl : type. // ctl_ap : ap -> ctl. // ctl_not : ctl -> ctl. // ctl_true : ctl. // ctl_and : ctl -> ctl -> ctl. // ctl_or : ctl -> ctl -> ctl. // ctl_ex : ctl -> ctl. // ctl_eg : ctl -> ctl. // ctl_ef : ctl -> ctl. // ctl_ax : ctl -> ctl. // ctl_ag : ctl -> ctl. // ctl_af : ctl -> ctl. // ok : ctl -> type // The predicate ok(A) // means A is a subformula of the input formula that you want to check // We need this so saturation terminates ok(?a) :- ok(ctl_not(?a)). ok(?a) :- ok(ctl_and(?a,?b)). ok(?b) :- ok(ctl_and(?a,?b)). ok(?a) :- ok(ctl_or(?a,?b)). ok(?b) :- ok(ctl_or(?a,?b)). ok(?a) :- ok(ctl_ex(?a)). ok(?a) :- ok(ctl_eg(?a)). // TASK: Add cases for ok for ctl_ef, ctl_ax, ctl_ag, and ctl_af // ---------------------------------------------------------------------- // models : state -> ctl -> type // invariant: if models(s,a) then state(s) and ok(a) // Therefore, if we ever add models(s,a) to the database, // 'a' is a subformula of the input, so saturation terminates. models(?s,ctl_true()). models(?s,ctl_ap(?a)) :- ok(ctl_ap(?a)), apmodels(?s,?a). models(?s,ctl_not(?a)) :- ok(ctl_not(?a)), state(?s), // because IRIS is untyped, // we need to strict s to be a state with a predicate not models(?s,?a). models(?s,ctl_and(?a1,?a2)) :- ok(ctl_and(?a1,?a2)), models(?s,?a1), models(?s,?a2). models(?s, ctl_or(?a1, ?a2)) :- ok(ctl_or(?a1, ?a2)), models(?s, ?a1). models(?s, ctl_or(?a1, ?a2)) :- ok(ctl_or(?a1, ?a2)), models(?s, ?a2). models(?s, ctl_ex(?a)) :- ok(ctl_ex(?a)), edge(?s,?s1), models(?s1, ?a). models(?s, ctl_eg(?a)) :- ok(ctl_eg(?a)), pathallmodel(?s, ?s1, ?a), pathallmodel(?s1, ?s1, ?a). // TASK: add cases for models for ctl_ef, ctl_ax, ctl_ag, and ctl_af // Make sure you maintain the invariant that state(s) and ok(a) // path all model // invariant: if pathallmodel(s1,s2,a) then state(s1) and state(s2) and ok(a) pathallmodel(?s1, ?s3, ?a) :- edge(?s1, ?s2), models(?s1, ?a), pathallmodel(?s2, ?s3, ?a). pathallmodel(?s1, ?s2, ?a) :- edge(?s1, ?s2), models(?s1, ?a), models(?s2, ?a). // ---------------------------------------------------------------------- // INPUT-SPECIFIC // states for microwave state('a'). // cooking, door closed state('b'). // not cooking, door closed state('c'). // not cooking, door open state('d'). // cooking, door open // edge : state -> state -> type // invariant: if edge(s1,s2) then state(s1) and state(s2) edge('a','b'). edge('b','a'). edge('b','c'). edge('c','b'). edge('d','d'). // atomic propositions models : state -> string -> type // invariant: if apmodels(s,ap) then state(s) apmodels('a','cooking'). // not apmodels('a','open'). // not apmodels('b','open'). // not apmodels('b','cooking'). apmodels('c','open'). // not apmodels('c','cooking'). apmodels('d','open'). apmodels('d','cooking'). // the queries // radiation leak: door is open but microwave is cooking (SHOULD BE: d) ok(ctl_and(ctl_ap('open'),ctl_ap('cooking'))). ?- models(?a,ctl_and(ctl_ap('open'),ctl_ap('cooking'))). // safe states: can never reach an error state (SHOULD BE: a b c) ok(ctl_ag(ctl_not(ctl_and(ctl_ap('open'),ctl_ap('cooking'))))). ?- models(?a,ctl_ag(ctl_not(ctl_and(ctl_ap('open'),ctl_ap('cooking'))))). // can eventually make dinner (SHOULD BE: all) ok(ctl_ef(ctl_ap('cooking'))). ?- models(?a,ctl_ef(ctl_ap('cooking'))). // (SHOULD BE: b d) ok(ctl_ex(ctl_or(ctl_ap('cooking'),ctl_ap('open')))). ?- models(?a,ctl_ex(ctl_or(ctl_ap('cooking'),ctl_ap('open')))). // (SHOULD BE: b d) ok(ctl_ax(ctl_or(ctl_ap('cooking'),ctl_ap('open')))). ?- models(?a,ctl_ax(ctl_or(ctl_ap('cooking'),ctl_ap('open')))). // (SHOULD BE: a c d) ok(ctl_ex(ctl_ex(ctl_or(ctl_ap('cooking'),ctl_ap('open'))))). ?- models(?a,ctl_ex(ctl_ex(ctl_or(ctl_ap('cooking'),ctl_ap('open'))))). // (SHOULD BE: a b c) ok(ctl_af(ctl_not(ctl_ap('open')))). ?- models(?a,ctl_af(ctl_not(ctl_ap('open')))).