(* Deleting the last occurrence of a dart: *)

Fixpoint D(m:fmap)(x:dart){struct m}:fmap:=
  match m with
      V => V
    | I m0 x0 t0 p0 =>
         if eq_dart_dec x0 x then m0
         else (I (D m0 x) x0 t0 p0)
    | L m0 k0 x0 y0 => L (D m0 x) k0 x0 y0
 end.(* Test : OK
Eval compute in (D q0 3%nat).
*)

(* Breaking the last k-link starting from a dart: *)

Fixpoint B(m:fmap)(k:dim)(x:dart){struct m}:fmap:=
  match m with
      V => V
    | I m0 x0 t0 p0 => (I (B m0 k x) x0 t0 p0)
    | L m0 k0 x0 y0 =>
         if (eq_dim_dec k0 k)
         then if (eq_dart_dec x0 x) then m0
              else (L (B m0 k x) k0 x0 y0)
         else (L (B m0 k x) k0 x0 y0)
  end.(* Breaking the last k-link arriving on a dart: *)

Fixpoint B_1(m:fmap)(k:dim)(y:dart){struct m}:fmap:=
  match m with
      V => V
    | I m0 x0 t0 p0 =>(I (B_1 m0 k y) x0 t0 p0)
    | L m0 k0 x0 y0 =>
         if (eq_dim_dec k0 k)
         then if (eq_dart_dec y0 y) then m0
              else (L (B_1 m0 k y) k0 x0 y0)
         else (L (B_1 m0 k y) k0 x0 y0)
  end.(* Here, the correctness of D, B and B_1 has to be proved:
what they do is what they have to do. *)

(*=========================================================
                 CLOSURES OF A and A_1
 ========================================================*)
(* Closures of A and A_1, together designed for qhmaps,
mutually recursive: *)

Fixpoint cA(m:fmap)(k:dim)(z:dart){struct m}:dart:=
 match m with
     V => nil
  |  I m0 x _ _ =>
        if eq_dart_dec x z then z
	else cA m0 k z
  |  L m0 k0 x y  =>
      if (eq_dim_dec k0 k)
      then
         if (eq_dart_dec x z) then y
	 else
	   if (eq_dart_dec (cA_1 m0 k y) z)
	   then cA m0 k x
	   else cA m0 k z
      else cA m0 k z
 end
with cA_1(m:fmap)(k:dim)(z:dart){struct m}:dart:=
 match m with
     V => nil
  |  I m0 x _ _ =>
        if eq_dart_dec x z then z
	else cA_1 m0 k z
  |  L m0 k0 x y =>
      if (eq_dim_dec k0 k)
      then
         if (eq_dart_dec y z) then x
	 else
	   if (eq_dart_dec (cA m0 k x) z)
	   then cA_1 m0 k y
	   else cA_1 m0 k z
      else cA_1 m0 k z
 end.(* Notations ?
Notation "A~" := cA.

Notation "A_1~" := cA_1.

Notation "A~" := cA.

Notation "A_1~" := cA_1.
*)

(*==========================================================
              I- AND L-PRECONDITIONS, HMAPS
==========================================================*)

(* For a unique insertion of a non nil dart
in a (future) hmap: *)

Definition prec_I (m:fmap)(x:dart):=
  x <> nil /\ ~exd m x .(* For correctness of functional link insertion,
always incomplete, in a hmap: *)

Definition prec_L (m:fmap)(k:dim)(x y:dart) :=
  exd m x /\ exd m y /\ ~succ m k x /\ ~pred m k y
    /\ cA m k x <> y.Fixpoint inv_hmap(m:fmap):Prop:=
  match m with
      V => True
    | I m0 x _ _ => inv_hmap m0 /\ prec_I m0 x
    | L m0 k0 x y => inv_hmap m0 /\ prec_L m0 k0 x y
  end.(* Definition of the hmap type: (not used) *)

Definition hmap:Set := {m:fmap | inv_hmap m}.(* Projection of a hmap to its fmap support: *)

Definition hmap_to_fmap(q:hmap):fmap:=
  match q with exist m _=> m end.

(* Specifications: *)
Lemma not_exd_nil : forall m:fmap, inv_hmap m -> ~exd m nil.
Lemma exd_not_nil : forall (m:fmap)(z:dart), inv_hmap m -> exd m z -> z <> nil.
Lemma succ_exd : forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> succ m k z -> exd m z.
Lemma pred_exd : forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> pred m k z -> exd m z.
Lemma not_exd_A_nil: forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> ~exd m z -> A m k z = nil.
Lemma not_exd_A_1_nil: forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> ~exd m z -> A_1 m k z = nil.
Lemma A_nil: forall (m:fmap)(k:dim), inv_hmap m -> A m k nil = nil.
Lemma A_1_nil: forall (m:fmap)(k:dim), inv_hmap m -> A_1 m k nil = nil.
Lemma succ_exd_A : forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> succ m k z -> exd m (A m k z).
Lemma pred_exd_A_1 : forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> pred m k z -> exd m (A_1 m k z).
Lemma exd_A_exd : forall (m : fmap) (k : dim) (z : dart), inv_hmap m -> exd m (A m k z) -> exd m z.
Lemma exd_A_1_exd : forall (m : fmap) (k : dim) (z : dart), inv_hmap m -> exd m (A_1 m k z) -> exd m z.
Lemma A_1_A : forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> succ m k z -> A_1 m k (A m k z) = z.
Lemma A_A_1 : forall (m:fmap)(k:dim)(z:dart), inv_hmap m -> pred m k z -> A m k (A_1 m k z) = z.