l3lab/ntp-mathlib huggingface dataset:
/-- The directed limit glues together the structures along the embeddings. -/
def setoid [DirectedSystem G fun i j h => f i j h] [IsDirected ι (· ≤ ·)] : Setoid (Σˣ f) where
  r := fun ⟨i, x⟩ ⟨j, y⟩ => ∃ (k : ι) (ik : i ≤ k) (jk : j ≤ k), f i k ik x = f j k jk y
  iseqv :=
    ⟨fun ⟨i, x⟩ => ⟨i, refl i, refl i, rfl⟩, @fun ⟨i, x⟩ ⟨j, y⟩ ⟨k, ik, jk, h⟩ =>
      ⟨k, jk, ik, h.symm⟩,
      @fun ⟨i, x⟩ ⟨j, y⟩ ⟨k, z⟩ ⟨ij, hiij, hjij, hij⟩ ⟨jk, hjjk, hkjk, hjk⟩ => by
        obtain ⟨ijk, hijijk, hjkijk⟩ := directed_of (· ≤ ·) ij jk
        refine' ⟨ijk, le_trans hiij hijijk, le_trans hkjk hjkijk, _⟩
        rw [← DirectedSystem.map_map, hij, DirectedSystem.map_map]
        symm
        

Proof state:
case intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝ : IsDirected ι fun x x_1 => x ≤ x_1
x✝⁴ x✝³ x✝² : Σˣ f
i : ι
x : (fun i => G i) i
j : ι
y : (fun i => G i) j
x✝¹ :
  match { fst := i, snd := x } with
  | { fst := i, snd := x } =>
    match { fst := j, snd := y } with
    | { fst := j, snd := y } => ∃ k, ∃ (ik : i ≤ k) (jk : j ≤ k), (f i k ik) x = (f j k jk) y
k : ι
z : (fun i => G i) k
x✝ :
  match { fst := j, snd := y } with
  | { fst := i, snd := x } =>
    match { fst := k, snd := z } with
    | { fst := j, snd := y } => ∃ k, ∃ (ik : i ≤ k) (jk : j ≤ k), (f i k ik) x = (f j k jk) y
ij : ι
hiij : i ≤ ij
hjij : j ≤ ij
hij : (f i ij hiij) x = (f j ij hjij) y
jk : ι
hjjk : j ≤ jk
hkjk : k ≤ jk
hjk : (f j jk hjjk) y = (f k jk hkjk) z
ijk : ι
hijijk : ij ≤ ijk
hjkijk : jk ≤ ijk
⊢ (f k ijk (_ : k ≤ ijk)) z = (f j ijk (_ : j ≤ ijk)) y

Next tactic:
rw [← DirectedSystem.map_map, ← hjk, DirectedSystem.map_map]
/-- The directed limit glues together the structures along the embeddings. -/
def setoid [DirectedSystem G fun i j h => f i j h] [IsDirected ι (· ≤ ·)] : Setoid (Σˣ f) where
  r := fun ⟨i, x⟩ ⟨j, y⟩ => ∃ (k : ι) (ik : i ≤ k) (jk : j ≤ k), f i k ik x = f j k jk y
  iseqv :=
    ⟨fun ⟨i, x⟩ => ⟨i, refl i, refl i, rfl⟩, @fun ⟨i, x⟩ ⟨j, y⟩ ⟨k, ik, jk, h⟩ =>
      ⟨k, jk, ik, h.symm⟩,
      @fun ⟨i, x⟩ ⟨j, y⟩ ⟨k, z⟩ ⟨ij, hiij, hjij, hij⟩ ⟨jk, hjjk, hkjk, hjk⟩ => by
        obtain ⟨ijk, hijijk, hjkijk⟩ := directed_of (· ≤ ·) ij jk
        refine' ⟨ijk, le_trans hiij hijijk, le_trans hkjk hjkijk, _⟩
        rw [← DirectedSystem.map_map, hij, DirectedSystem.map_map]
        symm
        rw [← DirectedSystem.map_map, ← hjk, DirectedSystem.map_map] <;> 

Proof state:
case intro.intro.hjk
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝ : IsDirected ι fun x x_1 => x ≤ x_1
x✝⁴ x✝³ x✝² : Σˣ f
i : ι
x : (fun i => G i) i
j : ι
y : (fun i => G i) j
x✝¹ :
  match { fst := i, snd := x } with
  | { fst := i, snd := x } =>
    match { fst := j, snd := y } with
    | { fst := j, snd := y } => ∃ k, ∃ (ik : i ≤ k) (jk : j ≤ k), (f i k ik) x = (f j k jk) y
