packages feed

safe-coupling-0.1.0.0: src/TD/Lemmata/Relational/Iterate.hs

{-@ LIQUID "--reflection"     @-}
{-@ LIQUID "--ple"            @-}

module TD.Lemmata.Relational.Iterate where 

import           Monad.PrM
import           Data.Dist
import           Data.List
import           Prelude hiding (iterate)

import           Monad.PrM.Relational.TCB.Spec 
import           Monad.PrM.Predicates

import           TD.TD0 
import           Language.Haskell.Liquid.ProofCombinators
import           Misc.ProofCombinators


{-@ relationaliterate :: m:{_|0 <= m} -> {k:_|k >= 0} -> n:Nat -> l:Nat
                      -> f:(v:ListN l -> PrM (ListN l))
                      -> (m:{_|0 <= m} -> y1:{List Double|llen y1 = l} -> y2:{List Double|llen y2 = l} -> {bounded m y1 y2 => lift (bounded (k * m)) (f y1) (f y2)})
                      -> x1:ListN l -> x2:ListN l
                      -> {bounded m x1 x2 => lift (bounded (pow k n * m)) ((iterate n (llen x1) f) (x1)) 
                                                                          ((iterate n (llen x2) f) (x2))} / [n] @-}
relationaliterate :: Double -> Double -> Int -> Int
                  -> (List Double -> PrM (List Double)) 
                  -> (Double -> List Double -> List Double -> ()) 
                  -> List Double -> List Double
                  -> ()
relationaliterate m k 0 _ _ _ x1 x2 | bounded m x1 x2
    =   pureSpec (bounded (pow k 0 * m)) x1 x2 ()
relationaliterate m k n l f lemma x1 x2 | bounded m x1 x2
    =   assert (pow k (n-1) * (k * m) == pow k n * m) ? 
        bindSpec (bounded (pow k n * m)) (bounded (k * m)) 
                 (f x1) (iterate (n - 1) (llen x1) f)
                 (f x2) (iterate (n - 1) (llen x2) f)
                 (lemma m x1 x2)
                 (relationaliterate (k * m) k (n - 1) l f lemma)
relationaliterate m k n l f lemma x1 x2 = ()