internlm/Lean-Github huggingface dataset:
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
phi psi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
psi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi
⊢ Holds D I V (head✝ :: tail✝) (sub τ (phi.iff_ psi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (phi.iff_ psi)
Tactic:
simp only [sub]
Proof state after:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
phi psi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
psi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi
⊢ Holds D I V (head✝ :: tail✝) ((sub τ phi).iff_ (sub τ psi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (phi.iff_ psi)
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
phi psi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
psi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi
⊢ Holds D I V (head✝ :: tail✝) ((sub τ phi).iff_ (sub τ psi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (phi.iff_ psi)
Tactic:
simp only [Holds]
Proof state after:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
phi psi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
psi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi
⊢ (Holds D I V (head✝ :: tail✝) (sub τ phi) ↔ Holds D I V (head✝ :: tail✝) (sub τ psi)) ↔
    (Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi)
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
case a.h.e'_1.a
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
phi psi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
psi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi
⊢ Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) phi
Tactic:
apply phi_ih
Proof state after:
no goals
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
case a.h.e'_2.a
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
phi psi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
psi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) psi
⊢ Holds D I V (head✝ :: tail✝) (sub τ psi) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) psi
Tactic:
apply psi_ih
Proof state after:
no goals
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds =>
            if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
V : VarAssignment D
⊢ Holds D I V (head✝ :: tail✝) (sub τ (exists_ x phi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (exists_ x phi)
Tactic:
simp only [Holds] at phi_ih
Proof state after:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ Holds D I V (head✝ :: tail✝) (sub τ (exists_ x phi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (exists_ x phi)
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ Holds D I V (head✝ :: tail✝) (sub τ (exists_ x phi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (exists_ x phi)
Tactic:
simp only [sub]
Proof state after:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ Holds D I V (head✝ :: tail✝) (exists_ x (sub τ phi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (exists_ x phi)
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ Holds D I V (head✝ :: tail✝) (exists_ x (sub τ phi)) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds =>
          if ds = [] then Holds D I V (head✝ :: tail✝) (pred_var_ (τ P) []) else I.pred_var_ P ds }
      V (head✝ :: tail✝) (exists_ x phi)
Tactic:
simp only [Holds]
Proof state after:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ (∃ d, Holds D I (Function.updateITE V x d) (head✝ :: tail✝) (sub τ phi)) ↔
    ∃ d,
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        (Function.updateITE V x d) (head✝ :: tail✝) phi
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ (∃ d, Holds D I (Function.updateITE V x d) (head✝ :: tail✝) (sub τ phi)) ↔
    ∃ d,
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        (Function.updateITE V x d) (head✝ :: tail✝) phi
Tactic:
first | apply forall_congr' | apply exists_congr
Proof state after:
case h
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ ∀ (a : D),
    Holds D I (Function.updateITE V x a) (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        (Function.updateITE V x a) (head✝ :: tail✝) phi
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
case h
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ ∀ (a : D),
    Holds D I (Function.updateITE V x a) (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        (Function.updateITE V x a) (head✝ :: tail✝) phi
Tactic:
intros d
Proof state after:
case h
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
d : D
⊢ Holds D I (Function.updateITE V x d) (head✝ :: tail✝) (sub τ phi) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
      (Function.updateITE V x d) (head✝ :: tail✝) phi
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
case h
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
d : D
⊢ Holds D I (Function.updateITE V x d) (head✝ :: tail✝) (sub τ phi) ↔
    Holds D
      { nonempty := ⋯, pred_const_ := I.pred_const_,
        pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
      (Function.updateITE V x d) (head✝ :: tail✝) phi
Tactic:
apply phi_ih
Proof state after:
no goals
Theorem: FOL.NV.Sub.Prop.All.Rec.substitution_theorem
Proof state before:
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ (∀ (d : D), Holds D I (Function.updateITE V x d) (head✝ :: tail✝) (sub τ phi)) ↔
    ∀ (d : D),
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        (Function.updateITE V x d) (head✝ :: tail✝) phi
Tactic:
apply forall_congr'
Proof state after:
case h
D : Type
I : Interpretation D
τ : PredName → PredName
head✝ : Definition
tail✝ : List Definition
tail_ih✝ :
  ∀ (V : VarAssignment D) (F : Formula),
    Holds D I V tail✝ (sub τ F) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then Holds D I V tail✝ (pred_var_ (τ P) []) else I.pred_var_ P ds }
        V tail✝ F
x : VarName
phi : Formula
V : VarAssignment D
phi_ih :
  ∀ (V : VarAssignment D),
    Holds D I V (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        V (head✝ :: tail✝) phi
⊢ ∀ (a : D),
    Holds D I (Function.updateITE V x a) (head✝ :: tail✝) (sub τ phi) ↔
      Holds D
        { nonempty := ⋯, pred_const_ := I.pred_const_,
          pred_var_ := fun P ds => if ds = [] then I.pred_var_ (τ P) (List.map V []) else I.pred_var_ P ds }
        (Function.updateITE V x a) (head✝ :: tail✝) phi