Section fo_model_simulation.
(* We state a general simulation result for models on a given formula build on a bounded list of symbols. The statement is so general that the proof is just obvious ;-) *)
Variables  (Σ : fo_signature) (ls : list (syms Σ)) (lr : list (rels Σ))
(X : Type) (M : fo_model Σ X)
(Y : Type) (N : fo_model Σ Y).
(* We assume that ⋈ is a simulation, ie a congruence for all operators in ls and all relations in lr *)
Record fo_simulation := Mk_fo_simulation {
fos_simul :> X -> Y -> Prop;
fos_syms  : forall s v w, In s ls
-> (forall p, fos_simul (vec_pos v p) (vec_pos w p))
-> fos_simul (fom_syms M s v) (fom_syms N s w);
fos_rels  : forall s v w, In s lr
-> (forall p, fos_simul (vec_pos v p) (vec_pos w p))
-> fom_rels M s v <-> fom_rels N s w;
fos_total : forall x, exists y, fos_simul x y;
fos_surj  : forall y, exists x, fos_simul x y;
}.
Record fo_projection := Mk_fo_projection {
fop_surj :> X -> Y;
fop_inj  : Y -> X;
fop_eq   : forall x, fop_surj (fop_inj x) = x;
fop_syms : forall s v, In s ls -> fop_surj (fom_syms M s v) = fom_syms N s (vec_map fop_surj v);
fop_rels : forall s v, In s lr -> fom_rels M s v <-> fom_rels N s (vec_map fop_surj v);
}.
Fact fo_proj_simul : fo_projection -> fo_simulation.
(* We assume the simulation to be total and surjective *)

Theorem fo_model_simulation A φ ψ :
incl (fol_syms A) ls
-> incl (fol_rels A) lr
-> (forall n : nat, In n (fol_vars A) -> φ n ⋈ ψ n)
-> ⟪A⟫ φ <-> ⟪A⟫' ψ.