k : ι
z : (fun i => G i) k
x✝ :
  match { fst := j, snd := y } with
  | { fst := i, snd := x } =>
    match { fst := k, snd := z } with
    | { fst := j, snd := y } => ∃ k, ∃ (ik : i ≤ k) (jk : j ≤ k), (f i k ik) x = (f j k jk) y
ij : ι
hiij : i ≤ ij
hjij : j ≤ ij
hij : (f i ij hiij) x = (f j ij hjij) y
jk : ι
hjjk : j ≤ jk
hkjk : k ≤ jk
hjk : (f j jk hjjk) y = (f k jk hkjk) z
ijk : ι
hijijk : ij ≤ ijk
hjkijk : jk ≤ ijk
⊢ jk ≤ ijk

Next tactic:
assumption
/-- The directed limit glues together the structures along the embeddings. -/
def setoid [DirectedSystem G fun i j h => f i j h] [IsDirected ι (· ≤ ·)] : Setoid (Σˣ f) where
  r := fun ⟨i, x⟩ ⟨j, y⟩ => ∃ (k : ι) (ik : i ≤ k) (jk : j ≤ k), f i k ik x = f j k jk y
  iseqv :=
    ⟨fun ⟨i, x⟩ => ⟨i, refl i, refl i, rfl⟩, @fun ⟨i, x⟩ ⟨j, y⟩ ⟨k, ik, jk, h⟩ =>
      ⟨k, jk, ik, h.symm⟩,
      @fun ⟨i, x⟩ ⟨j, y⟩ ⟨k, z⟩ ⟨ij, hiij, hjij, hij⟩ ⟨jk, hjjk, hkjk, hjk⟩ => by
        obtain ⟨ijk, hijijk, hjkijk⟩ := directed_of (· ≤ ·) ij jk
        refine' ⟨ijk, le_trans hiij hijijk, le_trans hkjk hjkijk, _⟩
        rw [← DirectedSystem.map_map, hij, DirectedSystem.map_map]
        symm
        rw [← DirectedSystem.map_map, ← hjk, DirectedSystem.map_map] <;> 

Proof state:
case intro.intro.hjk
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝ : IsDirected ι fun x x_1 => x ≤ x_1
x✝⁴ x✝³ x✝² : Σˣ f
i : ι
x : (fun i => G i) i
j : ι
y : (fun i => G i) j
x✝¹ :
  match { fst := i, snd := x } with
  | { fst := i, snd := x } =>
    match { fst := j, snd := y } with
    | { fst := j, snd := y } => ∃ k, ∃ (ik : i ≤ k) (jk : j ≤ k), (f i k ik) x = (f j k jk) y
k : ι
z : (fun i => G i) k
x✝ :
  match { fst := j, snd := y } with
  | { fst := i, snd := x } =>
    match { fst := k, snd := z } with
    | { fst := j, snd := y } => ∃ k, ∃ (ik : i ≤ k) (jk : j ≤ k), (f i k ik) x = (f j k jk) y
ij : ι
hiij : i ≤ ij
hjij : j ≤ ij
hij : (f i ij hiij) x = (f j ij hjij) y
jk : ι
hjjk : j ≤ jk
hkjk : k ≤ jk
hjk : (f j jk hjjk) y = (f k jk hkjk) z
ijk : ι
hijijk : ij ≤ ijk
hjkijk : jk ≤ ijk
⊢ ij ≤ ijk

Next tactic:
assumption
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  

Proof state:
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
x y : Σˣ f
i : ι
hx : x.fst ≤ i
hy : y.fst ≤ i
⊢ x ≈ y ↔ (f x.fst i hx) x.snd = (f y.fst i hy) y.snd

Next tactic:
cases x
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  

Proof state:
case mk
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
y : Σˣ f
i : ι
hy : y.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hx : { fst := fst✝, snd := snd✝ }.fst ≤ i
⊢ { fst := fst✝, snd := snd✝ } ≈ y ↔
    (f { fst := fst✝, snd := snd✝ }.fst i hx) { fst := fst✝, snd := snd✝ }.snd = (f y.fst i hy) y.snd

Next tactic:
cases y
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  

