source: sizechecking/Constraints.hs @ 17

Last change on this file since 17 was 17, checked in by gobi, 12 years ago

copyu

File size: 15.1 KB
Line 
1--
2-- Copyright (C) 2012 Attila Gobi - http://kp.elte.hu/sizechecking
3--
4
5{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances,
6             IncoherentInstances, RankNTypes, ScopedTypeVariables,
7             FlexibleContexts,UndecidableInstances, DeriveDataTypeable,
8             ImpredicativeTypes #-}
9module Constraints where
10
11import Lambda
12import qualified Data.List as List
13import qualified Data.Set as Set
14import qualified Data.Map as Map
15import qualified Data.Ord as Ord
16import qualified Data.SBV as SBV
17import Data.SBV ( (.==), (.<), (.>=))
18import Control.Monad
19import Control.Monad.IO.Class
20import Data.IORef()
21import Data.Supply as S
22import Data.Data
23import Data.IORef
24import Data.Dynamic
25
26asType :: a -> a -> a
27asType a _ = a
28
29data D = D { var::Int, cond::[Condition] } 
30
31data TypeKind = V | L TypeKind | F TypeKind TypeKind | U
32    deriving Show
33
34
35class TS a where
36    tk :: a -> TypeKind
37instance (TS a, TS b) => TS (a -> b) where
38    tk _ = F (tk (undefined :: a)) (tk (undefined :: b))
39instance TS a => TS [a] where
40    tk _ = L (tk (undefined :: a))
41instance TS a where
42    tk _ = V
43instance TS Int where
44    tk _ = U
45
46appall :: Int -> [L] -> L
47appall var = foldl App (Var var)
48
49data Condition = Condition [Constraint] L L
50
51instance Show Condition where
52    showsPrec _ (Condition d a b) = shows d . showString "|- " . shows a . showString " = " . shows b
53    showList [] = showString ""
54    showList [x] = shows x
55    showList (x:xs) = shows x . showString "\n" . shows xs
56
57data Constraint = Zero L | LTC L L | GEC L L
58    deriving Eq
59
60instance Show Constraint where
61    showList []     = id
62    showList [s]    = shows s . showChar ' '
63    showList (x:xs) = shows x . showString ", " . shows xs
64    showsPrec _ (Zero s) = shows s . showString " = 0"
65    showsPrec _ (LTC s1 s2) = shows s1 . showString " < " . shows s2
66    showsPrec _ (GEC s1 s2) = shows s1 . showString " >= " . shows s2
67
68normalize :: L -> L
69normalize l = delzero $ foldl (\a b -> Op a '-' b) (foldl (\a b -> Op  a '+' b) (f1 $ List.sortBy (Ord.comparing snd) a) c) d
70    where
71    (a,b,c,d) = norm l
72    f1 ((0,l):xs) = f1 xs
73    f1 ((1,l):xs) = Op (f1 xs) '+' (Var l)
74    f1 ((-1,l):xs) = Op (f1 xs) '-' (Var l)
75    f1 [] = Num b
76
77    delzero (Op (Num 0) '+' b) = b
78    delzero (Op a c b) = Op (delzero a) c b
79    delzero l          = l
80
81gnormalize :: L -> (L, Int)
82gnormalize l = case (c,d) of
83        ([], []) -> case nonzero of
84            [] -> (Num 0, b)
85            _  -> (expr, b)
86        (_, _)   -> error $ "Expression in condition" ++ show c
87    where
88    nonzero = List.sortBy (Ord.comparing snd) $ filter ((/=0).fst) a
89    proc (1, l) = Var l
90    proc (-1, l) = Op (Num (-1)) '*' (Var l)
91    t :: L -> (Int, Int) -> L
92    t l (1, var) = Op l '+' (Var var)
93    t l (-1, var) = Op l '-' (Var var)
94    expr = foldl t (proc $ head nonzero) (tail nonzero)
95
96    (a,b,c,d) = norm l
97
98normalizec :: Constraint -> Constraint
99normalizec (Zero l) = Zero $ normalize l
100normalizec (LTC a b) = LTC (normalize a) (normalize b)
101normalizec (GEC a b) = GEC (normalize a) (normalize b)
102--normalizec (LTC a b) = LTC x (Num (-y))
103--    where (x,y) = gnormalize $ Op a '-' b
104--normalizec (GEC a b) = GEC x (Num (-y))
105--    where (x,y) = gnormalize $ Op a '-' b
106
107normalizecs :: [Constraint] -> [Constraint]
108normalizecs = normalizecs' . Prelude.map normalizec
109    where
110    normalizecs' [] = []
111    normalizecs' (x:xs) = x:normalizecs' (filter (/=x) xs)
112
113{-
114 - Takes an extended lambda expression and
115 -}
116norm :: L -> ([(Int, Int)], Int, [L], [L])
117norm (App a b)     = ([], 0, [App (normalize a) (normalize b)], [])
118norm (List a b)    = ([], 0, [List (normalize a) (normalize b)], [])
119norm (AAbs a b e)  = ([], 0, [AAbs a b (normalize e)], [])
120norm (Shift a b c) = ([], 0, [Shift (normalize a) (normalize b) (normalize c)], [])
121norm (Unsized)     = ([], 0, [Unsized], [])
122norm (Bottom)      = ([], 0, [Bottom], [])
123norm (Abs i l)     = ([], 0, [Abs i $ normalize l], [])
124norm (Var i)       = ([(1, i)], 0, [], [])
125norm (Num i)       = ([], i, [], [])
126norm q@(Op a c b)  = case c of
127    '+' -> (a1++b1, a2+b2, a3++b3, a4++b4)
128    '-' -> (sub a1 b1, a2-b2, a3++b4, a4++b3)
129    '*' -> case a of
130            (Num cnt) -> (map (mul cnt) b1, cnt*b2, map (Op (Num cnt) '*') b3, map (Op (Num cnt) '*') b4)
131            _         -> ([], 0, [q], [])
132    _   -> ([], 0, [q], [])
133    where
134        mul c (x,var) = (c*x, var)
135        (a1, a2, a3, a4) = norm a
136        (b1, b2, b3, b4) = norm b
137        sub l1 ((c,i):xs) = sub (sub' l1 c i) xs
138            where
139            sub' [] c i = [(-c, i)]
140            sub' ((cc,ii):xs) c i = if i==ii then (cc-c,i):xs else (cc,ii):sub' xs c i
141        sub l1 [] = l1
142
143tnorm = Op (Num 1) '+' (Op (Var 0) '-' (Num 1))
144
145checkCond :: Supply Int -> [Condition] -> IO [Condition]
146checkCond v l = do
147    ll <- mapM (checkCond1 v) l
148    return $ concat ll
149
150    where
151--    checkCond1 v p@(Condition d a b) | a==b = do
152--        return  []
153    checkCond1 v z@(Condition d (List a b) (List p q)) = do
154--        i <- freshtypevar v
155        let (v1,v2,v3) = split3 v
156        let i = supplyValue v1
157        let b' = rall $ App b (Var i)
158        let q' = rall $ App q (Var i)
159        l1 <- checkCond1 v2 (Condition ((Var i `GEC` Num 0):d) a p) 
160        l2 <- checkCond1 v3 (Condition ((Var i `GEC` Num 0):(Var i `LTC` a):(Var i `LTC` p):d) b' q')
161        return $ l1++l2
162    checkCond1 v z@(Condition d (App (Shift e f g) h) x) = do
163        let (v1,v2,v3) = split3 v
164        let e' = rall $ App e h
165        let g' = rall $ App g $ Op h '-' f
166        l1 <- checkCond1 v1 (Condition ((h `LTC` f):d) e' x)
167        l2 <- checkCond1 v2 (Condition ((h `GEC` f):d) g' x)
168--        putStrLn $ " -> " ++ show l1
169--        putStrLn $ " -> " ++ show l2
170        return $ l1 ++ l2
171    checkCond1 v z@(Condition d (App (Var a) x) (App (Var b) y)) | a==b =
172        checkCond1 v (Condition d x y)
173    checkCond1 v p@(Condition d x z@(App (Shift e f g) h)) =
174        checkCond1 v (Condition d z x)
175    checkCond1 v z@(Condition d a b) = return [Condition dd (normalize a) (normalize b)]
176        where
177        dd = normalizecs d
178
179subst ndl hst (App a b)     = App (subst ndl hst a) (subst ndl hst b)
180subst ndl hst (List a b)    = List (subst ndl hst a) (subst ndl hst b)
181subst ndl hst (AAbs a b e)  = AAbs a b (subst ndl hst e)
182subst ndl hst (Shift a b c) = Shift (subst ndl hst a) (subst ndl hst b) (subst ndl hst c)
183subst ndl hst (Unsized)     = Unsized
184subst ndl hst (Bottom)      = Bottom
185subst ndl hst q@(Abs i l)   = if ndl==i then q else Abs i $ subst ndl hst l
186subst ndl hst q@(Var i)     = if ndl==i then hst else q
187subst ndl hst (Num i)       = Num i
188subst ndl hst (Op a c b)    = Op (subst ndl hst a) c (subst ndl hst b)
189
190substc ndl hst (Zero l)  = Zero $ subst ndl hst l
191substc ndl hst (LTC a b) = LTC (subst ndl hst a) (subst ndl hst b)
192substc ndl hst (GEC a b) = GEC (subst ndl hst a) (subst ndl hst b)
193
194reorder cs = if any check cs
195        then Just (map r cs)
196        else Nothing
197    where
198    check (Zero _)        = False
199    check (LTC a (Num 0)) = False 
200    check (GEC a (Num 0)) = False 
201    check _               = True
202    r (LTC a b) = LTC (normalize (Op a '-' b)) (Num 0)
203    r (GEC a b) = GEC (normalize (Op a '-' b)) (Num 0)
204    r l         = l
205
206solve :: [Condition] -> Supply Int -> IO [Condition]
207solve l supply = do
208    ll <- forM (zip l $ split supply) (\(c,s) -> do
209        putStrLn $ "\nSOLVING " ++ show c
210        solve1 s c
211        )
212    return $ concat ll
213    where
214
215    searchzero (Zero (Var a):xs) = Just (a,xs)
216    searchzero (x:xs)            = do
217        (a,l) <- searchzero xs
218        return (a,x:l)
219    searchzero []                = Nothing
220
221
222    searcheq (q@(GEC (Var var) exp):xs) prev = case findeq (List.reverse prev ++ xs) [] of
223            Nothing -> searcheq xs (q:prev)
224            l       -> l
225        where
226        expinc = normalize $ Op exp '+' $ Num 1
227        findeq []                       _     = Nothing
228        findeq (LTC (Var var2) exp2:xs) prev2 | var==var2 && exp2==expinc = Just (var, exp, List.reverse prev2 ++ xs)
229        findeq (x:xs)                   prev2 = findeq xs (x:prev2)
230
231    searcheq (x:xs)                 prev = searcheq xs (x:prev) 
232    searcheq []                     _    = Nothing
233
234    checkConds [] = False
235    checkConds (LTC a b : xs) | GEC a b `elem` xs            = True
236    checkConds (GEC a b : xs) | LTC a b `elem` xs            = True
237    checkConds (LTC a (Num b) : xs) | b<=0 && elem (Zero a) xs = True
238    checkConds (GEC a (Num b) : xs) | b>0  && elem (Zero a) xs = True
239    checkConds (_:xs) = checkConds xs
240
241    checkConds2 (LTC (Num a) (Num b):xs) | a>=b = Nothing
242    checkConds2 (LTC (Num a) (Num b):xs) | a<= checkConds2 xs
243    checkConds2 (GEC (Num a) (Num b):xs) | a<= Nothing
244    checkConds2 (GEC (Num a) (Num b):xs) | a>=b = checkConds2 xs
245    checkConds2 (x:xs)                          = do { y <- checkConds2 xs; return (x:y) }
246    checkConds2 []                              = Just []
247
248--    applyList a b d supp = do
249--        let (s1,s2,s3) = split3 supp
250--        let t = fresh (L V) s1
251--        let dd = (Condition d (rall $ App a t) (rall $ App b t))
252--        putStrLn $ "Applying a fresh variable: "++(show t) ++"\n"++(show dd)
253--        x <- checkCond s2 [dd] >>= mapM (solve1 s3)
254--        return $ concat x
255
256    solve1  supp c@(Condition d a b) = case checkConds2 d of
257        Nothing -> do
258            putStrLn "Contradiction in preconditions"
259            return []
260        Just d' -> solve1' supp $ Condition d a b
261
262    solve1' supp c@(Condition d a b)
263--        | checkConds d = do
264--            putStrLn "Contradiction in preconditions"
265--            return []
266        | a==b = do
267            putStrLn "Equals"
268            return []
269--        | Just (var, nl) <- searchzero d = do
270--            let x = Condition (Prelude.map (normalizec.substc var (Num 0)) nl)
271--                        (normalize$subst var (Num 0) a)
272--                        (normalize$subst var (Num 0) b)
273--
274--            putStrLn $ show (Var var) ++ " is zero:\n" ++ show x
275--            solve1 supp x
276--        | Just (var, exp, nl) <- searcheq d [] = do
277--            putStrLn $ "Found equation " ++ show (Var var) ++ " = " ++ show exp
278--            let x = Condition (Prelude.map (normalizec.substc var exp) nl )
279--                        (normalize$subst var exp a)
280--                        (normalize$subst var exp b)
281--            putStrLn $ "New equations:\n" ++ show x
282--            solve1 supp x
283        | App p q <- a, App r s <- b = do
284            putStrLn "Branching!"
285            nc <- checkCond supp [Condition d p r, Condition d q s] 
286            solve nc supp
287
288--        | Abs _ _ <- a, Abs _ _ <- b = do
289--            let (s1, s2) = split2 supp
290--            let t = fresh (tk a) s1
291--            let dd= (Condition d (rall $ App a t) (rall $ App b t))
292--            putStrLn $ "Applying a fresh variable: "++(show t) ++"\n"++(show dd)
293--            solve1 s2 dd
294--        | AAbs _ _ _ <- a, Abs  _ _   <- b = applyList a b d supp
295--        | Abs  _ _   <- a, AAbs _ _ _ <- b = applyList a b d supp
296--        | AAbs _ _ _ <- a, AAbs _ _ _ <- b = applyList a b d supp
297
298--        | Just dd <- reorder d = do
299--            putStrLn $ "Reorder " ++ show dd
300--            solve1 supp $ Condition dd a b
301        | otherwise = do
302            putStrLn "Tying to call solver"
303            let x = compiletosolver a b d
304            y <- SBV.prove x
305            print y
306            case y of
307                (SBV.ThmResult (SBV.Unsatisfiable _)) -> return []
308                otherwise -> return [c]
309
310data LU = LU deriving (Eq, Ord, Data, Typeable)
311instance SBV.SymWord LU
312instance SBV.HasKind LU
313
314fvc (Zero a)  = fv a
315fvc (LTC a b) = fv a `Set.union` fv b
316fvc (GEC a b) = fv a `Set.union` fv b
317
318compiletosolver :: L -> L -> [Constraint] -> SBV.Symbolic SBV.SBool
319compiletosolver a b d = do
320    varmap <- liftIO createVarPool
321    expmap <- liftIO createExpPool
322    supply  <- liftIO $ newNumSupply
323    let (s1,s2,s3,s4) = split4 supply
324    cs <- mapM (\(s,x) -> compilec varmap expmap s x) $ zip (split s1) d
325    mapM_ (SBV.constrain) cs
326    lhs <- compilel varmap expmap s3 a
327    rhs <- compilel varmap expmap s4 b
328    return $ lhs .== rhs
329
330data VarT = VarI | VarF VarT VarT
331type VarPool = IORef (Map.Map Int Dynamic)
332type ExpPool = IORef (Map.Map L SBV.SInteger)
333
334createVarPool :: IO (VarPool)
335createVarPool = newIORef $ Map.empty
336createExpPool :: IO (ExpPool)
337createExpPool = newIORef $ Map.empty
338
339
340sbvTc :: TyCon
341sbvTc = mkTyCon3 "Data" "SBV" "SBV"
342
343instance (Typeable t) => Typeable (SBV.SBV t) where
344  typeOf x = mkTyConApp sbvTc [typeOf (get x)]
345    where
346      get :: SBV.SBV a -> a
347      get = undefined
348
349
350getVarSymbol :: VarPool -> (SBV.Symbolic Dynamic) -> Int -> SBV.Symbolic Dynamic
351getVarSymbol pool factory a = do
352  v <- liftIO $ readIORef pool
353  case Map.lookup a v of
354    Just q -> return $ q
355    Nothing -> do
356      dx <- factory
357      let newmap = Map.insert a dx v
358      liftIO $ writeIORef pool newmap
359      return dx
360
361getExpSymbol :: ExpPool -> (SBV.Symbolic SBV.SInteger) -> L -> SBV.Symbolic SBV.SInteger
362getExpSymbol pool factory a = do
363  v <- liftIO $ readIORef pool
364  case Map.lookup a v of
365    Just q -> return $ q
366    Nothing -> do
367      dx <- factory
368      let newmap = Map.insert a dx v
369      liftIO $ writeIORef pool newmap
370      return dx
371
372
373compilec :: VarPool -> ExpPool -> Supply Int -> Constraint -> SBV.Symbolic (SBV.SBool)
374compilec v e s (Zero a)  = do
375  lhs <- compilel v e s a
376  return $ lhs .== (0::SBV.SInteger)
377
378compilec v e s (LTC a b) = do
379  let (s1,s2) = split2 s
380  lhs <- compilel v e s1 a
381  rhs <- compilel v e s2 b
382  return $ lhs .< rhs
383
384compilec v e s (GEC a b) = do
385  let (s1,s2) = split2 s
386  lhs <- compilel v e s1 a
387  rhs <- compilel v e s2 b
388  return $ lhs .>= rhs
389
390class Typeable a => VarFactory a where
391  createDyn :: String -> a -> SBV.Symbolic Dynamic
392  createDyn a n = do
393    x <- createVar a n
394    return $ toDyn x
395  createVar :: String -> a -> SBV.Symbolic a
396
397instance VarFactory SBV.SInteger where
398  createVar n _ = SBV.free n
399
400compilel :: VarPool -> ExpPool -> Supply Int -> L -> SBV.Symbolic (SBV.SInteger)
401compilel v e s (Op a c b) = do
402  let (s1, s2) = split2 s
403  al <- compilel v e s1 a
404  bl <- compilel v e s1 b
405  return $ case c of
406    '+' -> al + bl
407    '-' -> al - bl
408    '*' -> al * bl
409    '/' -> al `SBV.sDiv` bl
410compilel v e s (Var a)   = do
411  let itype = (undefined ::SBV.SInteger)
412  sym <- getVarSymbol v (createDyn (showVar a "") itype) a
413  let var = (fromDynamic sym) :: Maybe SBV.SInteger
414  case var of
415      Just x -> return x
416      Nothing -> do
417        error "Type Error"
418compilel v e s (Num a)   = return $ SBV.literal $ fromIntegral a
419compilel v e s (Bottom)  = SBV.free_
420compilel v e s l = do
421    sym <- getExpSymbol e (return $ SBV.uninterpret ("unint" ++ showVar (supplyValue s) "") ) l
422    return sym
423--compilel v e x         = error $  "Cannot compile "++ show x
424
425gettype :: ((b -> t) -> t) -> a -> b -> a
426gettype = error "???"
427
428{-
429compileapp :: (VarFactory b, SBV.Uninterpreted (b -> SBV.SInteger)) => VarPool -> L -> ((b -> t) -> t) -> SBV.Symbolic (SBV.SInteger)
430compileapp v (Var a) f = do
431  let itype = (error :: SBV.SInteger)
432  sym <- getVarSymbol v (createDyn (showVar a "") (gettype f itype)) a
433  let var = (fromDynamic sym) :: Maybe SBV.SInteger
434  case var of
435      Just x -> return x
436      Nothing -> do
437        error "Type Error"
438-}
439compileapp v (App x y) t = error $ "Not yet implemented."
440
Note: See TracBrowser for help on using the repository browser.