Theory Propositional_Formula

section ‹Propositional Formulas and CNFs›

text ‹We provide a straight-forward definition of propositional formulas, defined as arbitray formulas
  using variables, negations, conjunctions and disjunctions. CNFs are represented as lists of lists of 
  literals and then converted into formulas.›

theory Propositional_Formula
  imports Main
begin

subsection ‹Propositional Formulas›

datatype 'a formula = 
  Prop 'a | 
  Conj "'a formula list" | 
  Disj "'a formula list" | 
  Neg "'a formula" |
  Impl "'a formula" "'a formula" |
  Equiv "'a formula" "'a formula" 

fun eval :: "('a  bool)  'a formula  bool" where
  "eval v (Prop x) = v x" 
| "eval v (Neg f) = (¬ eval v f)" 
| "eval v (Conj fs) = ( f  set fs. eval v f)"  
| "eval v (Disj fs) = ( f  set fs. eval v f)"  
| "eval v (Impl f g) = (eval v f  eval v g)"  
| "eval v (Equiv f g) = (eval v f  eval v g)"  

text ‹Definition of propositional formula size: number of connectives›

fun size_pf :: "'a formula  nat" where
  "size_pf (Prop x) = 1" 
| "size_pf (Neg f) = 1 + size_pf f" 
| "size_pf (Conj fs) = 1 + sum_list (map size_pf fs)"  
| "size_pf (Disj fs) = 1 + sum_list (map size_pf fs)"  
| "size_pf (Impl f g) = 1 + size_pf f + size_pf g"  
| "size_pf (Equiv f g) = 1 + size_pf f + size_pf g"  

subsection ‹Conjunctive Normal Forms›

type_synonym 'a clause = "('a × bool) list" 
type_synonym 'a cnf = "'a clause list" 

fun formula_of_lit :: "'a × bool  'a formula" where
  "formula_of_lit (x,True) = Prop x" 
| "formula_of_lit (x,False) = Neg (Prop x)" 

definition formula_of_cnf :: "'a cnf  'a formula" where
  "formula_of_cnf = (Conj o map (Disj o map formula_of_lit))" 

definition eval_cnf :: "('a  bool)  'a cnf  bool" where
  "eval_cnf α cnf = eval α (formula_of_cnf cnf)" 

lemma eval_cnf_alt_def: "eval_cnf α cnf = Ball (set cnf) (λ c. Bex (set c) (λ l. α (fst l) = snd l))" 
  unfolding eval_cnf_def formula_of_cnf_def o_def eval.simps set_map Ball_image_comp bex_simps
  apply (intro ball_cong bex_cong refl)
  subgoal for c l by (cases l; cases "snd l", auto) 
  done


text ‹The size of a CNF is the number of literals + the number of clauses, i.e., 
  the sum of the lengths of all clauses + the length.›

definition size_cnf :: "'a cnf  nat" where
  "size_cnf cnf = sum_list (map length cnf) + length cnf"


end