Abstract Refinements {#induction} ================================= Induction --------- Encoding *induction* with Abstract refinements
12: module Loop where 13: import Prelude hiding ((!!), foldr, length, (++)) 14: -- import Measures 15: import Language.Haskell.Liquid.Prelude 16: {-@ LIQUID "--no-termination" @-} 17: 18: {-@ measure llen :: (L a) -> Int 19: llen (N) = 0 20: llen (C x xs) = 1 + (llen xs) @-} 21: 22: size :: L a -> Int 23: add :: Int -> Int -> Int 24: loop :: Int -> Int -> α -> (Int -> α -> α) -> α 25: foldr :: (L a -> a -> b -> b) -> b -> L a -> b
40: forall a <p :: (GHC.Types.Int)-> a-> Bool>. lo:(Int) -> hi:{VV : (Int) | (lo <= VV)} -> {VV : a<p lo> | true} -> (i:(Int) -> {VV : a<p i> | true} -> forall [ex:{VV : (Int) | (VV == (i + 1))}].{VV : a<p ex> | true}) -> {VV : a<p hi> | true}loop (Int)lo {VV : (Int) | (lo <= VV)}hi {VV : a | ((papp2 p VV lo))}base i:(Int) -> {VV : a | ((papp2 p VV i))} -> forall [ex:{VV : (Int) | (VV == (i + 1))}].{VV : a | ((papp2 p VV ex))}f = x1:{x4 : (Int) | (x4 >= lo) && (lo <= x4) && (x4 <= hi)} -> {VV : a | ((papp2 p VV x1))} -> {VV : a | ((papp2 p VV hi))}go {x2 : (Int) | (x2 == lo)}lo {VV : a | ((papp2 p VV lo)) && (VV == base)}base 41: where 42: i:{VV : (Int) | (VV >= lo) && (VV <= hi) && (lo <= VV)} -> {VV : a | ((papp2 p VV i))} -> {VV : a | ((papp2 p VV hi))}go {VV : (Int) | (VV >= lo) && (VV <= hi) && (lo <= VV)}i {VV : a | ((papp2 p VV i))}acc 43: | {x5 : (Int) | (x5 == i) && (x5 >= lo) && (lo <= x5) && (x5 <= hi)}i x1:{x14 : (Int) | (x14 >= i) && (x14 >= lo) && (i <= x14) && (lo <= x14) && (x14 <= hi)} -> x2:{x14 : (Int) | (x14 >= i) && (x14 >= lo) && (i <= x14) && (lo <= x14) && (x14 <= hi)} -> {x2 : (Bool) | (((Prop x2)) <=> (x1 < x2))}< {x3 : (Int) | (x3 == hi) && (lo <= x3)}hi = i:{VV : (Int) | (VV >= lo) && (VV <= hi) && (lo <= VV)} -> {VV : a | ((papp2 p VV i))} -> {VV : a | ((papp2 p VV hi))}go ({x5 : (Int) | (x5 == i) && (x5 >= lo) && (lo <= x5) && (x5 <= hi)}ix1:(Int) -> x2:(Int) -> {x4 : (Int) | (x4 == (x1 + x2))}+{x2 : (Int) | (x2 == (1 : int))}1) (x1:(Int) -> {VV : a | ((papp2 p VV x1))} -> forall [ex:{VV : (Int) | (VV == (x1 + 1))}].{VV : a | ((papp2 p VV ex))}f {x5 : (Int) | (x5 == i) && (x5 >= lo) && (lo <= x5) && (x5 <= hi)}i {VV : a | ((papp2 p VV i)) && (VV == acc)}acc) 44: | otherwise = {VV : a | ((papp2 p VV i)) && (VV == acc)}accIteration Dependence -------------------- We used `loop` to write
53: {-@ add :: n:Nat -> m:Nat -> {v:Nat|v=m+n} @-} 54: add n m = loop 0 m n (\_ i -> i + 1)
75: {-@ add :: n:Nat -> m:Nat -> {v:Nat|v=m+n} @-} 76: add n m = loop 0 m n (\_ i -> i + 1)
92: {-@ add :: n:Nat -> m:Nat -> {v:Nat|v=m+n} @-} 93: add n m = loop 0 m n (\_ i -> i + 1)
110: loop lo hi base f = go lo base 111: where 112: go i acc 113: | i < hi = go (i+1) (f i acc) 114: | otherwise = acc
136: loop lo hi base f = go lo base 137: where 138: go i acc 139: | i < hi = go (i+1) (f i acc) 140: | otherwise = acc
155: loop lo hi base f = go lo base 156: where 157: go i acc 158: | i < hi = go (i+1) (f i acc) 159: | otherwise = acc
173: loop lo hi base f = go lo base 174: where 175: go i acc 176: | i < hi = go (i+1) (f i acc) 177: | otherwise = acc
195: {-@ loop :: forall a <p :: Int -> a -> Prop>. 196: lo:Int 197: -> hi:{v:Int|lo <= v} 198: -> base:a<p lo> 199: -> f:(i:Int -> a<p i> -> a<p (i+1)>) 200: -> a<p hi> @-}
212: p :: Int -> a -> Prop -- invt 213: base :: a<p lo> -- base 214: f :: i:Int -> a<p i> -> a<p(i+1)> -- step 215: out :: a<p hi> -- goalUsing Induction ---------------
224: {-@ add :: n:Nat -> m:Nat -> {v:Nat| v=m+n} @-} 225: n:{VV : (Int) | (VV >= 0)} -> m:{VV : (Int) | (VV >= 0)} -> {VV : (Int) | (VV == (m + n)) && (VV >= 0)}add {VV : (Int) | (VV >= 0)}n {VV : (Int) | (VV >= 0)}m = forall <p :: (GHC.Types.Int)-> (GHC.Types.Int)-> Bool>. x1:(Int) -> x2:{x21 : (Int) | (x1 <= x21)} -> {x19 : (Int)<p x1> | (x19 >= 0) && (x19 >= n) && (n <= x19)} -> (i:(Int) -> {x19 : (Int)<p i> | (x19 >= 0) && (x19 >= n) && (n <= x19)} -> forall [ex:{VV : (Int) | (VV == (i + 1))}].{x19 : (Int)<p ex> | (x19 >= 0) && (x19 >= n) && (n <= x19)}) -> {x19 : (Int)<p x2> | (x19 >= 0) && (x19 >= n) && (n <= x19)}loop {x2 : (Int) | (x2 == (0 : int))}0 {x3 : (Int) | (x3 == m) && (x3 >= 0)}m {x3 : (Int) | (x3 == n) && (x3 >= 0)}n (x1:(Int) -> x2:{x17 : (Int) | (x17 == (x1 + n)) && (x17 == (n + x1)) && (x17 >= 0) && (x17 >= x1) && (x17 >= n) && (x1 <= x17) && (n <= x17)} -> {x9 : (Int) | (x9 == (x2 + 1)) && (x9 > 0) && (x9 > x1) && (x9 > x2) && (x9 > n) && (x9 >= 0) && (x1 <= x9) && (n <= x9)}\_ {VV : (Int) | (VV >= 0) && (VV >= n) && (n <= VV)}z -> {x5 : (Int) | (x5 == z) && (x5 >= 0) && (x5 >= n) && (n <= x5)}z x1:(Int) -> x2:(Int) -> {x4 : (Int) | (x4 == (x1 + x2))}+ {x2 : (Int) | (x2 == (1 : int))}1)
239: {-@ add :: n:Nat -> m:Nat -> {v:Nat| v=m+n} @-} 240: add n m = loop 0 m n (\_ z -> z + 1)
269: data L a = N 270: | C a (L a)
283: foldr f b N = b 284: foldr f b (C x xs) = f xs x (foldr f b xs)
297: {-@ foldr :: 298: forall a b <p :: L a -> b -> Prop>. 299: (xs:_ -> x:_ -> b<p xs> -> b<p(C x xs)>) 300: -> b<p N> 301: -> ys:L a 302: -> b<p ys> @-} 303: forall a b <p :: (Loop.L a)-> b-> Bool>. (xs:(L a) -> x:a -> {VV : b<p xs> | true} -> forall [ex:{VV : (L a) | (VV == (Loop.C x xs))}].{VV : b<p ex> | true}) -> forall [ex:{VV : (L a) | (VV == (Loop.N))}].{VV : b<p ex> | true} -> ys:(L a) -> {VV : b<p ys> | true}foldr xs:(L a) -> x:a -> {VV : b | ((papp2 p VV xs))} -> forall [ex:{VV : (L a) | (VV == (Loop.C x xs))}].{VV : b | ((papp2 p VV ex))}f forall [ex:{VV : (L a) | (VV == (Loop.N))}].{VV : a | ((papp2 p VV ex))}b N = forall [ex:{VV : (L a) | (VV == (Loop.N))}].{VV : a | ((papp2 p VV ex))}b 304: foldr f b (C x xs) = x1:(L a) -> x2:a -> {VV : b | ((papp2 p VV x1))} -> forall [ex:{VV : (L a) | (VV == (Loop.C x2 x1))}].{VV : b | ((papp2 p VV ex))}f {x2 : (L a) | (x2 == xs)}xs {VV : a | (VV == x)}x (forall <p :: (Loop.L a)-> b-> Bool>. (xs:(L a) -> x:a -> {VV : b<p xs> | true} -> forall [ex:{VV : (L a) | (VV == (Loop.C x xs))}].{VV : b<p ex> | true}) -> forall [ex:{VV : (L a) | (VV == (Loop.N))}].{VV : b<p ex> | true} -> x4:(L a) -> {VV : b<p x4> | true}foldr x1:(L a) -> x2:a -> {VV : b | ((papp2 p VV x1))} -> forall [ex:{VV : (L a) | (VV == (Loop.C x2 x1))}].{VV : b | ((papp2 p VV ex))}f forall [ex:{VV : (L a) | (VV == (Loop.N))}].{VV : a | ((papp2 p VV ex))}b {x2 : (L a) | (x2 == xs)}xs)
318: p :: L a -> b -> Prop 319: step :: xs:_ -> x:_ -> b<p xs> -> b<p(C x xs)> 320: base :: b<p N> 321: ys :: L a 322: out :: b<p ys>
336: p :: L a -> b -> Prop 337: step :: xs:_ -> x:_ -> b<p xs> -> b<p(C x xs)> 338: base :: b<p N> 339: ys :: L a 340: out :: b<p ys>
` states `foldr`: Ind. Step ------------------
355: p :: L a -> b -> Prop 356: step :: xs:_ -> x:_ -> b<p xs> -> b<p(C x xs)> 357: base :: b<p N> 358: ys :: L a 359: out :: b<p ys>
-> b
` `foldr`: Output ---------------
373: p :: L a -> b -> Prop 374: step :: xs:_ -> x:_ -> b<p xs> -> b<p(C x xs)> 375: base :: b<p N> 376: ys :: L a 377: out :: b<p ys>
`
Using `foldr`: Size
-------------------
We can now verify
392: {-@ size :: xs:_ -> {v:Int| v = (llen xs)} @-} 393: forall a. xs:(L a) -> {VV : (Int) | (VV == (llen xs))}size = forall <p :: (Loop.L a)-> (GHC.Types.Int)-> Bool>. (xs:(L a) -> x:a -> {x12 : (Int)<p xs> | (x12 >= 0)} -> forall [ex:{VV : (L a) | (VV == (Loop.C x xs))}].{x12 : (Int)<p ex> | (x12 >= 0)}) -> forall [ex:{VV : (L a) | (VV == (Loop.N))}].{x12 : (Int)<p ex> | (x12 >= 0)} -> x4:(L a) -> {x12 : (Int)<p x4> | (x12 >= 0)}foldr (x1:(L a) -> a -> x3:{x8 : (Int) | (x8 == (llen x1)) && (x8 >= 0)} -> {x5 : (Int) | (x5 == (x3 + 1)) && (x5 > 0) && (x5 > x3) && (x5 >= 0)}\_ _ {VV : (Int) | (VV >= 0)}n -> {x3 : (Int) | (x3 == n) && (x3 >= 0)}n x1:(Int) -> x2:(Int) -> {x4 : (Int) | (x4 == (x1 + x2))}+ {x2 : (Int) | (x2 == (1 : int))}1) {x2 : (Int) | (x2 == (0 : int))}0
408: {-@ (++) :: xs:_ -> ys:_ -> (Cat a xs ys) @-} 409: (L a)xs forall a. xs:(L a) -> ys:(L a) -> {VV : (L a) | ((llen VV) == ((llen xs) + (llen ys)))}++ (L a)ys = forall <p :: (Loop.L a)-> (Loop.L a)-> Bool>. (xs:(L a) -> x:a -> {x8 : (L a)<p xs> | true} -> forall [ex:{VV : (L a) | (VV == (Loop.C x xs))}].{x8 : (L a)<p ex> | true}) -> forall [ex:{VV : (L a) | (VV == (Loop.N))}].{x8 : (L a)<p ex> | true} -> x4:(L a) -> {x8 : (L a)<p x4> | true}foldr ((L a) -> a -> x3:(L a) -> {x2 : (L a) | ((llen x2) == (1 + (llen x3)))}\_ -> a -> x2:(L a) -> {x2 : (L a) | ((llen x2) == (1 + (llen x2)))}C) {x2 : (L a) | (x2 == ys)}ys {x2 : (L a) | (x2 == xs)}xs
421: {-@ type Cat a X Y = 422: {v:L a|(llen v) = (llen X) + (llen Y)} @-}
431: {-@ (++) :: xs:_ -> ys:_ -> (Cat a xs ys) @-} 432: xs ++ ys = foldr (\_ -> C) ys xs