(**************************************************************)
(*   Copyright Dominique Larchey-Wendling *                 *)
(*                                                            *)
(*                             * Affiliation LORIA -- CNRS  *)
(**************************************************************)
(*      This file is distributed under the terms of the       *)
(*         CeCILL v2 FREE SOFTWARE LICENSE AGREEMENT          *)
(**************************************************************)

Require Import List Permutation.

From Undecidability.ILL
  Require Import IMSELL.

From Undecidability.Shared.Libs.DLW
  Require Import utils pos vec.

Set Implicit Arguments.

(* * Intuionistic Multiplicative Linear Logic with several exponentials and modabilities *)

Local Infix "~p" := (@Permutation _) (at level 70).
Local Notation "X ⊆ Y" := ( a, X a Y a : Prop) (at level 70).
Local Infix "∊" := In (at level 70).

Local Reserved Notation "'⟦' A '⟧'" (at level 1, format "⟦ A ⟧").

Section IMSELL.

  Variable bang : Type.

  Notation "£ A" := (@imsell_var _ _ A) (at level 1).
  Notation "‼ l" := (@imsell_lban bang l).

  Fact imsell_lban_perm Σ Γ : Σ p Γ Σ p Γ.
  Proof. apply Permutation_map. Qed.

  Variable (bang_le : bang bang Prop) (bang_U : bang Prop).

  Infix "≤" := bang_le (at level 70).
  Notation U := bang_U.

  Notation "u ≼ l" := ( '(v,A), (v,A) l u v) (at level 70).
  Notation "Γ ⊢ A" := (@S_imsell _ bang_le bang_U Γ A) (at level 70).

  Fact S_imsell_weak Γ Δ B : Forall ( '(u,_) U u) Γ Δ B ΓΔ B.
  Proof.
    intros ; revert .
    induction 1 as [ | (u,A) Γ ]; simpl; auto.
    apply in_imsell_weak; auto.
  Qed.


  Fact S_imsell_gen_weak u Γ Δ B : U u Δ B map ( A ![u]A) ΓΔ B.
  Proof.
    intros .
    replace (map ( A ![u]A) Γ) with ( (map ( A (u,A)) Γ)).
    + apply S_imsell_weak; auto.
      apply Forall_forall.
      intros ?; rewrite in_map_iff.
      intros (? & & ?); auto.
    + unfold imsell_lban; rewrite map_map; auto.
  Qed.


  Fact S_imsell_cntr Γ Δ B : Forall ( '(u,_) U u) Γ ΓΓΔ B ΓΔ B.
  Proof.
    intros H; revert H Δ.
    induction 1 as [ | (u,A) Γ ]; simpl; auto; intros Δ H.
    apply in_imsell_cntr; auto.
    apply in_imsell_perm with (Γ (![u]A::![u]A::Δ)).
    + apply Permutation_sym.
      do 2 apply Permutation_cons_app; auto.
    + apply .
      revert H; apply in_imsell_perm.
      rewrite app_assoc.
      apply Permutation_cons_app.
      rewrite app_assoc.
      apply Permutation_app; auto.
      apply Permutation_cons_app; auto.
  Qed.


  Theorem S_imsell_extract Γ u A B : ![u]A Γ U u Γ B ![u]A::Γ B.
  Proof.
    intros ; split.
    + apply in_imsell_weak; auto.
    + intros .
      apply In_perm in as (Δ & ).
      apply in_imsell_perm with (1 := ).
      apply in_imsell_cntr; auto.
      apply in_imsell_perm with (2 := ).
      apply perm_skip, Permutation_sym; auto.
  Qed.


(*
 
  Theorem S_imsell_weak_cntr' Σ Γ u A B : (u,A) ∊ Σ -> U u -> ‼Σ++Γ ⊢ B <-> !uA::‼Σ++Γ ⊢ B.
  Proof.
    intros H1 H2; apply S_imsell_extract; auto.
    apply in_app_iff; left.
    apply in_map_iff.
    exists (u,A); auto.
  Qed.

*)


  Section Trivial_Phase_semantics.

    (* We only consider the monoids nat^n *)

    Variables (n : ) (s : vec n Prop).

    Notation "⦳" := vec_zero.
    Notation ø := vec_nil.

    Definition imsell_tps_mult (X Y : _ Prop) (x : vec _ n) := a b, x = vec_plus a b X a Y b.
    Definition imsell_tps_imp (X Y : _ Prop) (v : vec _ n) := x, X x Y (vec_plus x v).

    Infix "⊛" := imsell_tps_mult (at level 65, right associativity).
    Infix "-⊛" := imsell_tps_imp (at level 65, right associativity).

    Fact imsell_tps_imp_zero X Y : (X -⊛ Y) X Y.
    Proof.
      split.
      + intros ? ? ?; rewrite vec_zero_plus, vec_plus_comm; auto.
      + intros ? ?; rewrite vec_plus_comm, vec_zero_plus; auto.
    Qed.


    Variable (K : bang vec n Prop).

    Hypothesis HK_antitone : p q, p q K q K p.
    Hypothesis HK_unit0 : m, K m .
    Hypothesis HK_plus : m, K m K m K m.
    Hypothesis HK_unit1 : u, U u x, K u x x = .

    Fact imsell_tps_mult_mono (X1 X2 Y1 Y2 : _ Prop) :
               .
    Proof.
      intros x (y & z & & & ); subst.
      exists y, z; auto.
    Qed.


    Fixpoint imsell_tps (A : imsell_form bang) x : Prop :=
      match A with
        | £ X s X x
        | ![m]A A x K m x
        | AB (A-⊛B) x
      end
    where "⟦ A ⟧" := (imsell_tps A).

    Fact imsell_tps_bang_zero m A : ![m]A A .
    Proof. simpl; split; auto; tauto. Qed.

    Fact imsell_tps_bang_U u A : U u ( v, ![u]A v v = ) A .
    Proof.
      intros Hu; split.
      + intros H; rewrite imsell_tps_bang_zero, H; auto.
      + intros H v; split; simpl.
        * intros (_ & ); revert ; eauto.
        * intros ; auto.
    Qed.


    Reserved Notation "⟪ Γ ⟫" (at level 1, format "⟪ Γ ⟫").

    Fixpoint imsell_tps_list Γ :=
      match Γ with
        | nil eq
        | A::Γ AΓ
      end
    where "⟪ Γ ⟫" := (imsell_tps_list Γ).

    Fact imsell_tps_app Γ Δ x : ΓΔ x (ΓΔ) x.
    Proof.
      revert Γ Δ x; intros Ga De.
      induction Ga as [ | A Ga IH ]; intros x; simpl; split; intros Hx.
      + exists vec_zero, x; simpl; rew vec.
      + destruct Hx as (? & ? & ? & ? & ?); subst; auto; rewrite vec_zero_plus; auto.
      + destruct Hx as (y & z & & & ).
        apply IH in .
        destruct as (c & d & & & ).
        exists (vec_plus y c), d; split.
        * subst; apply vec_plus_assoc.
        * split; auto.
        exists y, c; auto.
      + destruct Hx as (y & d & ? & (z & g & ? & ? & ?) & ?).
        exists z, (vec_plus g d); split.
        * subst; symmetry; apply vec_plus_assoc.
        * split; auto.
          apply IH.
          exists g, d; auto.
    Qed.


    Fact imsell_tps_perm Γ Δ : Γ p Δ Γ Δ.
    Proof.
      induction 1 as [ | A Ga De H IH | A B Ga | ]; simpl; auto.
      + intros x (y & z & & & ).
        exists y, z; repeat split; auto.
      + intros x (y & z & & & c & d & & & ).
        exists c, (vec_plus y d); split.
        * subst; rewrite (vec_plus_comm c), vec_plus_assoc, (vec_plus_comm c); auto.
        * split; auto.
          exists y, d; auto.
    Qed.


    Fact imsell_tps_list_zero Γ : ( A, A Γ A ) Γ .
    Proof.
      induction Γ as [ | A Γ IH ]; simpl; auto; intros H.
      exists , ; msplit 2; auto; now rewrite vec_zero_plus.
    Qed.


    Definition imsell_sequent_tps Γ A := Γ -⊛ A.

    Notation "'[<' Γ '|-' A '>]'" := (imsell_sequent_tps Γ A) (at level 1, format "[< Γ |- A >]").

    Fact imsell_sequent_tps_mono Γ A B :
           A B [< Γ A >] [< Γ B >].
    Proof.
      intros H x; simpl; unfold imsell_sequent_tps.
      intros ? ; apply H, ; auto.
    Qed.


    Fact imsell_perm_tps Γ Δ : Γ p Δ A, [< Γ A >] [< Δ A >].
    Proof.
      intros B x; unfold imsell_sequent_tps.
      intros ? ; apply ; revert .
      apply imsell_tps_perm, Permutation_sym; auto.
    Qed.


    Fact imsell_sequent_tps_eq Γ A : [< Γ A >] Γ A.
    Proof.
      split.
      * intros H x Hx.
        rewrite vec_zero_plus, vec_plus_comm.
        apply (H x); trivial.
      * intros H x Hx.
        rewrite vec_plus_comm, vec_zero_plus; auto.
    Qed.


   Fact imsell_tps_lbang m Γ : m Γ Γ K m.
    Proof.
      induction Γ as [ | (v,A) Γ IH ]; simpl; intros x.
      + intros ; auto.
      + intros (y & z & & ( & ) & ).
        apply HK_plus; exists y, z; msplit 2; auto.
        * revert ; apply HK_antitone; auto.
          apply ( (v,A)); auto.
        * revert ; apply IH.
          intros (w,B) ?; apply ( (_,B)); auto.
    Qed.


    Theorem imsell_tps_sound Γ A : Γ A [< Γ A >] .
    Proof.
      induction 1 as [ A
                     | Γ Δ A
                     | Γ Δ A B C
                     | Γ A B
                     | Γ m A B
                     | Γ m A
                     | Γ u A B
                     | Γ u A B
                     ]; unfold imsell_sequent_tps in * |- *.

      + intros x; simpl; intros (y & z & & & ); subst; eq goal .
        f_equal; do 2 rewrite vec_plus_comm, vec_zero_plus; auto.

      + revert ; apply imsell_perm_tps; auto.

      + intros x (y & z & & & ); simpl.
        apply .
        apply imsell_tps_app in as (g & d & & & ).
        simpl in ; apply , in .
        exists (vec_plus y g), d; repeat split; auto.
        * subst; apply vec_plus_assoc.
        * eq goal ; f_equal; rew vec.

      + simpl; intros y Hy x Hx.
        rewrite vec_plus_assoc.
        apply .
        exists x, y; repeat split; auto.

      + intros x (y & z & & & ).
        apply ; exists y, z; repeat split; auto.
        apply .

      + intros x Hx; split.
        * apply ; auto.
        * rew vec.
          revert Hx; apply imsell_tps_lbang; auto.

      + intros x (y & z & & & ); rew vec.
        apply proj2, HK_unit1 in ; auto; subst.
        rewrite vec_plus_comm.
        now apply .

      + intros x (y & z & & & ).
        apply .
        exists y, z; repeat (split; auto).
        exists y, z; repeat (split; auto).
        apply proj2, HK_unit1 in ; auto.
        subst; rew vec; auto.
    Qed.


  End Trivial_Phase_semantics.

End IMSELL.