-- FVIntmax/Propositions.lean

import Mathlib.Order.Bounds.Basic

import Mathlib.Order.Bounds.Defs

import Mathlib.Order.Defs

import Aesop

import FVIntmax.Wheels.Dictionary

namespace Intmax

def iso {X : Type} [Preorder X] (a b : X) := a ≤ b ∧ b ≤ a

notation:51 (priority := high) a:52 " ≅ " b:52 => iso a b

section iso

variable {X : Type} [Preorder X]
         {a b c : X}

end iso

def IsEquivRel {X : Type} [Preorder X] := ∀ a b : X, a ≤ b ↔ a ≅ b

class Setoid' (X : Type) extends Preorder X where
  isEquiv : IsEquivRel (X := X)

section Automation

variable {α : Type} [Preorder α]
         {x y : α}

end Automation

section Propositions

variable {X Y : Type}

section proposition3

variable [Preorder X]
         {x? y? join? join'? : Option X}
         {x y join join' : X}

end proposition3

section Automation

variable {X : Type} [Setoid' X]
         {x y : X}
         {x? y? : Option X}

end Automation

-- Repository definitions used:
content: notation:51 (priority := high) a:52 " ≅ " b:52 => iso a b

content: def Merge (D₁ D₂ : Dict α ω) : Dict α ω := D
  where D := λ x ↦ First (D₁ x) (D₂ x)

content: def First (x₁ x₂ : Option α) : Option α :=
  match x₁, x₂ with
  | .some x, .none => .some x
  | .some x, .some _ => .some x
  | .none, .some y => .some y
  | .none, .none => .none

content: abbrev Dict (α ω : Type) : Type := α → Option ω

content: notation:65 π₁:65 " <+> " π₂:66 => Dict.Merge π₁ π₂

-- Repository lemmas used:
content: theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

-- Local definitions used:
content: def iso {X : Type} [Preorder X] (a b : X) := a ≤ b ∧ b ≤ a

content: def IsEquivRel {X : Type} [Preorder X] := ∀ a b : X, a ≤ b ↔ a ≅ b

content: class Setoid' (X : Type) extends Preorder X where
  isEquiv : IsEquivRel (X := X)

-- Local lemmas used:
content: @[simp, refl]
lemma iso_rfl : a ≅ a

content: @[symm]
lemma iso_symm : (a ≅ b) ↔ b ≅ a

content: @[trans]
lemma iso_trans : (a ≅ b) → (b ≅ c) → a ≅ c

content: lemma proposition2 [Setoid' X] {x y : X} :
  (∃ join : X, IsLUB {x, y} join) ↔ x ≅ y

content: lemma proposition2' [Setoid' X] {join x y : X} (h : IsLUB {x, y} join) :
  (x ≅ join) ∧ y ≅ join

content: lemma proposition3' : 
  (∃ join : X, IsLUB {x, y} join) ↔ (∃ join : Option X, IsLUB {.some x, .some y, .none} join)

content: lemma proposition4 [Setoid' X] {x y : Option X} :
  (∃ join : Option X, IsLUB {x, y, .none} join) ↔ (x ≠ .none ∧ y ≠ .none → x ≅ y)

content: lemma proposition4' [Setoid' X] {join x y : Option X} (h : IsLUB {x, y, .none} join) :
  join ≅ Dict.First x y

content: lemma proposition5 [Preorder Y] {f g : X → Y} {join : X → Y} :
  IsLUB {f, g} join ↔ ∀ x : X, IsLUB {f x, g x} (join x)

content: lemma proposition5' [Preorder Y] {f g h join' : X → Y}
  (h₀ : IsLUB {f, g} join')
  (h₁ : ∀ x, h x ≅ join' x) :
  join' ≅ h

-- Target theorem and proof:
lemma proposition6' [Setoid' Y] {D₁ D₂ join : Dict X Y} (h : IsLUB {D₁, D₂} join) :
  join ≅ Dict.Merge D₁ D₂
:= by
  unfold Dict.Merge Dict.Merge.D
  apply proposition5' (h₀ := h)
  intros x
  rw [iso_symm]
  apply proposition4'
  revert x
  rw [proposition5] at h
  simpa