{-# OPTIONS --safe #-}
module RationalSingleTreeGame where
open import Library
open import Relation.Binary.PropositionalEquality using (cong₂)
open import Data.Rational
open import Data.Rational.Properties using
( +-identityˡ; +-assoc
; ≤-reflexive; +-monoʳ-≤; module ≤-Reasoning)
import Data.Rational.Tactic.RingSolver as ℚ
open import Tree using (Tree; ε; _∙_; tail; rotate)
open import SingleTreeGame using (Moves; C; R; T; ε; _∙_)
open import Counting using (count; count-compose; C:_T:_R:_)
[_]ℚ : ℕ → ℚ
[ zero ]ℚ = 0ℚ
[ suc n ]ℚ = 1ℚ + [ n ]ℚ
[+]ℚ : ∀ a b → [ a ℕ.+ b ]ℚ ≡ [ a ]ℚ + [ b ]ℚ
[+]ℚ zero b = sym (+-identityˡ [ b ]ℚ)
[+]ℚ (suc a) b
= trans (cong (1ℚ +_) ([+]ℚ a b))
(sym (+-assoc 1ℚ [ a ]ℚ [ b ]ℚ))
record Resourced (A : Set) : Set where
constructor _⨮_
field
resources : ℚ
payload : A
infixl 4 _⨮_
RT = Resourced Tree
rempty : RT
rempty = 0ℚ ⨮ ε
module RMoves (kₐ kₜ : ℚ) where
rmoves : Moves → RT → Maybe RT
rmoves C (q ⨮ t) = just (kₐ + q ⨮ t ∙ ε)
rmoves T (q ⨮ t) = Maybe.map (kₜ + q ⨮_) (tail t)
rmoves R (q ⨮ t) with q ≥? 1ℚ
... | yes _ = Maybe.map ((q - 1ℚ) ⨮_) (rotate t)
... | no _ = nothing
rmoves ε = just
rmoves (m ∙ m') = rmoves m >=> rmoves m'
thm-counts
: ∀ m q t {q' t'} (let (C: c# T: t# R: r#) = count m)
→ rmoves m (q ⨮ t) ≡ just (q' ⨮ t')
→ [ r# ]ℚ + q' ≤ [ c# ]ℚ * kₐ + ([ t# ]ℚ * kₜ + q)
thm-counts C q t refl = ≤-reflexive (step kₐ kₜ q)
where
step : ∀ kₐ kₜ q → [ 0 ]ℚ + (kₐ + q) ≡ [ 1 ]ℚ * kₐ + ([ 0 ]ℚ * kₜ + q)
step = ℚ.solve-∀
thm-counts T q (ε ∙ t) refl = ≤-reflexive (step kₐ kₜ q)
where
step : ∀ kₐ kₜ q → [ 0 ]ℚ + (kₜ + q) ≡ [ 0 ]ℚ * kₐ + ([ 1 ]ℚ * kₜ + q)
step = ℚ.solve-∀
thm-counts R q ε eq with q ≥? 1ℚ | eq
... | yes _ | ()
... | no _ | ()
thm-counts R q (ε ∙ _) eq with q ≥? 1ℚ | eq
... | yes _ | ()
... | no _ | ()
thm-counts R q ((t₁ ∙ t₂) ∙ t₃) eq with q ≥? 1ℚ | eq
... | yes _ | refl = ≤-reflexive (step kₐ kₜ q)
where
step : ∀ kₐ kₜ q → [ 1 ]ℚ + (q - 1ℚ) ≡ [ 0 ]ℚ * kₐ + ([ 0 ]ℚ * kₜ + q)
step = ℚ.solve-∀
... | no _ | ()
thm-counts ε q t refl = ≤-reflexive (step kₐ kₜ q)
where
step : ∀ kₐ kₜ q → [ 0 ]ℚ + q ≡ [ 0 ]ℚ * kₐ + ([ 0 ]ℚ * kₜ + q)
step = ℚ.solve-∀
thm-counts (m ∙ m') q t {q'} {t'} eq with rmoves m (q ⨮ t) in rm | eq
... | nothing | ()
... | just (q₁ ⨮ u) | eq' rewrite count-compose m m' =
let
(C: c# T: t# R: r# ) = count m
(C: c#' T: t#' R: r#') = count m'
p₁ : [ r# ]ℚ + q₁ ≤ [ c# ]ℚ * kₐ + ([ t# ]ℚ * kₜ + q)
p₁ = thm-counts m q t rm
p₂ : [ r#' ]ℚ + q' ≤ [ c#' ]ℚ * kₐ + ([ t#' ]ℚ * kₜ + q₁)
p₂ = thm-counts m' q₁ u eq'
open ≤-Reasoning
in
begin
[ r# ℕ.+ r#' ]ℚ + q'
≡⟨ cong (_+ q') ([+]ℚ r# r#') ⟩
([ r# ]ℚ + [ r#' ]ℚ) + q'
≡⟨ +-assoc [ r# ]ℚ [ r#' ]ℚ q' ⟩
[ r# ]ℚ + ([ r#' ]ℚ + q')
≤⟨ +-monoʳ-≤ [ r# ]ℚ p₂ ⟩
[ r# ]ℚ + ([ c#' ]ℚ * kₐ + ([ t#' ]ℚ * kₜ + q₁))
≡⟨ step₁ [ r# ]ℚ ([ c#' ]ℚ * kₐ) ([ t#' ]ℚ * kₜ) q₁ ⟩
[ c#' ]ℚ * kₐ + ([ t#' ]ℚ * kₜ + ([ r# ]ℚ + q₁))
≤⟨ +-monoʳ-≤ ([ c#' ]ℚ * kₐ) (+-monoʳ-≤ ([ t#' ]ℚ * kₜ) p₁) ⟩
[ c#' ]ℚ * kₐ + ([ t#' ]ℚ * kₜ + ([ c# ]ℚ * kₐ + ([ t# ]ℚ * kₜ + q)))
≡⟨ step₂ kₐ kₜ [ c# ]ℚ [ t# ]ℚ [ c#' ]ℚ [ t#' ]ℚ q ⟩
([ c# ]ℚ + [ c#' ]ℚ) * kₐ + (([ t# ]ℚ + [ t#' ]ℚ) * kₜ + q)
≡⟨ cong₂ (λ a b → a * kₐ + (b * kₜ + q))
(sym ([+]ℚ c# c#')) (sym ([+]ℚ t# t#')) ⟩
[ c# ℕ.+ c#' ]ℚ * kₐ + ([ t# ℕ.+ t#' ]ℚ * kₜ + q)
∎
where
step₁ : (r c t q : ℚ) → r + (c + (t + q)) ≡ c + (t + (r + q))
step₁ = ℚ.solve-∀
step₂ : (kₐ kₜ c₁ t₁ c₂ t₂ q : ℚ)
→ c₂ * kₐ + (t₂ * kₜ + (c₁ * kₐ + (t₁ * kₜ + q))) ≡ (c₁ + c₂) * kₐ + ((t₁ + t₂) * kₜ + q)
step₂ = ℚ.solve-∀