Proof state:
case mk.mk
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
⊢ { fst := fst✝¹, snd := snd✝¹ } ≈ { fst := fst✝, snd := snd✝ } ↔
    (f { fst := fst✝¹, snd := snd✝¹ }.fst i hx) { fst := fst✝¹, snd := snd✝¹ }.snd =
      (f { fst := fst✝, snd := snd✝ }.fst i hy) { fst := fst✝, snd := snd✝ }.snd

Next tactic:
refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
  

Proof state:
case mk.mk
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
xy : { fst := fst✝¹, snd := snd✝¹ } ≈ { fst := fst✝, snd := snd✝ }
⊢ (f { fst := fst✝¹, snd := snd✝¹ }.fst i hx) { fst := fst✝¹, snd := snd✝¹ }.snd =
    (f { fst := fst✝, snd := snd✝ }.fst i hy) { fst := fst✝, snd := snd✝ }.snd

Next tactic:
obtain ⟨j, _, _, h⟩ := xy
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
  obtain ⟨j, _, _, h⟩ := xy
  

Proof state:
case mk.mk.intro.intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
j : ι
w✝¹ : fst✝¹ ≤ j
w✝ : fst✝ ≤ j
h : (f fst✝¹ j w✝¹) snd✝¹ = (f fst✝ j w✝) snd✝
⊢ (f { fst := fst✝¹, snd := snd✝¹ }.fst i hx) { fst := fst✝¹, snd := snd✝¹ }.snd =
    (f { fst := fst✝, snd := snd✝ }.fst i hy) { fst := fst✝, snd := snd✝ }.snd

Next tactic:
obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
  obtain ⟨j, _, _, h⟩ := xy
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  

Proof state:
case mk.mk.intro.intro.intro.intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
j : ι
w✝¹ : fst✝¹ ≤ j
w✝ : fst✝ ≤ j
h : (f fst✝¹ j w✝¹) snd✝¹ = (f fst✝ j w✝) snd✝
k : ι
ik : i ≤ k
jk : j ≤ k
⊢ (f { fst := fst✝¹, snd := snd✝¹ }.fst i hx) { fst := fst✝¹, snd := snd✝¹ }.snd =
    (f { fst := fst✝, snd := snd✝ }.fst i hy) { fst := fst✝, snd := snd✝ }.snd

Next tactic:
have h := congr_arg (f j k jk) h
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
  obtain ⟨j, _, _, h⟩ := xy
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  have h := congr_arg (f j k jk) h
  

Proof state:
case mk.mk.intro.intro.intro.intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
j : ι
w✝¹ : fst✝¹ ≤ j
w✝ : fst✝ ≤ j
h✝ : (f fst✝¹ j w✝¹) snd✝¹ = (f fst✝ j w✝) snd✝
k : ι
ik : i ≤ k
jk : j ≤ k
h : (f j k jk) ((f fst✝¹ j w✝¹) snd✝¹) = (f j k jk) ((f fst✝ j w✝) snd✝)
⊢ (f { fst := fst✝¹, snd := snd✝¹ }.fst i hx) { fst := fst✝¹, snd := snd✝¹ }.snd =
    (f { fst := fst✝, snd := snd✝ }.fst i hy) { fst := fst✝, snd := snd✝ }.snd

Next tactic:
apply (f i k ik).injective
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
  obtain ⟨j, _, _, h⟩ := xy
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  have h := congr_arg (f j k jk) h
  apply (f i k ik).injective
  

Proof state:
case mk.mk.intro.intro.intro.intro.intro.a
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
j : ι
w✝¹ : fst✝¹ ≤ j
w✝ : fst✝ ≤ j
h✝ : (f fst✝¹ j w✝¹) snd✝¹ = (f fst✝ j w✝) snd✝
k : ι
ik : i ≤ k
jk : j ≤ k
h : (f j k jk) ((f fst✝¹ j w✝¹) snd✝¹) = (f j k jk) ((f fst✝ j w✝) snd✝)
⊢ (f i k ik) ((f { fst := fst✝¹, snd := snd✝¹ }.fst i hx) { fst := fst✝¹, snd := snd✝¹ }.snd) =
    (f i k ik) ((f { fst := fst✝, snd := snd✝ }.fst i hy) { fst := fst✝, snd := snd✝ }.snd)

Next tactic:
rw [DirectedSystem.map_map, DirectedSystem.map_map] at *
theorem equiv_iff {x y : Σˣ f} {i : ι} (hx : x.1 ≤ i) (hy : y.1 ≤ i) :
    x ≈ y ↔ (f x.1 i hx) x.2 = (f y.1 i hy) y.2 := by
  cases x
  cases y
  refine' ⟨fun xy => _, fun xy => ⟨i, hx, hy, xy⟩⟩
  obtain ⟨j, _, _, h⟩ := xy
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  have h := congr_arg (f j k jk) h
  apply (f i k ik).injective
  rw [DirectedSystem.map_map, DirectedSystem.map_map] at *
  

