import Provenance.SemiringWithMonus import Mathlib.Order.Interval.Set.Defs import Mathlib.Data.Rat.Init import Mathlib.Algebra.Order.Ring.Rat import Mathlib.Tactic.Ring.RingNF abbrev Interval01 := {q : ℚ // 0 ≤ q ∧ q ≤ 1} @[ext] structure Lukasiewicz where carrier : Interval01 instance : Coe Lukasiewicz Interval01 := ⟨Lukasiewicz.carrier⟩ instance : Zero Lukasiewicz where zero := ⟨⟨0, by simp⟩⟩ instance : One Lukasiewicz where one := ⟨⟨1, by simp⟩⟩ instance : Add Lukasiewicz where add a b := ⟨max a.carrier b.carrier⟩ instance : Mul Lukasiewicz where mul a b := let raw := max (a.carrier.val+b.carrier.val-1) 0 have h : raw ≥ 0 ∧ raw ≤ 1 := by have ha := a.carrier.property have hb := b.carrier.property unfold raw constructor . simp . simp calc a.carrier + b.carrier ≤ (1: ℚ) + b.carrier := by simp[ha.right] _ ≤ (1: ℚ) + 1 := by simp[hb.right] ⟨raw, h⟩ instance : Sub Lukasiewicz where sub a b := if a.carrier≤b.carrier then ⟨⟨0, by simp⟩⟩ else a instance : CommMagma Lukasiewicz where mul_comm := by intro a b have ha := a.carrier.property have hb := b.carrier.property simp[(· * ·), Mul.mul] rw[add_comm] instance instLeftDistribClassLukasiweicz : LeftDistribClass Lukasiewicz where left_distrib := by intro a b c simp[(· * ·), (· + ·), Mul.mul, Add.add] by_cases hbc: b.carrier ≤ c.carrier . simp[hbc] by_cases hab: a.carrier.val + b.carrier.val ≤ 1 . right exact hab . left constructor . exact add_le_add (le_of_eq rfl) hbc . simp at hab have := add_le_add (le_of_eq rfl: a.carrier.val ≤ a.carrier.val) hbc exact le_of_lt (lt_of_lt_of_le hab this) . simp at hbc simp[le_of_lt hbc] by_cases hac: a.carrier.val + c.carrier.val ≤ 1 . right exact hac . left constructor . exact add_le_add (le_of_eq rfl) (le_of_lt hbc) . simp at hac have := add_le_add (le_of_eq rfl: a.carrier.val ≤ a.carrier.val) (le_of_lt hbc) exact le_of_lt (lt_of_lt_of_le hac this) instance : CommSemiring Lukasiewicz where add_assoc := by intro a b c simp[(· + ·),Add.add] apply max_assoc add_comm := by intro a b simp[(· + ·),Add.add] apply max_comm zero_add := by intro a simp[(· + ·),Add.add] have ha := a.carrier.property.left ext simp apply eq_of_le_of_ge . simp exact ha . simp add_zero := by intro a simp[(· + ·),Add.add] have ha := a.carrier.property.left ext simp apply eq_of_le_of_ge . simp exact ha . simp mul_assoc := by intro a b c have ha := a.carrier.property have hb := b.carrier.property have hc := c.carrier.property simp[(· * ·), Mul.mul] rw[add_max,max_add] simp by_cases h₁ : c.carrier.val ≤ a.carrier.val + b.carrier.val - 1 + c.carrier.val . rw[max_eq_left h₁] by_cases h₂ : a.carrier.val ≤ a.carrier.val + (b.carrier.val + c.carrier.val - 1) . rw[max_eq_left h₂] ring_nf . rw[max_eq_right (le_of_not_ge h₂)] simp at h₂ have : a.carrier.val - 1 ≤ 0 := by simp[ha.2] rw[max_eq_right this] simp ring_nf have bound : a.carrier.val + b.carrier.val + c.carrier.val < 2 := by calc a.carrier.val + b.carrier.val + c.carrier.val = a.carrier.val + (b.carrier.val + c.carrier.val) := by ring _ < a.carrier.val + 1 := add_lt_add_right h₂ a.carrier.val _ ≤ 1 + 1 := by simp[ha.2] _ = 2 := by norm_num have := add_lt_add_left bound (-1) ring_nf at this exact (le_of_lt this) . rw[max_eq_right (le_of_not_ge h₁)] simp at h₁ by_cases h₂ : a.carrier.val ≤ a.carrier.val + (b.carrier.val + c.carrier.val - 1) . rw[max_eq_left h₂] simp at h₂ have : c.carrier.val - 1 ≤ 0 := by simp[hc.2] rw[max_eq_right this] simp ring_nf have bound : a.carrier.val + b.carrier.val + c.carrier.val < 2 := by calc a.carrier.val + b.carrier.val + c.carrier.val _ < 1 + c.carrier.val := add_lt_add_left h₁ c.carrier.val _ ≤ 1 + 1 := by simp[hc.2] _ = 2 := by norm_num have := add_lt_add_left bound (-1) ring_nf at this exact (le_of_lt this) . rw[max_eq_right (le_of_not_ge h₂)] simp at h₂ have : a.carrier.val - 1 ≤ 0 := by simp[ha.2] rw[max_eq_right this] simp exact hc.2 nsmul := nsmulRec zero_mul := by intro a simp[(· * ·), Mul.mul] congr simp exact add_le_of_nonpos_of_le rfl a.carrier.property.2 mul_zero := by intro a have ha := a.carrier.property simp[(· * ·), Mul.mul] congr simp rw[add_comm] exact add_le_of_nonpos_of_le rfl a.carrier.property.2 one_mul := by intro a simp[(· * ·), Mul.mul] congr have : (Lukasiewicz.carrier 1).val = 1 := by rfl rw[this] simp exact a.carrier.property.1 mul_one := by intro a simp[(· * ·), Mul.mul] congr have : (Lukasiewicz.carrier 1).val = 1 := by rfl rw[this] simp exact a.carrier.property.1 left_distrib := instLeftDistribClassLukasiweicz.left_distrib right_distrib := by intro a b c rw[mul_comm (a+b) c,mul_comm a c,mul_comm b c] exact left_distrib c a b instance : LinearOrder Lukasiewicz where le a b := a.carrier ≤ b.carrier le_refl := by simp le_antisymm := by intro a b hab hba ext have := le_antisymm hab hba exact congrArg _ this le_trans := by intro a b c hab hbc exact le_trans hab hbc le_total := by intro a b exact le_total _ _ toDecidableLE := inferInstance instance : IsOrderedAddMonoid Lukasiewicz where add_le_add_left := by intro a b hab c simp[(· + ·),Add.add] by_cases hca : c.carrier ≤ a.carrier . rw[max_eq_left hca] rw[max_eq_left (le_trans hca hab)] exact hab . simp at hca rw[max_eq_right (le_of_lt hca)] exact le_max_right b.carrier c.carrier instance : CanonicallyOrderedAdd Lukasiewicz where exists_add_of_le := by intro a b hab simp[(· + ·), Add.add] use b rw[@max_eq_right _ _ a.carrier b.carrier hab] le_self_add := by intro a b simp[(· + ·), Add.add] exact le_max_left a.carrier b.carrier le_add_self := by intro a b simp[(· + ·), Add.add] exact le_max_right b.carrier a.carrier instance : SemiringWithMonus Lukasiewicz where monus_spec := by intro a b c simp[(· - ·),Sub.sub,(· + ·),Add.add] apply Iff.intro . intro h by_cases hab: a.carrier ≤ b.carrier . apply le_trans hab exact le_max_left b.carrier c.carrier . simp[hab] at h simp at hab have hbc : b.carrier ≤ c.carrier := le_trans (le_of_lt hab) h simp[hbc] exact h . intro h by_cases hab: a.carrier ≤ b.carrier . simp[hab] exact c.carrier.property.1 . simp[hab] by_cases hbc: b.carrier ≤ c.carrier . simp[hbc] at h exact h . simp at hbc simp[le_of_lt hbc] at h contradiction theorem Lukasiewicz.absorptive : absorptive Lukasiewicz := by intro a simp[(· + ·), Add.add] congr refine max_eq_left ?_ have h₁ := a.1.2.2 have h₂ : (One.one: Lukasiewicz).1.1 = (1: ℚ) := by rfl simp[← h₂] at h₁ exact h₁ theorem Lukasiewicz.idempotent : idempotent Lukasiewicz := idempotent_of_absorptive (Lukasiewicz.absorptive)