ATBR.DecideKleeneAlgebra
(**************************************************************************)
(* This is part of ATBR, it is distributed under the terms of the *)
(* GNU Lesser General Public License version 3 *)
(* (see file LICENSE for more details) *)
(* *)
(* Copyright 2009-2011: Thomas Braibant, Damien Pous. *)
(**************************************************************************)
(* This is part of ATBR, it is distributed under the terms of the *)
(* GNU Lesser General Public License version 3 *)
(* (see file LICENSE for more details) *)
(* *)
(* Copyright 2009-2011: Thomas Braibant, Damien Pous. *)
(**************************************************************************)
This module aggregates all DKA* modules, to obtain the decision
procedure for Kleene algebras kleene_reflexivity.
Require Import Common.
Require Import Classes.
Require Import Graph.
Require Import Converse.
Require Import DKA_Definitions.
Require DKA_CheckLabels.
Require DKA_Construction.
Require DKA_Epsilon.
Require DKA_Determinisation.
Require DKA_Merge.
Require DKA_DFA_Equiv.
Require StrictStarForm.
Require Reification.
Require Import List.
Definition word := list positive.
Inductive CounterExample: Set :=
| NotLeq: word -> CounterExample
| NotGeq: word -> CounterExample
| DifferentAtomSets: CounterExample.
Definition X_to_DFA (a: regex) :=
let a' := StrictStarForm.ssf a in
let A := DKA_Construction.X_to_eNFA a' in
let A := DKA_Epsilon.eNFA_to_NFA A (DKA_Construction.well_founded (StrictStarForm.ssf_complete a)) in
let A := DKA_Determinisation.NFA_to_DFA A in
A.
Definition translate_ce (ce: option (bool*word)) :=
match ce with
| None => None
| Some(b,w) => Some ((if b then NotLeq else NotGeq) (List.rev w))
end.
Notation clean := RegExp.Clean.rewrite.
Definition decide_kleene a b :=
let a := clean a in
let b := clean b in
if negb (DKA_CheckLabels.same_labels a b) then Some DifferentAtomSets
else translate_ce (DKA_Merge.compare_DFAs DKA_DFA_Equiv.equiv (X_to_DFA a) (X_to_DFA b)).
Lemma X_to_DFA_correct: forall a, DFA.eval (X_to_DFA a) == a.
Proof.
intro a. unfold X_to_DFA.
rewrite DKA_Determinisation.correct by apply DKA_Epsilon.bounded, DKA_Construction.bounded.
rewrite DKA_Epsilon.correct by apply DKA_Construction.bounded.
rewrite DKA_Construction.correct.
apply StrictStarForm.ssf_correct.
Qed.
Lemma X_to_DFA_bounded: forall a, DFA.bounded (X_to_DFA a).
Proof.
intro a. apply DKA_Determinisation.bounded, DKA_Epsilon.bounded, DKA_Construction.bounded.
Qed.
Lemma X_to_DFA_labels: forall a b,
DKA_CheckLabels.same_labels (clean a) (clean b) = true ->
DFA.max_label (X_to_DFA (clean a)) = DFA.max_label (X_to_DFA (clean b)).
Proof.
intros. unfold X_to_DFA.
rewrite 2 DKA_Determinisation.preserve_max_label.
rewrite 2 DKA_Epsilon.preserve_max_label.
apply DKA_Construction.same_labels_max_label.
apply DKA_CheckLabels.same_labels_ssf.
assumption.
Qed.
Lemma translate_correct: forall ce, translate_ce ce = None <-> ce = None.
Proof. intros [[b w]|]; simpl; intuition discriminate. Qed.
Theorem Kozen94: forall a b, decide_kleene a b = None <-> a == b.
Proof.
unfold decide_kleene. intros a b.
case_eq (DKA_CheckLabels.same_labels (clean a) (clean b)); simpl; intros Hm.
rewrite translate_correct.
rewrite DKA_Merge.correct; try apply X_to_DFA_bounded.
setoid_rewrite X_to_DFA_correct.
setoid_rewrite <- RegExp.Clean.correct.
reflexivity.
apply DKA_DFA_Equiv.correct.
apply X_to_DFA_labels, Hm.
split; intro H.
discriminate H.
exfalso. apply DKA_CheckLabels.complete in Hm. tauto.
Qed.
(* Print Assumptions Kozen94. *)
Import RegExp.Untype.
Import Reification.
Corollary dk_erase_correct `{KA: KleeneAlgebra} {env: Env}:
forall n m (a b: KA.X n m), decide_kleene (erase a) (erase b) = None -> KA.eval a == KA.eval b.
Proof. intros. apply erase_faithful. apply Kozen94. assumption. Qed.
Ltac display_counter_example e ce :=
let eval_word w :=
let rec build w :=
lazymatch w with
| nil => fail 1
| ?x::nil => constr:(Reification.unpack (@Reification.val _ e x))
| ?x::?q => let q := build q in constr:(q * Reification.unpack (@Reification.val _ e x))
end
in
let x := build w in
let x := eval compute [e Reification.unpack Reification.tgt Reification.src
Reification.sigma_get Reification.sigma_add Reification.sigma_empty
FMapPositive.PositiveMap.find FMapPositive.PositiveMap.add
FMapPositive.PositiveMap.empty Reification.val] in x
in x
in
match ce with
| DifferentAtomSets => fail 1 "Not a Kleene algebra theorem: different atom sets"
| NotGeq ?w =>
(try let u := eval_word w in
fail 2 "Not a Kleene Algebra theorem: " u "does not belong to the left-hand side");
fail 1 "Not a Kleene Algebra theorem: the empty word (1) does not belong to the left-hand side"
| NotLeq ?w =>
(try let u := eval_word w in
fail 2 "Not a Kleene Algebra theorem: " u "does not belong to the right-hand side");
fail 1 "Not a Kleene Algebra theorem: the empty word (1) does not belong to the right-hand side"
end.
the tactic for solving Kleene algebras equations
Ltac kleene_reflexivity :=
let e := fresh "e" in
unfold leq;
kleene_reify; intros t e l r;
apply dk_erase_correct; vm_compute;
(reflexivity || lazymatch goal with |- Some ?w = None => display_counter_example e w end).
let e := fresh "e" in
unfold leq;
kleene_reify; intros t e l r;
apply dk_erase_correct; vm_compute;
(reflexivity || lazymatch goal with |- Some ?w = None => display_counter_example e w end).
extension to Kleene algebras with converse
Ltac ckleene_reflexivity := converse_down; kleene_reflexivity.
Ltac kleene_ssf := StrictStarForm.kleene_ssf.
Ltac kleene_clean_zeros := Model_RegExp.kleene_clean_zeros.
(*begintests
Section test.
Context `{KA: KleeneAlgebra}.
Goal forall A B (a: X A B) (b: X B A), a*(b*a) == (a*b)*a.
intros.
Time kleene_reflexivity.
Abort.
Goal forall A (a b: X A A), (a+b) == a*(b*a).
intros.
Time kleene_reflexivity.
Abort.
Goal forall A (a b: X A A), a*b + a*b == a*b. intros. Time kleene_reflexivity. Abort. Goal forall A B (a c: X A B) (b: X B A), (a+c)*(b*a+b*c) == (a*b+c*b)*(a+c). intros. Time kleene_reflexivity. Abort. Goal forall A (a b: X A A), (a*b) == (a+b) . intros. try kleene_reflexivity. idtac. Abort. Goal forall A B (a: X A B) (b: X B A), a*(b*a) == (a*b)*a .
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A), a*b*a*b == a*b + a*b*a*b .
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A), a*b <== a*b*a*b.
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A) (c: X B B), a*c*(b*a) == (a*b)*a.
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A) (c: X B B), a*c*(b*a) == (a*b)*a*(1+c*0).
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A (a b: X A A), (a*0)*b == b+0*a+b*0. intros. kleene_clean_zeros. Abort. Goal forall A (a b: X A A), (a*0) <== b+0*a+0.
intros. kleene_clean_zeros.
Abort.
Goal forall A (a b: X A A), ((1+b)*(1+a)) == (a+b).
intros. kleene_ssf.
Abort.
End test.
Section ctest.
Context `{KA: ConverseKleeneAlgebra}.
Goal forall A B (a: X A B) (b: X B A), a`*(a*b)` == (b*a)`*a`.
intros.
Time ckleene_reflexivity.
Abort.
End ctest.
endtests*)
Ltac kleene_ssf := StrictStarForm.kleene_ssf.
Ltac kleene_clean_zeros := Model_RegExp.kleene_clean_zeros.
(*begintests
Section test.
Context `{KA: KleeneAlgebra}.
Goal forall A B (a: X A B) (b: X B A), a*(b*a) == (a*b)*a.
intros.
Time kleene_reflexivity.
Abort.
Goal forall A (a b: X A A), (a+b) == a*(b*a).
intros.
Time kleene_reflexivity.
Abort.
Goal forall A (a b: X A A), a*b + a*b == a*b. intros. Time kleene_reflexivity. Abort. Goal forall A B (a c: X A B) (b: X B A), (a+c)*(b*a+b*c) == (a*b+c*b)*(a+c). intros. Time kleene_reflexivity. Abort. Goal forall A (a b: X A A), (a*b) == (a+b) . intros. try kleene_reflexivity. idtac. Abort. Goal forall A B (a: X A B) (b: X B A), a*(b*a) == (a*b)*a .
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A), a*b*a*b == a*b + a*b*a*b .
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A), a*b <== a*b*a*b.
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A) (c: X B B), a*c*(b*a) == (a*b)*a.
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A B (a: X A B) (b: X B A) (c: X B B), a*c*(b*a) == (a*b)*a*(1+c*0).
intros.
try kleene_reflexivity.
idtac.
Abort.
Goal forall A (a b: X A A), (a*0)*b == b+0*a+b*0. intros. kleene_clean_zeros. Abort. Goal forall A (a b: X A A), (a*0) <== b+0*a+0.
intros. kleene_clean_zeros.
Abort.
Goal forall A (a b: X A A), ((1+b)*(1+a)) == (a+b).
intros. kleene_ssf.
Abort.
End test.
Section ctest.
Context `{KA: ConverseKleeneAlgebra}.
Goal forall A B (a: X A B) (b: X B A), a`*(a*b)` == (b*a)`*a`.
intros.
Time ckleene_reflexivity.
Abort.
End ctest.
endtests*)