Proof state:
case mk.mk.intro.intro.intro.intro.intro.a
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
i fst✝¹ : ι
snd✝¹ : (fun i => G i) fst✝¹
hx : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ i
fst✝ : ι
snd✝ : (fun i => G i) fst✝
hy : { fst := fst✝, snd := snd✝ }.fst ≤ i
j : ι
w✝¹ : fst✝¹ ≤ j
w✝ : fst✝ ≤ j
h✝ : (f fst✝¹ j w✝¹) snd✝¹ = (f fst✝ j w✝) snd✝
k : ι
ik : i ≤ k
jk : j ≤ k
h : (f fst✝¹ k (_ : fst✝¹ ≤ k)) snd✝¹ = (f fst✝ k (_ : fst✝ ≤ k)) snd✝
⊢ (f { fst := fst✝¹, snd := snd✝¹ }.fst k (_ : { fst := fst✝¹, snd := snd✝¹ }.fst ≤ k))
      { fst := fst✝¹, snd := snd✝¹ }.snd =
    (f { fst := fst✝, snd := snd✝ }.fst k (_ : { fst := fst✝, snd := snd✝ }.fst ≤ k)) { fst := fst✝, snd := snd✝ }.snd

Next tactic:
exact h
theorem funMap_unify_equiv {n : ℕ} (F : L.Functions n) (x : Fin n → Σˣ f) (i j : ι)
    (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hj : j ∈ upperBounds (range (Sigma.fst ∘ x))) :
    Structure.Sigma.mk f i (funMap F (unify f x i hi)) ≈ .mk f j (funMap F (unify f x j hj)) := by
  

Proof state:
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
n : ℕ
F : Functions L n
x : Fin n → Σˣ f
i j : ι
hi : i ∈ upperBounds (range (Sigma.fst ∘ x))
hj : j ∈ upperBounds (range (Sigma.fst ∘ x))
⊢ Structure.Sigma.mk f i (funMap F (unify f x i hi)) ≈ Structure.Sigma.mk f j (funMap F (unify f x j hj))

Next tactic:
obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
theorem funMap_unify_equiv {n : ℕ} (F : L.Functions n) (x : Fin n → Σˣ f) (i j : ι)
    (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hj : j ∈ upperBounds (range (Sigma.fst ∘ x))) :
    Structure.Sigma.mk f i (funMap F (unify f x i hi)) ≈ .mk f j (funMap F (unify f x j hj)) := by
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  

Proof state:
case intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
n : ℕ
F : Functions L n
x : Fin n → Σˣ f
i j : ι
hi : i ∈ upperBounds (range (Sigma.fst ∘ x))
hj : j ∈ upperBounds (range (Sigma.fst ∘ x))
k : ι
ik : i ≤ k
jk : j ≤ k
⊢ Structure.Sigma.mk f i (funMap F (unify f x i hi)) ≈ Structure.Sigma.mk f j (funMap F (unify f x j hj))

Next tactic:
refine' ⟨k, ik, jk, _⟩
theorem funMap_unify_equiv {n : ℕ} (F : L.Functions n) (x : Fin n → Σˣ f) (i j : ι)
    (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hj : j ∈ upperBounds (range (Sigma.fst ∘ x))) :
    Structure.Sigma.mk f i (funMap F (unify f x i hi)) ≈ .mk f j (funMap F (unify f x j hj)) := by
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  refine' ⟨k, ik, jk, _⟩
  

Proof state:
case intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
n : ℕ
F : Functions L n
x : Fin n → Σˣ f
i j : ι
hi : i ∈ upperBounds (range (Sigma.fst ∘ x))
hj : j ∈ upperBounds (range (Sigma.fst ∘ x))
k : ι
ik : i ≤ k
jk : j ≤ k
⊢ (f i k ik) (funMap F (unify f x i hi)) = (f j k jk) (funMap F (unify f x j hj))

Next tactic:
rw [(f i k ik).map_fun, (f j k jk).map_fun, comp_unify, comp_unify]
theorem relMap_unify_equiv {n : ℕ} (R : L.Relations n) (x : Fin n → Σˣ f) (i j : ι)
    (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hj : j ∈ upperBounds (range (Sigma.fst ∘ x))) :
    RelMap R (unify f x i hi) = RelMap R (unify f x j hj) := by
  

