source: sizechecking/Constraints.hs @ 16

Last change on this file since 16 was 15, checked in by gobi, 13 years ago

new solver

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