/-- **Isomorphisms preserve truth**: `M ⊨ φ[ρ]` if and only if `N ⊨ φ[e ∘ ρ]`, for every
formula. Induction on `φ`: equations use that `e` is injective, atomic formulas use `map_rel`,
and the quantifier cases use that `e` is surjective (every element of `N` is `e(a)`). -/
theorem Iso.realize (e : Iso S T) (φ : Formula L) :
∀ ρ : ℕ → M, φ.Realize S ρ ↔ φ.Realize T (fun i => e.toEquiv (ρ i)) := by
have hcons : ∀ (a : M) (ρ : ℕ → M),
(fun i => e.toEquiv (cons a ρ i)) = cons (e.toEquiv a) (fun i => e.toEquiv (ρ i)) := by
intro a ρ
funext i
cases i <;> rfl
induction φ with
| falsum => intro ρ; exact Iff.rfl
| eq t u =>
intro ρ
simp only [Formula.Realize, ← e.eval, e.toEquiv.apply_eq_iff_eq]
| rel R ts =>
intro ρ
simp only [Formula.Realize, ← e.eval]
exact e.map_rel R _
| imp φ ψ ihφ ihψ => intro ρ; simp only [Formula.Realize, ihφ, ihψ]
| and φ ψ ihφ ihψ => intro ρ; simp only [Formula.Realize, ihφ, ihψ]
| or φ ψ ihφ ihψ => intro ρ; simp only [Formula.Realize, ihφ, ihψ]
| all φ ih =>
intro ρ
simp only [Formula.Realize]
constructor
· intro h b
have hb := (ih (cons (e.toEquiv.symm b) ρ)).1 (h _)
rw [hcons, Equiv.apply_symm_apply] at hb
exact hb
· intro h a
rw [ih, hcons]
exact h _
| ex φ ih =>
intro ρ
simp only [Formula.Realize]
constructor
· rintro ⟨a, ha⟩
refine ⟨e.toEquiv a, ?_⟩
rw [← hcons, ← ih]
exact ha
· rintro ⟨b, hb⟩
refine ⟨e.toEquiv.symm b, ?_⟩
rw [ih, hcons, Equiv.apply_symm_apply]
exact hb