Section GENERAL_CASE.
Context (_constant_symbols' : Set) (L' := mkL_with_constant_symbols _constant_symbols').
Hypothesis constant_symbols_similarity : Similarity _constant_symbols _constant_symbols'.
Inductive trm_similarity : Similarity (trm L) (trm L') :=
| Var_sim (x : ivar)
: @Var_trm L x =~= @Var_trm L' x
| Fun_sim (f : _function_symbols) (ts : trms L (L.(function_arity_table) f)) (ts' : trms L' (L'.(function_arity_table) f))
(ts_SIM : ts =~= ts')
: @Fun_trm L f ts =~= @Fun_trm L' f ts'
| Con_sim (c : _constant_symbols) (c' : _constant_symbols')
(c_SIM : c =~= c')
: @Con_trm L c =~= @Con_trm L' c'
with trms_similarity : forall n : arity, Similarity (trms L n) (trms L' n) :=
| O_trms_sim
: @O_trms L =~= @O_trms L'
| S_trms_sim (n : arity) (t : trm L) (t' : trm L') (ts : trms L n) (ts' : trms L' n)
(t_SIM : t =~= t')
(ts_SIM : ts =~= ts')
: @S_trms L n t ts =~= @S_trms L' n t' ts'.
#[local] Instance trm_similarity_instance : Similarity (trm L) (trm L') :=
trm_similarity.
#[local] Instance trms_similarity_instance (n : arity) : Similarity (trms L n) (trms L' n) :=
trms_similarity n.
Inductive frm_similarity : Similarity (frm L) (frm L') :=
| Rel_sim (R : _relation_symbols) (ts : trms L (L.(relation_arity_table) R)) (ts' : trms L' (L'.(relation_arity_table) R))
(ts_SIM : ts =~= ts')
: @Rel_frm L R ts =~= @Rel_frm L' R ts'
| Eqn_sim (t1 : trm L) (t1' : trm L') (t2 : trm L) (t2' : trm L')
(t1_SIM : t1 =~= t1')
(t2_SIM : t2 =~= t2')
: @Eqn_frm L t1 t2 =~= @Eqn_frm L' t1' t2'
| Neg_sim (p1 : frm L) (p1' : frm L')
(p1_SIM : p1 =~= p1')
: @Neg_frm L p1 =~= @Neg_frm L' p1'
| Imp_sim (p1 : frm L) (p1' : frm L') (p2 : frm L) (p2' : frm L')
(p1_SIM : p1 =~= p1')
(p2_SIM : p2 =~= p2')
: @Imp_frm L p1 p2 =~= @Imp_frm L' p1' p2'
| All_sim (y : ivar) (p1 : frm L) (p1' : frm L')
(p1_SIM : p1 =~= p1')
: @All_frm L y p1 =~= @All_frm L' y p1'.
#[local] Instance frm_similarity_instance : Similarity (frm L) (frm L') :=
frm_similarity.
Proof with eauto with *.
- induction t_SIM.
+ reflexivity.
+ change (fvs_trms ts = fvs_trms ts'). eapply fvs_trms_compat_similarity. exact ts_SIM.
+ reflexivity.
- induction ts_SIM.
+ reflexivity.
+ change (fvs_trm t ++ fvs_trms ts = fvs_trm t' ++ fvs_trms ts'). f_equal...
Qed.
Proof with try done!.
induction p_SIM; simpl...
- eapply fvs_trms_compat_similarity...
- f_equal; eapply fvs_trm_compat_similarity...
Qed.
Variant frms_similarity (Gamma : ensemble (frm L)) (Gamma' : ensemble (frm L')) : Prop :=
| frms_similarity_intro
(FWD : forall p : frm L, p \in Gamma -> exists p' : frm L', p =~= p' /\ p' \in Gamma')
(BWD : forall p' : frm L', p' \in Gamma' -> exists p : frm L, p =~= p' /\ p \in Gamma)
: frms_similarity Gamma Gamma'.
#[local]
Instance frms_similarity_instance : Similarity (ensemble (frm L)) (ensemble (frm L')) :=
frms_similarity.
#[local] Hint Resolve fvs_trm_similarity fvs_trms_similarity : core.
#[local] Hint Resolve fvs_frm_similarity : core.
Proof with eauto.
assert (ENOUGH : forall xs : list ivar, forall f : ivar -> list ivar, maxs (L.map (maxs ∘ f)%prg xs) = maxs (L.flat_map f xs)).
{ induction xs; simpl; i; eauto. unfold "∘"%prg. rewrite maxs_app. f_equal. eauto. }
unfold chi_frm. f_equal. unfold last_ivar_trm.
change (maxs (L.map (maxs ∘ (fvs_trm ∘ s))%prg (fvs_frm p)) = maxs (L.map (maxs ∘ (fvs_trm ∘ s'))%prg (fvs_frm p'))).
do 2 rewrite ENOUGH. eapply maxs_ext. intros z. do 2 rewrite in_flat_map. unfold "∘"%prg. clear ENOUGH.
split; intros [x [FREE FREE']]; exists x; split.
- erewrite <- fvs_frm_similarity...
- erewrite <- fvs_trm_similarity...
- erewrite -> fvs_frm_similarity...
- erewrite -> fvs_trm_similarity...
Qed.

Lemma subst_trm_similiarity (s : subst L) (s' : subst L') (t : trm L) (t' : trm L')
(s_SIM : s =~= s')
(t_SIM : t =~= t')
: subst_trm s t =~= subst_trm s' t'
with subst_trms_similiarity n (s : subst L) (s' : subst L') (ts : trms L n) (ts' : trms L' n)
(s_SIM : s =~= s')
(ts_SIM : ts =~= ts')
: subst_trms s ts =~= subst_trms s' ts'.