-- 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: lemma mem_iff_isSome {m : Dict α ω} {x : α} : x ∈ m ↔ (m x).isSome

-- 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: @[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 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 proposition6_aux [Setoid' Y] {D₁ D₂ : Dict X Y}
  (h : ∀ k, D₁ k ≠ .none ∧ D₂ k ≠ .none → D₁ k ≅ D₂ k) : IsLUB {D₁, D₂} (Dict.Merge D₁ D₂)

-- Target theorem and proof:
lemma proposition6 [Setoid' Y] {D₁ D₂ : Dict X Y} :
  (∃ join, IsLUB {D₁, D₂} join) ↔ ∀ x, D₁ x ≠ .none ∧ D₂ x ≠ .none → D₁ x ≅ D₂ x
:= by
  refine' ⟨λ h ↦ _, λ h ↦ _⟩
  simp_rw [proposition5] at h
  simp_rw [←proposition4]
  aesop
  use D₁.Merge D₂
  exact proposition6_aux h