We now give an implementation of a tableau calculus for the basic modal logic S4. We use a tableau version of the sequent calculus from Heuerding.
In the following we use two histories, DIAMONDS for the diamond history and BOXES for the box history. Intuitively, the diamond history contains certain diamond formulae found in the branch from the root to the current node. The box history contains all the boxes found in the branch from the root to the current node.
The modal tableau rules shown below are an adaptation of Heuerding's sequent rules. source K module FormulaSet = TwbSet.Make( struct type t = formula let to_string = formula_printer let copy s = s end ) HISTORIES DIAMONDS : FormulaSet.set := new FormulaSet.set; BOXES : FormulaSet.set := new FormulaSet.set END open Twblib open Klib TABLEAU RULE S4 { <> A } ; Z --- A ; BOXES COND notin(<> A, DIAMONDS) ACTION [ DIAMONDS := add(<> A,DIAMONDS) ] END RULE T { [] A } === A COND notin(A, BOXES) ACTION [ BOXES := add(A,BOXES); DIAMONDS := emptyset(DIAMONDS)] END RULE Id { a } ; { ~ a } === Close END RULE False Falsum === Close END RULE And { A & B } === A ; B END RULE Or { A v B } === A | B END END STRATEGY := let sat = tactic ( (False ! Id ! And ! T ! Or) ) in tactic ( ( (sat)* ; S4 )* ) PP := List.map nnf NEG := List.map neg MAIN
In particular the (T)-rule is applied to a principal formula [] P only if its sub-formula P is not in the history BOXES. If notin(P,BOXES) , the denominator is created from the current rule by deleting [] P and adding P. The formula P is added to the history BOXES and the diamond history DIAMONDS is emptied.
RULE T { [] A } ======== A COND notin(A, BOXES) ACTION [ BOXES := add(A,BOXES); DIAMONDS := emptyset(DIAMONDS)] END
Since the Kripke models for the logic S4 are transitive, box formulae always accumulate. In the calculus, the (T)-rule is applied only if the immediate sub-formulae P of the box formula [] P under consideration is "new" (not present in the box history) in the branch, thus exploiting transitivity. Intuitively, if a box formula is new in a branch, we force the procedure "to recompute", by forgetting (empting DIAMONDS) any information about the diamond formulae found so far.
RULE S4 { <> A } ; Z ----------------- A ; BOXES COND notin(<> A, DIAMONDS) ACTION [ DIAMONDS := add(<> A,DIAMONDS) ] END
Similarly, the S4 rule is applied only if its diamond formula <> P is not present in the diamond history DIAMONDS. If notin(<>P,DIAMONDS), then the formula P and the content of the box history DIAMONDS is added to the denominator. The context Z is discarded and the formula <> P is the diamond history DIAMONDS. The box history BOXES is unchanged.
let add (l,h) = h#addlist l let notin (l,h) = not(h#mem (List.hd l)) let emptyset h = h#empty