Require Import Arith Lia.
From Undecidability.Shared.Libs.DLW.Utils
Require Import utils_tac utils_nat gcd crt sums.
From Undecidability.Shared.Libs.DLW.Vec
Require Import pos vec.
From Undecidability.MuRec
Require Import recalg recomp beta ra_utils ra_recomp.
Set Implicit Arguments.
Set Default Proof Using "Type".
Local Notation "'⟦' f '⟧'" := (@ra_rel _ f) (at level 0).
Opaque ra_cst_n ra_iter_n ra_iter ra_prim_min ra_prim_max.
Opaque ra_plus ra_pred ra_minus ra_mult ra_exp ra_div ra_rem.
Opaque ra_ite ra_eq.
Opaque ra_div2 ra_mod2 ra_pow2 ra_notdiv_pow2.
Opaque ra_decomp_l ra_decomp_r ra_recomp.
Section ra_godel_beta.
Definition ra_godel_beta : recalg 3.
Proof.
ra root ra_rem.
+ ra arg pos0.
+ ra root ra_succ.
ra root ra_mult.
* ra root ra_succ.
ra arg pos2.
* ra arg pos1.
Defined.
Fact ra_godel_beta_prim_rec : prim_rec ra_godel_beta.
Proof. ra prim rec. Qed.
Fact ra_godel_beta_val a b n : ⟦ra_godel_beta⟧ (a##b##n##vec_nil) (godel_beta a b n).
Proof.
exists (a##S ((S n)*b)##vec_nil); split.
+ apply ra_rem_val; discriminate.
+ pos split; simpl; auto.
exists (((S n)*b)##vec_nil); split; simpl; auto.
pos split; simpl.
exists (S n##b##vec_nil); split.
* apply ra_mult_val.
* pos split; simpl; auto.
exists (n##vec_nil); split; simpl; auto.
pos split; simpl; auto.
Qed.
Fact ra_godel_beta_rel v e : ⟦ra_godel_beta⟧ v e <-> e = godel_beta (vec_pos v pos0) (vec_pos v pos1) (vec_pos v pos2).
Proof.
vec split v with a; vec split v with b; vec split v with n; vec nil v.
split.
+ intros H; apply ra_rel_fun with (1 := H), ra_godel_beta_val; auto.
+ intros; subst; apply ra_godel_beta_val; auto.
Qed.
End ra_godel_beta.
#[export] Hint Resolve ra_godel_beta_prim_rec ra_godel_beta_val : core.
Opaque ra_godel_beta.
Section ra_beta.
Definition ra_beta : recalg 2.
Proof.
ra root ra_godel_beta.
+ ra root ra_decomp_l.
ra arg pos0.
+ ra root ra_decomp_r.
ra arg pos0.
+ ra arg pos1.
Defined.
Fact ra_beta_prim_rec : prim_rec ra_beta.
Proof. ra prim rec. Qed.
Fact ra_beta_val a n : ⟦ra_beta⟧ (a##n##vec_nil) (beta a n).
Proof.
exists (decomp_l a##decomp_r a##n##vec_nil); split.
{ apply ra_godel_beta_val. }
pos split; simpl; auto;
exists (a##vec_nil); split; auto;
pos split; simpl; auto.
Qed.
Fact ra_beta_rel v e : ⟦ra_beta⟧ v e <-> e = beta (vec_pos v pos0) (vec_pos v pos1).
Proof.
vec split v with a; vec split v with n; vec nil v.
split.
+ intros H; apply ra_rel_fun with (1 := H), ra_beta_val; auto.
+ intros; subst; apply ra_beta_val; auto.
Qed.
End ra_beta.
#[export] Hint Resolve ra_beta_prim_rec ra_beta_val : core.