let ltl_to_neg_dnf (f : Types.ltl_type) : Types.if_term list list =
let lists_from_dnf f =
let rec list_from_dij = function
| Dij(f1,f2) -> (list_from_dij f1) @ (list_from_dij f2)
| x -> [x]
in
let rec list_from_conj = function
| Pred(str) -> [str]
| Conj(f1,f2) -> (list_from_conj f1) @ (list_from_conj f2)
| x -> failwith "list_from_conj: impossible case"
in
List.map list_from_conj (list_from_dij f)
in
let rec ltl_to_dnf neg = function
| Pred(Ifnot(str)) ->
if neg then
Pred(str)
else
Pred(Ifnot(str))
| Pred(str) ->
if neg then
Pred(Ifnot(str))
else
Pred(str)
| Op5(f) ->
ltl_to_dnf (not neg) f
| Conj(f1,f2) ->
if neg then
ltl_to_dnf false (Dij(Op5(f1),Op5(f2)))
else
let f1' = ltl_to_dnf false f1
and f2' = ltl_to_dnf false f2
in
(match f1' with
Dij(f1a,f1b) ->
Dij(ltl_to_dnf false (Conj(f1a,f2')),
ltl_to_dnf false (Conj(f1b,f2')))
| _ ->
(match f2' with
Dij(f2a,f2b) ->
Dij(ltl_to_dnf false (Conj(f1',f2a)),
ltl_to_dnf false (Conj(f1',f2b)))
| _ ->
Conj(f1',f2')))
| Dij(f1,f2) ->
if neg then
ltl_to_dnf false (Conj(Op5(f1),Op5(f2)))
else
let f1' = ltl_to_dnf false f1
and f2' = ltl_to_dnf false f2
in
Dij(f1',f2')
| Impl(f1,f2) ->
ltl_to_dnf neg (Dij(Op5(f1),f2))
| x -> x
in
lists_from_dnf (ltl_to_dnf true f)