Proof state:
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
n : ℕ
R : Relations L n
x : Fin n → Σˣ f
i j : ι
hi : i ∈ upperBounds (range (Sigma.fst ∘ x))
hj : j ∈ upperBounds (range (Sigma.fst ∘ x))
⊢ RelMap R (unify f x i hi) = RelMap R (unify f x j hj)

Next tactic:
obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
theorem relMap_unify_equiv {n : ℕ} (R : L.Relations n) (x : Fin n → Σˣ f) (i j : ι)
    (hi : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hj : j ∈ upperBounds (range (Sigma.fst ∘ x))) :
    RelMap R (unify f x i hi) = RelMap R (unify f x j hj) := by
  obtain ⟨k, ik, jk⟩ := directed_of (· ≤ ·) i j
  

Proof state:
case intro.intro
L : Language
ι : Type v
inst✝³ : Preorder ι
G : ι → Type w
inst✝² : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝¹ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝ : DirectedSystem G fun i j h => ⇑(f i j h)
n : ℕ
R : Relations L n
x : Fin n → Σˣ f
i j : ι
hi : i ∈ upperBounds (range (Sigma.fst ∘ x))
hj : j ∈ upperBounds (range (Sigma.fst ∘ x))
k : ι
ik : i ≤ k
jk : j ≤ k
⊢ RelMap R (unify f x i hi) = RelMap R (unify f x j hj)

Next tactic:
rw [← (f i k ik).map_rel, comp_unify, ← (f j k jk).map_rel, comp_unify]
theorem exists_unify_eq {α : Type*} [Fintype α] {x y : α → Σˣ f} (xy : x ≈ y) :
    ∃ (i : ι)(hx : i ∈ upperBounds (range (Sigma.fst ∘ x)))(hy :
      i ∈ upperBounds (range (Sigma.fst ∘ y))), unify f x i hx = unify f y i hy := by
  

Proof state:
L : Language
ι : Type v
inst✝⁵ : Preorder ι
G : ι → Type w
inst✝⁴ : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝³ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝² : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝¹ : Nonempty ι
α : Type u_1
inst✝ : Fintype α
x y : α → Σˣ f
xy : x ≈ y
⊢ ∃ i,
    ∃ (hx : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hy : i ∈ upperBounds (range (Sigma.fst ∘ y))),
      unify f x i hx = unify f y i hy

Next tactic:
obtain ⟨i, hi⟩ := Fintype.bddAbove_range (Sum.elim (fun a => (x a).1) fun a => (y a).1)
theorem exists_unify_eq {α : Type*} [Fintype α] {x y : α → Σˣ f} (xy : x ≈ y) :
    ∃ (i : ι)(hx : i ∈ upperBounds (range (Sigma.fst ∘ x)))(hy :
      i ∈ upperBounds (range (Sigma.fst ∘ y))), unify f x i hx = unify f y i hy := by
  obtain ⟨i, hi⟩ := Fintype.bddAbove_range (Sum.elim (fun a => (x a).1) fun a => (y a).1)
  

Proof state:
case intro
L : Language
ι : Type v
inst✝⁵ : Preorder ι
G : ι → Type w
inst✝⁴ : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝³ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝² : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝¹ : Nonempty ι
α : Type u_1
inst✝ : Fintype α
x y : α → Σˣ f
xy : x ≈ y
i : ι
hi : i ∈ upperBounds (range (Sum.elim (fun a => (x a).fst) fun a => (y a).fst))
⊢ ∃ i,
    ∃ (hx : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hy : i ∈ upperBounds (range (Sigma.fst ∘ y))),
      unify f x i hx = unify f y i hy

Next tactic:
rw [Sum.elim_range, upperBounds_union] at hi
theorem exists_unify_eq {α : Type*} [Fintype α] {x y : α → Σˣ f} (xy : x ≈ y) :
    ∃ (i : ι)(hx : i ∈ upperBounds (range (Sigma.fst ∘ x)))(hy :
      i ∈ upperBounds (range (Sigma.fst ∘ y))), unify f x i hx = unify f y i hy := by
  obtain ⟨i, hi⟩ := Fintype.bddAbove_range (Sum.elim (fun a => (x a).1) fun a => (y a).1)
  rw [Sum.elim_range, upperBounds_union] at hi
  

