Section MU_RECURSIVE.
#[local] Close Scope list_scope.
#[local] Open Scope vector_scope.
#[local] Notation " [ ] " := (VNil).
#[local] Notation " x :: xs " := (VCons _ x xs).
#[local] Notation " [ x ] " := (VCons _ x VNil).
Let Arity : Set := nat.
Inductive MuRec : Arity -> Set :=
| MR_succ : MuRec 1
| MR_zero : MuRec 0
| MR_proj {n : Arity} (i : Fin.t n) : MuRec n
| MR_compose {n : Arity} {m : Arity} (g : MuRecs n m) (h : MuRec m) : MuRec n
| MR_primRec {n : Arity} (g : MuRec n) (h : MuRec (S (S n))) : MuRec (S n)
| MR_mu {n : Arity} (g : MuRec (S n)) : MuRec n
with MuRecs : Arity -> Arity -> Set :=
| MRs_nil {n : Arity} : MuRecs n 0
| MRs_cons {n : Arity} {m : Arity} (f : MuRec n) (fs : MuRecs n m) : MuRecs n (S m).
Let Value := nat.
Inductive MuRecSpec : forall n : Arity, MuRec n -> Vector.t Value n -> Value -> Prop :=
| MR_succ_spec x
: MuRecSpec 1 (MR_succ) [x] (S x)
| MR_zero_spec
: MuRecSpec 0 (MR_zero) [] (O)
| MR_proj_spec n xs i
: MuRecSpec n (MR_proj i) xs (xs !! i)
| MR_compose_spec n m g h xs ys z
(g_spec : MuRecsSpec n m g xs ys)
(h_spec : MuRecSpec m h ys z)
: MuRecSpec n (MR_compose g h) xs z
| MR_primRec_spec_O n g h xs z
(g_spec : MuRecSpec n g xs z)
: MuRecSpec (S n) (MR_primRec g h) (O :: xs) z
| MR_primRec_spec_S n g h xs z a acc
(ACC : MuRecSpec (S n) (MR_primRec g h) (a :: xs) acc)
(h_spec : MuRecSpec (S (S n)) h (a :: acc :: xs) z)
: MuRecSpec (S n) (MR_primRec g h) (S a :: xs) z
| MR_mu_spec n g xs z
(g_spec : MuRecSpec (S n) g (z :: xs) 0)
(MIN : forall y, y < z -> exists p, p > 0 /\ MuRecSpec (S n) g (y :: xs) p)
: MuRecSpec n (MR_mu g) xs z
with MuRecsSpec : forall n : Arity, forall m : Arity, MuRecs n m -> Vector.t Value n -> Vector.t Value m -> Prop :=
| MRs_nil_spec n xs
: MuRecsSpec n (O) (MRs_nil) xs []
| MRs_cons_spec n m xs y ys f fs
(f_spec : MuRecSpec n f xs y)
(fs_spec : MuRecsSpec n m fs xs ys)
: MuRecsSpec n (S m) (MRs_cons f fs) xs (y :: ys).
Fixpoint MuRecGraph {n : Arity} (f : MuRec n) : Vector.t Value n -> Value -> Prop :=
match f with
| MR_succ => fun xs => fun z => S (V.head xs) = z
| MR_zero => fun xs => fun z => O = z
| MR_proj i => fun xs => fun z => xs !! i = z
| MR_compose g h => fun xs => fun z => exists ys, MuRecsGraph g xs ys /\ MuRecGraph h ys z
| MR_primRec g h => fun xs => nat_rect _ (fun z => MuRecGraph g (V.tail xs) z) (fun a => fun ACC => fun z => exists y, ACC y /\ MuRecGraph h (a :: y :: V.tail xs) z) (V.head xs)
| MR_mu g => fun xs => fun z => (forall y, y < z -> exists p, p > 0 /\ MuRecGraph g (y :: xs) p) /\ MuRecGraph g (z :: xs) 0
end
with MuRecsGraph {n : Arity} {m : Arity} (fs : MuRecs n m) : Vector.t Value n -> Vector.t Value m -> Prop :=
match fs with
| MRs_nil => fun xs => fun z => [] = z
| MRs_cons f fs => fun xs => fun z => exists y, exists ys, MuRecGraph f xs y /\ MuRecsGraph fs xs ys /\ y :: ys = z
end.
Fixpoint MuRecGraph_sound (n : Arity) (f : MuRec n) {struct f}
: forall xs, forall z, MuRecGraph f xs z -> MuRecSpec n f xs z
with MuRecsGraph_sound (n : Arity) (m : Arity) (fs : MuRecs n m) {struct fs}
: forall xs, forall z, MuRecsGraph fs xs z -> MuRecsSpec n m fs xs z.
Fixpoint MuRecGraph_complete (n : Arity) (f : MuRec n) (xs : Vector.t Value n) (z : Value) (SPEC : MuRecSpec n f xs z) {struct SPEC}
: MuRecGraph f xs z
with MuRecsGraph_complete (n : Arity) (m : Arity) (fs : MuRecs n m) (xs : Vector.t Value n) (z : Vector.t Value m) (SPEC : MuRecsSpec n m fs xs z) {struct SPEC}
: MuRecsGraph fs xs z.

Theorem MuRecGraph_correct (n : Arity) (f : MuRec n) (xs : Vector.t Value n) (z : Value)
: MuRecGraph f xs z <-> MuRecSpec n f xs z.