lean4-htt/tests/bench/rbmap2.lean
2019-05-29 16:33:50 +02:00

233 lines
7.8 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
universes u v w w'
namespace tst
inductive Rbcolor
| red | black
inductive Rbnode (α : Type u) (β : α → Type v)
| leaf {} : Rbnode
| Node (c : Rbcolor) (lchild : Rbnode) (key : α) (val : β key) (rchild : Rbnode) : Rbnode
namespace Rbnode
variables {α : Type u} {β : α → Type v} {σ : Type w}
instance Rbcolor.DecidableEq : DecidableEq Rbcolor :=
{decEq := λ a b, Rbcolor.casesOn a
(Rbcolor.casesOn b (isTrue rfl) (isFalse (λ h, Rbcolor.noConfusion h)))
(Rbcolor.casesOn b (isFalse (λ h, Rbcolor.noConfusion h)) (isTrue rfl))}
open tst.Rbcolor
def depth (f : Nat → Nat → Nat) : Rbnode α β → Nat
| leaf := 0
| (Node _ l _ _ r) := (f (depth l) (depth r))+1
protected def min : Rbnode α β → Option (Σ k : α, β k)
| leaf := none
| (Node _ leaf k v _) := some ⟨k, v⟩
| (Node _ l _ _ _) := min l
protected def max : Rbnode α β → Option (Σ k : α, β k)
| leaf := none
| (Node _ _ k v leaf) := some ⟨k, v⟩
| (Node _ _ _ _ r) := max r
@[specialize] def fold (f : Π (k : α), β k → σσ) : Rbnode α β → σσ
| leaf b := b
| (Node _ l k v r) b := fold r (f k v (fold l b))
@[specialize] def mfold {m : Type w → Type w'} [Monad m] (f : Π (k : α), β k → σ → m σ) : Rbnode α β → σ → m σ
| leaf b := pure b
| (Node _ l k v r) b := do b₁ ← mfold l b, b₂ ← f k v b₁, mfold r b₂
@[specialize] def revFold (f : Π (k : α), β k → σσ) : Rbnode α β → σσ
| leaf b := b
| (Node _ l k v r) b := revFold l (f k v (revFold r b))
@[specialize] def all (p : Π k : α, β k → Bool) : Rbnode α β → Bool
| leaf := true
| (Node _ l k v r) := p k v && all l && all r
@[specialize] def any (p : Π k : α, β k → Bool) : Rbnode α β → Bool
| leaf := false
| (Node _ l k v r) := p k v || any l || any r
def balance (rb : Rbcolor) (t1 : Rbnode α β) (k : α) (vk : β k) (t2 : Rbnode α β) :=
match rb with
| red := Node red t1 k vk t2
| black :=
match t1 with
| Node red (Node red a x vx b) y vy c :=
Node red (Node black a x vx b) y vy (Node black c k vk t2)
| Node red a x vx (Node red b y vy c) :=
Node red (Node black a x vx b) y vy (Node black c k vk t2)
| a := match t2 with
| Node red (Node red b y vy c) z vz d :=
Node red (Node black t1 k vk b) y vy (Node black c z vz d)
| Node red b y vy (Node red c z vz d) :=
Node red (Node black t1 k vk b) y vy (Node black c z vz d)
| _ := Node black t1 k vk t2
def makeBlack (t : Rbnode α β) :=
match t with
| leaf := leaf
| Node _ a x vx b := Node black a x vx b
section insert
variables (lt : αα → Prop) [DecidableRel lt]
def ins (x : α) (vx : β x) : Rbnode α β → Rbnode α β
| leaf := Node red leaf x vx leaf
| (Node c a y vy b) :=
if lt x y then balance c (ins a) y vy b
else if lt y x then balance c a y vy (ins b)
else Node c a x vx b
def insert (t : Rbnode α β) (k : α) (v : β k) : Rbnode α β :=
makeBlack (ins lt k v t)
end insert
section membership
variable (lt : αα → Prop)
variable [DecidableRel lt]
def findCore : Rbnode α β → Π k : α, Option (Σ k : α, β k)
| leaf x := none
| (Node _ a ky vy b) x :=
(match cmpUsing lt x ky with
| Ordering.lt := findCore a x
| Ordering.Eq := some ⟨ky, vy⟩
| Ordering.gt := findCore b x)
def find {β : Type v} : Rbnode α (λ _, β) → α → Option β
| leaf x := none
| (Node _ a ky vy b) x :=
(match cmpUsing lt x ky with
| Ordering.lt := find a x
| Ordering.Eq := some vy
| Ordering.gt := find b x)
def lowerBound : Rbnode α β → α → Option (Sigma β) → Option (Sigma β)
| leaf x lb := lb
| (Node _ a ky vy b) x lb :=
(match cmpUsing lt x ky with
| Ordering.lt := lowerBound a x lb
| Ordering.Eq := some ⟨ky, vy⟩
| Ordering.gt := lowerBound b x (some ⟨ky, vy⟩))
end membership
inductive WellFormed (lt : αα → Prop) : Rbnode α β → Prop
| leafWff : WellFormed leaf
| insertWff {n n' : Rbnode α β} {k : α} {v : β k} [DecidableRel lt] : WellFormed n → n' = insert lt n k v → WellFormed n'
end Rbnode
open tst.Rbnode
/- TODO(Leo): define dRbmap -/
def Rbmap (α : Type u) (β : Type v) (lt : αα → Prop) : Type (max u v) :=
{t : Rbnode α (λ _, β) // t.WellFormed lt }
@[inline] def mkRbmap (α : Type u) (β : Type v) (lt : αα → Prop) : Rbmap α β lt :=
⟨leaf, WellFormed.leafWff lt⟩
namespace Rbmap
variables {α : Type u} {β : Type v} {σ : Type w} {lt : αα → Prop}
def depth (f : Nat → Nat → Nat) (t : Rbmap α β lt) : Nat :=
t.val.depth f
@[inline] def fold (f : α → β → σσ) : Rbmap α β lt → σσ
| ⟨t, _⟩ b := t.fold f b
@[inline] def revFold (f : α → β → σσ) : Rbmap α β lt → σσ
| ⟨t, _⟩ b := t.revFold f b
@[inline] def mfold {m : Type w → Type w'} [Monad m] (f : α → β → σ → m σ) : Rbmap α β lt → σ → m σ
| ⟨t, _⟩ b := t.mfold f b
@[inline] def mfor {m : Type w → Type w'} [Monad m] (f : α → β → m σ) (t : Rbmap α β lt) : m PUnit :=
t.mfold (λ k v _, f k v *> pure ⟨⟩) ⟨⟩
@[inline] def empty : Rbmap α β lt → Bool
| ⟨leaf, _⟩ := true
| _ := false
@[specialize] def toList : Rbmap α β lt → List (α × β)
| ⟨t, _⟩ := t.revFold (λ k v ps, (k, v)::ps) []
@[inline] protected def min : Rbmap α β lt → Option (α × β)
| ⟨t, _⟩ :=
match t.min with
| some ⟨k, v⟩ := some (k, v)
| none := none
@[inline] protected def max : Rbmap α β lt → Option (α × β)
| ⟨t, _⟩ :=
match t.max with
| some ⟨k, v⟩ := some (k, v)
| none := none
instance [HasRepr α] [HasRepr β] : HasRepr (Rbmap α β lt) :=
⟨λ t, "rbmapOf " ++ repr t.toList⟩
variables [DecidableRel lt]
def insert : Rbmap α β lt → α → β → Rbmap α β lt
| ⟨t, w⟩ k v := ⟨t.insert lt k v, WellFormed.insertWff w rfl⟩
@[specialize] def ofList : List (α × β) → Rbmap α β lt
| [] := mkRbmap _ _ _
| (⟨k,v⟩::xs) := (ofList xs).insert k v
def findCore : Rbmap α β lt → α → Option (Σ k : α, β)
| ⟨t, _⟩ x := t.findCore lt x
def find : Rbmap α β lt → α → Option β
| ⟨t, _⟩ x := t.find lt x
/-- (lowerBound k) retrieves the kv pair of the largest key smaller than or equal to `k`,
if it exists. -/
def lowerBound : Rbmap α β lt → α → Option (Σ k : α, β)
| ⟨t, _⟩ x := t.lowerBound lt x none
@[inline] def contains (t : Rbmap α β lt) (a : α) : Bool :=
(t.find a).isSome
def fromList (l : List (α × β)) (lt : αα → Prop) [DecidableRel lt] : Rbmap α β lt :=
l.foldl (λ r p, r.insert p.1 p.2) (mkRbmap α β lt)
@[inline] def all : Rbmap α β lt → (α → β → Bool) → Bool
| ⟨t, _⟩ p := t.all p
@[inline] def any : Rbmap α β lt → (α → β → Bool) → Bool
| ⟨t, _⟩ p := t.any p
end Rbmap
def rbmapOf {α : Type u} {β : Type v} (l : List (α × β)) (lt : αα → Prop) [DecidableRel lt] : Rbmap α β lt :=
Rbmap.fromList l lt
end tst
@[reducible] def map : Type := tst.Rbmap Nat Bool (<)
def mkMapAux : Nat → Nat → map → map
| 0 i m := m
| (n+1) i m := mkMapAux n (i+1) (tst.Rbmap.insert m i (i % 10 = 0))
def mkMap (n : Nat) :=
mkMapAux n 0 (tst.mkRbmap Nat Bool (<))
def main (xs : List String) : IO UInt32 :=
let m := mkMap xs.head.toNat in
let v := tst.Rbmap.fold (λ (k : Nat) (v : Bool) (r : Nat), if v then r + 1 else r) m 0 in
IO.println (toString v) *>
pure 0