-- FVIntmax/Wheels.lean

import Mathlib.Algebra.Order.Ring.Unbundled.Nonneg

import Mathlib.Data.Finite.Defs

import Mathlib.Data.Finmap

import Mathlib.Data.List.Intervals

import Mathlib.Data.Set.Image

import Mathlib.Logic.Embedding.Basic

import Mathlib.Tactic

import FVIntmax.Wheels.Wheels

namespace Intmax

namespace CryptoAssumptions

section Hashing

class Injective {α ω : Type} (f : α → ω) where
  h : ComputationallyInfeasible (¬ Function.Injective f)

end Hashing

end CryptoAssumptions

section UniquelyIndexed

prefix:max "!" => UniqueTokenT

namespace UniquelyIndexed

end UniquelyIndexed

end UniquelyIndexed

section NonNeg

postfix:max "₊" => NonNeg

section Nonneg

variable {α : Type} [PreWithZero α] {v : α₊}

end Nonneg

end NonNeg

section Order

section VectorPreorder

open Mathlib

variable {α : Type} [Preorder α] {n : ℕ}
         {v₁ v₂ v₃ : Vector α n}

namespace Vec

def le (v₁ v₂ : Vector α n) :=
  ∀ x ∈ (v₁.1.zip v₂.1), x.1 ≤ x.2

-- Repository definitions used:
content: ...

-- 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: class Injective {α ω : Type} (f : α → ω) where
  h : ComputationallyInfeasible (¬ Function.Injective f)

content: def le (v₁ v₂ : Vector α n) :=
  ∀ x ∈ (v₁.1.zip v₂.1), x.1 ≤ x.2

-- Local lemmas used:

-- Target theorem and proof:
lemma le_trans (h₁ : v₁ ≤ v₂) (h₂ : v₂ ≤ v₃) : v₁ ≤ v₃
:= by
  dsimp [(·≤·), le] at *
  rcases v₁ with ⟨l₁, hl₁⟩
  rcases v₂ with ⟨l₂, hl₂⟩
  rcases v₃ with ⟨l₃, hl₃⟩
  simp at *
  induction' l₂ with hd₂ tl₂ ih generalizing l₁ l₃ n
  · rcases l₃; exact h₁; simp_all; omega
  · rcases l₃ with _ | ⟨hd₃, tl₃⟩ <;> [simp; skip]
    rcases l₁ with _ | ⟨hd₁, tl₁⟩ <;> simp at *
    intros a b h
    rcases h with ⟨h₃, h₄⟩ | h
    · transitivity hd₂ <;> tauto
    · specialize @ih tl₁.length tl₁ rfl (by aesop) tl₃ (by aesop)
      aesop