packages feed

liquidhaskell-0.8.10.7: benchmarks/esop2013-submission/Array.hs

{-@ LIQUID "--no-termination" @-}

module LiquidArray where

import Language.Haskell.Liquid.Prelude (liquidAssume)

data Vec a = V (Int -> a)
{-@
data Vec a <dom :: Int -> Bool, rng :: Int -> a -> Bool>
     = V {a :: i:Int<dom> -> a <rng i>}
  @-}


{-@ empty :: forall <p :: Int -> a -> Bool>. Vec <{\v -> 0=1}, p> a @-}
empty     :: Vec  a
empty     = V $ \_ -> (error "Empty array!")


{-@ create :: x:a -> Vec <{\v -> 0=0}, {\i v-> v=x}> a @-}
create     :: a -> Vec  a
create x   = V $ \_ -> x

{-@ get :: forall a <r :: x0: Int -> x1: a -> Bool, d :: x0: Int -> Bool>.
             i: Int<d> ->
             a: Vec<d, r> a ->
             a<r i> @-}
get :: Int -> Vec a -> a
get i (V f) = f i

{-@ set :: forall a <r :: x0: Int -> x1: a -> Bool, d :: x0: Int -> Bool>.
      i: Int<d> ->
      x: a<r i> ->
      a: Vec <{v:Int<d> | v != i}, r> a -> 
      Vec <d, r> a @-}
set :: Int -> a -> Vec a -> Vec a
set i v (V f) = V $ \k -> if k == i then v else f k


-------------------------------------------------------------------------------
---------------------------- init array  --------------------------------------
-------------------------------------------------------------------------------

{-@ zero ::
      i: {v: Int | v >= 0} ->
      n: Int ->
      a: Vec <{\v -> (0 <= v && v < i)}, {\d v -> v = 0}> Int ->
      Vec <{\v -> (0 <= v && v < n)}, {\d v ->  v = 0}> Int @-}
zero :: Int -> Int -> Vec Int -> Vec Int
zero i n a = if i >= n then a
                       else zero (i + 1) n (set i 0 a)
{-@ tenZeroes :: Vec <{\v ->  (0 <= v && v < 10)}, {\d v ->  v = 0}> Int  @-}
tenZeroes = zero z ten empty
  where z   = 0
        ten = 10 

{-@ zeroBackwards ::
      i: Int ->
      n: {v: Int | v > i} ->
      a: Vec <{\v ->  (i < v && v < n)}, {\d v ->  v = 0}> Int ->
      Vec <{\v ->  (0 <= v && v < n)}, {\d v ->  v = 0}> Int @-}
zeroBackwards :: Int -> Int -> Vec Int ->  Vec Int
zeroBackwards i n a = if i < 0 then a
                               else zeroBackwards (i - 1) n (set i 0 a)


{-@ tenZeroes' :: Vec <{\v -> (0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}
tenZeroes' :: Vec Int
tenZeroes' = zeroBackwards nine ten empty
  where nine = 9
        ten  = 10

{-@ zeroEveryOther ::
      i: {v: Int | (v >= 0 && v mod 2 = 0)} ->
      n: Int ->
      a: Vec <{\v -> (0 <= v && v < i && v mod 2 = 0)}, {\d v -> v = 0}> Int ->
      Vec <{\v ->  (0 <= v && v < n && v mod 2 = 0)}, {\d v -> v = 0}> Int @-}
zeroEveryOther :: Int -> Int -> Vec Int -> Vec Int
zeroEveryOther i n a = if i >= n then a
                       else zeroEveryOther (i + 2) n (set i 0 a)

{-@ stridedZeroes ::
      Vec <{\v -> (v mod 2 = 0 && 0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}
stridedZeroes :: Vec Int
stridedZeroes = zeroEveryOther z ten empty
  where z     = 0
        ten   = 10

{-@ initArray :: forall a <p :: x0: Int -> x1: a -> Bool>.
      f: Vec <{\v ->  0=0}, p> a ->
      i: {v: Int | v >= 0} ->
      n: Int ->
      a: Vec <{\v -> (0 <= v && v < i)}, p> a ->
      Vec <{\v -> (0 <= v && v < n)}, p> a  @-}
initArray :: Vec a -> Int -> Int -> Vec a -> Vec a
initArray (V f) i n a = if i >= n then a
                              else initArray (V f) (i + 1) n (set i (f i) a)

{-@ zeroInitArray ::
      i: {v: Int | v >= 0} ->
      n: Int ->
      a: Vec <{\v -> (0 <= v && v < i)}, {\d v -> v = 0}> Int ->
      Vec <{\v -> (0 <= v && v < n)}, {\d v ->  v = 0}> Int @-}
zeroInitArray :: Int -> Int -> Vec Int -> Vec Int
zeroInitArray = initArray (V (\_ ->  0))

{-@ tenZeroes'' :: Vec <{\v -> (0 <= v && v < 10)}, {\d v -> v = 0}> Int @-}
tenZeroes'' :: Vec Int
tenZeroes'' = zeroInitArray z ten empty
  where z   = 0
        ten = 10 

{-@ initid ::
      i: {v: Int | v >= 0} ->
      n: Int ->
      a: Vec <{\v -> (0 <= v && v < i)}, {\j v -> v = j}> Int ->
      Vec <{\v -> (0 <= v && v < n)}, {\k v ->  v = k}> Int @-}
initid :: Int -> Int -> Vec Int -> Vec Int
initid = initArray (V id)

-------------------------------------------------------------------------------
---------------------------- null terms  --------------------------------------
-------------------------------------------------------------------------------

{-@ upperCaseString' ::
      n: {v: Int | v > 0} ->
      i: {v: Nat | v < n} ->
      s: Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int ->
      Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int
@-}
upperCaseString' :: Int -> Int -> Vec Int -> Vec Int
upperCaseString' n i s =
  let c = get i s in
  if c == 0 then s
            else upperCaseString' n (i + 1) (set i (c + 32) s)

{-@ upperCaseString ::
      n: {v: Int | v > 0} ->
      s: Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int ->
      Vec <{\v -> (0 <= v && v < n)}, {\j v -> (j = n - 1 => v = 0)}> Int
@-}
upperCaseString :: Int -> Vec Int -> Vec Int
upperCaseString n s = upperCaseString' n 0 s



-------------------------------------------------------------------------------
---------------------------- memoization --------------------------------------
-------------------------------------------------------------------------------
{-@ measure fib :: Int -> Int @-}
{-@ type FibV = Vec <{\v -> 0=0}, {\j v -> ((v != 0) => (v = fib(j)))}> Int @-}


{-@ assume axiom_fib :: i:Int -> {v: Bool | v <=> (fib i = (if i <= 1 then 1 else (fib (i-1) + fib (i-2)))) } @-}
axiom_fib :: Int -> Bool
axiom_fib i = undefined

{-@ fastFib :: x:Int -> {v:Int | v = fib(x)} @-}
fastFib     :: Int -> Int
fastFib n   = snd $ fibMemo (V (\_ -> 0)) n


{-@ fibMemo :: FibV -> i:Int -> (FibV, {v: Int | v = fib(i)}) @-}
fibMemo :: Vec Int -> Int -> (Vec Int, Int)
fibMemo t i 
  | i <= 1    
  = (t, liquidAssume (axiom_fib i) (1 :: Int))
  
  | otherwise 
  = case get i t of   
      0 -> let (t1, n1) = fibMemo t  (i-1)
               (t2, n2) = fibMemo t1 (i-2)
               n        = liquidAssume (axiom_fib i) (n1 + n2)
           in  (set i n t2,  n)
      n -> (t, n)