Proof state:
case intro
L : Language
ι : Type v
inst✝⁵ : Preorder ι
G : ι → Type w
inst✝⁴ : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝³ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝² : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝¹ : Nonempty ι
α : Type u_1
inst✝ : Fintype α
x y : α → Σˣ f
xy : x ≈ y
i : ι
hi : i ∈ upperBounds (range fun a => (x a).fst) ∩ upperBounds (range fun a => (y a).fst)
⊢ ∃ i,
    ∃ (hx : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hy : i ∈ upperBounds (range (Sigma.fst ∘ y))),
      unify f x i hx = unify f y i hy

Next tactic:
simp_rw [← Function.comp_apply (f := Sigma.fst)] at hi
theorem exists_unify_eq {α : Type*} [Fintype α] {x y : α → Σˣ f} (xy : x ≈ y) :
    ∃ (i : ι)(hx : i ∈ upperBounds (range (Sigma.fst ∘ x)))(hy :
      i ∈ upperBounds (range (Sigma.fst ∘ y))), unify f x i hx = unify f y i hy := by
  obtain ⟨i, hi⟩ := Fintype.bddAbove_range (Sum.elim (fun a => (x a).1) fun a => (y a).1)
  rw [Sum.elim_range, upperBounds_union] at hi
  simp_rw [← Function.comp_apply (f := Sigma.fst)] at hi
  

Proof state:
case intro
L : Language
ι : Type v
inst✝⁵ : Preorder ι
G : ι → Type w
inst✝⁴ : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝³ : IsDirected ι fun x x_1 => x ≤ x_1
inst✝² : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝¹ : Nonempty ι
α : Type u_1
inst✝ : Fintype α
x y : α → Σˣ f
xy : x ≈ y
i : ι
hi : i ∈ upperBounds (range fun a => (Sigma.fst ∘ x) a) ∩ upperBounds (range fun a => (Sigma.fst ∘ y) a)
⊢ ∃ i,
    ∃ (hx : i ∈ upperBounds (range (Sigma.fst ∘ x))) (hy : i ∈ upperBounds (range (Sigma.fst ∘ y))),
      unify f x i hx = unify f y i hy

Next tactic:
exact ⟨i, hi.1, hi.2, funext fun a => (equiv_iff G f _ _).1 (xy a)⟩
/-- The direct limit `setoid` respects the structure `sigmaStructure`, so quotienting by it
  gives rise to a valid structure. -/
noncomputable instance prestructure : L.Prestructure (DirectLimit.setoid G f) where
  toStructure := sigmaStructure G f
  fun_equiv {n} {F} x y xy := by
    

Proof state:
L : Language
ι : Type v
inst✝⁴ : Preorder ι
G : ι → Type w
inst✝³ : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝² : IsDirected ι fun x x_1 => x ≤ x_1
inst✝¹ : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝ : Nonempty ι
n : ℕ
F : Functions L n
x y : Fin n → Σˣ f
xy : x ≈ y
⊢ funMap F x ≈ funMap F y

Next tactic:
obtain ⟨i, hx, hy, h⟩ := exists_unify_eq G f xy
/-- The direct limit `setoid` respects the structure `sigmaStructure`, so quotienting by it
  gives rise to a valid structure. -/
noncomputable instance prestructure : L.Prestructure (DirectLimit.setoid G f) where
  toStructure := sigmaStructure G f
  fun_equiv {n} {F} x y xy := by
    obtain ⟨i, hx, hy, h⟩ := exists_unify_eq G f xy
    

Proof state:
case intro.intro.intro
L : Language
ι : Type v
inst✝⁴ : Preorder ι
G : ι → Type w
inst✝³ : (i : ι) → Structure L (G i)
f : (i j : ι) → i ≤ j → G i ↪[L] G j
inst✝² : IsDirected ι fun x x_1 => x ≤ x_1
inst✝¹ : DirectedSystem G fun i j h => ⇑(f i j h)
inst✝ : Nonempty ι
n : ℕ
F : Functions L n
x y : Fin n → Σˣ f
xy : x ≈ y
i : ι
hx : i ∈ upperBounds (range (Sigma.fst ∘ x))
hy : i ∈ upperBounds (range (Sigma.fst ∘ y))
h : unify f x i hx = unify f y i hy
⊢ funMap F x ≈ funMap F y

Next tactic:
refine'
      Setoid.trans (funMap_equiv_unify G f F x i hx)
        (Setoid.trans _ (Setoid.symm (funMap_equiv_unify G f F y i hy)))