source: sizechecking/Constraints.hs @ 14

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

removing some debug

File size: 12.1 KB
Line 
1{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances,
2             IncoherentInstances, RankNTypes, ScopedTypeVariables,
3             FlexibleContexts,UndecidableInstances #-}
4module Constraints where
5
6import Lambda
7import qualified Data.List as List
8import qualified Data.Set as Set
9import qualified Data.Map as Map
10import qualified Data.Ord as Ord
11import qualified Data.SBV as SBV
12import Data.SBV ( (.==), (.<), (.>=))
13import Control.Monad
14import Data.IORef()
15import Data.Supply as S
16
17asType :: a -> a -> a
18asType a _ = a
19
20data D = D { var::Int, cond::[Condition] } 
21
22data TypeKind = V | L TypeKind | F TypeKind TypeKind | U
23    deriving Show
24
25
26class TS a where
27    tk :: a -> TypeKind
28instance (TS a, TS b) => TS (a -> b) where
29    tk _ = F (tk (undefined :: a)) (tk (undefined :: b))
30instance TS a => TS [a] where
31    tk _ = L (tk (undefined :: a))
32instance TS a where
33    tk _ = V
34instance TS Int where
35    tk _ = U
36
37appall :: Int -> [L] -> L
38appall var = foldl App (Var var)
39
40
41data Condition = Condition [Constraint] L L
42
43instance Show Condition where
44    showsPrec _ (Condition d a b) = shows d . showString "|- " . shows a . showString " = " . shows b
45    showList [] = showString ""
46    showList [x] = shows x
47    showList (x:xs) = shows x . showString "\n" . shows xs
48
49data Constraint = Zero L | LTC L L | GEC L L
50    deriving Eq
51
52instance Show Constraint where
53    showList []     = id
54    showList [s]    = shows s . showChar ' '
55    showList (x:xs) = shows x . showString ", " . shows xs
56    showsPrec _ (Zero s) = shows s . showString " = 0"
57    showsPrec _ (LTC s1 s2) = shows s1 . showString " < " . shows s2
58    showsPrec _ (GEC s1 s2) = shows s1 . showString " >= " . shows s2
59
60normalize :: L -> L
61normalize l = delzero $ foldl (\a b -> Op a '-' b) (foldl (\a b -> Op  a '+' b) (f1 $ List.sortBy (Ord.comparing snd) a) c) d
62    where
63    (a,b,c,d) = norm l
64    f1 ((0,l):xs) = f1 xs
65    f1 ((1,l):xs) = Op (f1 xs) '+' (Var l)
66    f1 ((-1,l):xs) = Op (f1 xs) '-' (Var l)
67    f1 [] = Num b
68
69    delzero (Op (Num 0) '+' b) = b
70    delzero (Op a c b) = Op (delzero a) c b
71    delzero l          = l
72
73gnormalize :: L -> (L, Int)
74gnormalize l = case (c,d) of
75        ([], []) -> case nonzero of
76            [] -> (Num 0, b)
77            _  -> (expr, b)
78        (_, _)   -> error $ "Expression in condition" ++ show c
79    where
80    nonzero = List.sortBy (Ord.comparing snd) $ filter ((/=0).fst) a
81    proc (1, l) = Var l
82    proc (-1, l) = Op (Num (-1)) '*' (Var l)
83    t :: L -> (Int, Int) -> L
84    t l (1, var) = Op l '+' (Var var)
85    t l (-1, var) = Op l '-' (Var var)
86    expr = foldl t (proc $ head nonzero) (tail nonzero)
87
88    (a,b,c,d) = norm l
89
90normalizec :: Constraint -> Constraint
91normalizec (Zero l) = Zero $ normalize l
92normalizec (LTC a b) = LTC (normalize a) (normalize b)
93normalizec (GEC a b) = GEC (normalize a) (normalize b)
94--normalizec (LTC a b) = LTC x (Num (-y))
95--    where (x,y) = gnormalize $ Op a '-' b
96--normalizec (GEC a b) = GEC x (Num (-y))
97--    where (x,y) = gnormalize $ Op a '-' b
98
99normalizecs :: [Constraint] -> [Constraint]
100normalizecs = normalizecs' . Prelude.map normalizec
101    where
102    normalizecs' [] = []
103    normalizecs' (x:xs) = x:normalizecs' (filter (/=x) xs)
104
105{-
106 - Takes an extended lambda expression and
107 -}
108norm :: L -> ([(Int, Int)], Int, [L], [L])
109norm (App a b)     = ([], 0, [App (normalize a) (normalize b)], [])
110norm (List a b)    = ([], 0, [List (normalize a) (normalize b)], [])
111norm (AAbs a b e)  = ([], 0, [AAbs a b (normalize e)], [])
112norm (Shift a b c) = ([], 0, [Shift (normalize a) (normalize b) (normalize c)], [])
113norm (Unsized)     = ([], 0, [Unsized], [])
114norm (Bottom)      = ([], 0, [Bottom], [])
115norm (Abs i l)     = ([], 0, [Abs i $ normalize l], [])
116norm (Var i)       = ([(1, i)], 0, [], [])
117norm (Num i)       = ([], i, [], [])
118norm q@(Op a c b)  = case c of
119    '+' -> (a1++b1, a2+b2, a3++b3, a4++b4)
120    '-' -> (sub a1 b1, a2-b2, a3++b4, a4++b3)
121    '*' -> case a of
122            (Num cnt) -> (map (mul cnt) b1, cnt*b2, map (Op (Num cnt) '*') b3, map (Op (Num cnt) '*') b4)
123            _         -> ([], 0, [q], [])
124    _   -> ([], 0, [q], [])
125    where
126        mul c (x,var) = (c*x, var)
127        (a1, a2, a3, a4) = norm a
128        (b1, b2, b3, b4) = norm b
129        sub l1 ((c,i):xs) = sub (sub' l1 c i) xs
130            where
131            sub' [] c i = [(-c, i)]
132            sub' ((cc,ii):xs) c i = if i==ii then (cc-c,i):xs else (cc,ii):sub' xs c i
133        sub l1 [] = l1
134
135tnorm = Op (Num 1) '+' (Op (Var 0) '-' (Num 1))
136
137checkCond :: Supply Int -> [Condition] -> IO [Condition]
138checkCond v l = do
139    ll <- mapM (checkCond1 v) l
140    return $ concat ll
141
142    where
143--    checkCond1 v p@(Condition d a b) | a==b = do
144--        return  []
145    checkCond1 v z@(Condition d (List a b) (List p q)) = do
146--        i <- freshtypevar v
147        let (v1,v2,v3) = split3 v
148        let i = supplyValue v1
149        let b' = rall $ App b (Var i)
150        let q' = rall $ App q (Var i)
151        l1 <- checkCond1 v2 (Condition ((Var i `GEC` Num 0):d) a p) 
152        l2 <- checkCond1 v3 (Condition ((Var i `GEC` Num 0):(Var i `LTC` a):(Var i `LTC` p):d) b' q')
153        return $ l1++l2
154    checkCond1 v z@(Condition d (App (Shift e f g) h) x) = do
155        let (v1,v2,v3) = split3 v
156        let e' = rall $ App e h
157        let g' = rall $ App g $ Op h '-' f
158        l1 <- checkCond1 v1 (Condition ((h `LTC` f):d) e' x)
159        l2 <- checkCond1 v2 (Condition ((h `GEC` f):d) g' x)
160--        putStrLn $ " -> " ++ show l1
161--        putStrLn $ " -> " ++ show l2
162        return $ l1 ++ l2
163    checkCond1 v z@(Condition d (App (Var a) x) (App (Var b) y)) | a==b =
164        checkCond1 v (Condition d x y)
165    checkCond1 v p@(Condition d x z@(App (Shift e f g) h)) =
166        checkCond1 v (Condition d z x)
167    checkCond1 v z@(Condition d a b) = return [Condition dd (normalize a) (normalize b)]
168        where
169        dd = normalizecs d
170
171subst ndl hst (App a b)     = App (subst ndl hst a) (subst ndl hst b)
172subst ndl hst (List a b)    = List (subst ndl hst a) (subst ndl hst b)
173subst ndl hst (AAbs a b e)  = AAbs a b (subst ndl hst e)
174subst ndl hst (Shift a b c) = Shift (subst ndl hst a) (subst ndl hst b) (subst ndl hst c)
175subst ndl hst (Unsized)     = Unsized
176subst ndl hst (Bottom)      = Bottom
177subst ndl hst q@(Abs i l)   = if ndl==i then q else Abs i $ subst ndl hst l
178subst ndl hst q@(Var i)     = if ndl==i then hst else q
179subst ndl hst (Num i)       = Num i
180subst ndl hst (Op a c b)    = Op (subst ndl hst a) c (subst ndl hst b)
181
182substc ndl hst (Zero l)  = Zero $ subst ndl hst l
183substc ndl hst (LTC a b) = LTC (subst ndl hst a) (subst ndl hst b)
184substc ndl hst (GEC a b) = GEC (subst ndl hst a) (subst ndl hst b)
185
186reorder cs = if any check cs
187        then Just (map r cs)
188        else Nothing
189    where
190    check (Zero _)        = False
191    check (LTC a (Num 0)) = False 
192    check (GEC a (Num 0)) = False 
193    check _               = True
194    r (LTC a b) = LTC (normalize (Op a '-' b)) (Num 0)
195    r (GEC a b) = GEC (normalize (Op a '-' b)) (Num 0)
196    r l         = l
197
198solve :: [Condition] -> Supply Int -> IO [Condition]
199solve l supply = do
200    ll <- forM (zip l $ split supply) (\(c,s) -> do
201        putStrLn $ "\nSOLVING " ++ show c
202        solve1 s c
203        )
204    return $ concat ll
205    where
206
207    searchzero (Zero (Var a):xs) = Just (a,xs)
208    searchzero (x:xs)            = do
209        (a,l) <- searchzero xs
210        return (a,x:l)
211    searchzero []                = Nothing
212
213
214    searcheq (q@(GEC (Var var) exp):xs) prev = case findeq (List.reverse prev ++ xs) [] of
215            Nothing -> searcheq xs (q:prev)
216            l       -> l
217        where
218        expinc = normalize $ Op exp '+' $ Num 1
219        findeq []                       _     = Nothing
220        findeq (LTC (Var var2) exp2:xs) prev2 | var==var2 && exp2==expinc = Just (var, exp, List.reverse prev2 ++ xs)
221        findeq (x:xs)                   prev2 = findeq xs (x:prev2)
222
223    searcheq (x:xs)                 prev = searcheq xs (x:prev) 
224    searcheq []                     _    = Nothing
225
226    checkConds [] = False
227    checkConds (LTC a b : xs) | GEC a b `elem` xs            = True
228    checkConds (GEC a b : xs) | LTC a b `elem` xs            = True
229    checkConds (LTC a (Num b) : xs) | b<=0 && elem (Zero a) xs = True
230    checkConds (GEC a (Num b) : xs) | b>0  && elem (Zero a) xs = True
231    checkConds (_:xs) = checkConds xs
232
233    checkConds2 (LTC (Num a) (Num b):xs) | a>=b = Nothing
234    checkConds2 (LTC (Num a) (Num b):xs) | a<= checkConds2 xs
235    checkConds2 (GEC (Num a) (Num b):xs) | a<= Nothing
236    checkConds2 (GEC (Num a) (Num b):xs) | a>=b = checkConds2 xs
237    checkConds2 (x:xs)                          = do { y <- checkConds2 xs; return (x:y) }
238    checkConds2 []                              = Just []
239
240--    applyList a b d supp = do
241--        let (s1,s2,s3) = split3 supp
242--        let t = fresh (L V) s1
243--        let dd = (Condition d (rall $ App a t) (rall $ App b t))
244--        putStrLn $ "Applying a fresh variable: "++(show t) ++"\n"++(show dd)
245--        x <- checkCond s2 [dd] >>= mapM (solve1 s3)
246--        return $ concat x
247
248    solve1  supp c@(Condition d a b) = case checkConds2 d of
249        Nothing -> do
250            putStrLn "Contradiction in preconditions"
251            return []
252        Just d' -> solve1' supp $ Condition d a b
253
254    solve1' supp c@(Condition d a b)
255        | checkConds d = do
256            putStrLn "Contradiction in preconditions"
257            return []
258        | a==b = do
259            putStrLn "Equals"
260            return []
261        | Just (var, nl) <- searchzero d = do
262            let x = Condition (Prelude.map (normalizec.substc var (Num 0)) nl)
263                        (normalize$subst var (Num 0) a)
264                        (normalize$subst var (Num 0) b)
265
266            putStrLn $ show (Var var) ++ " is zero:\n" ++ show x
267            solve1 supp x
268        | Just (var, exp, nl) <- searcheq d [] = do
269            putStrLn $ "Found equation " ++ show (Var var) ++ " = " ++ show exp
270            let x = Condition (Prelude.map (normalizec.substc var exp) nl )
271                        (normalize$subst var exp a)
272                        (normalize$subst var exp b)
273            putStrLn $ "New equations:\n" ++ show x
274            solve1 supp x
275        | App p q <- a, App r s <- b = do
276            putStrLn "Branching!"
277            nc <- checkCond supp [Condition d p r, Condition d q s] 
278            solve nc supp
279
280
281--        | Abs _ _ <- a, Abs _ _ <- b = do
282--            let (s1, s2) = split2 supp
283--            let t = fresh (tk a) s1
284--            let dd= (Condition d (rall $ App a t) (rall $ App b t))
285--            putStrLn $ "Applying a fresh variable: "++(show t) ++"\n"++(show dd)
286--            solve1 s2 dd
287--        | AAbs _ _ _ <- a, Abs  _ _   <- b = applyList a b d supp
288--        | Abs  _ _   <- a, AAbs _ _ _ <- b = applyList a b d supp
289--        | AAbs _ _ _ <- a, AAbs _ _ _ <- b = applyList a b d supp
290        | Just dd <- reorder d = do
291            putStrLn $ "Reorder " ++ show dd
292            solve1 supp $ Condition dd a b
293        | otherwise = do
294            putStrLn "Tying to call solver"
295            let x = compiletosolver a b d
296            y <- SBV.prove x
297            print y
298            case y of
299                (SBV.ThmResult (SBV.Unsatisfiable _)) -> return []
300                otherwise -> return [c]
301
302fvc (Zero a)  = fv a
303fvc (LTC a b) = fv a `Set.union` fv b
304fvc (GEC a b) = fv a `Set.union` fv b
305
306compiletosolver :: L -> L -> [Constraint] -> SBV.Symbolic SBV.SBool
307compiletosolver a b d = do
308    let fvs = Set.toList $ Set.unions $ fv a : fv b : map fvc d
309    (vars::[SBV.SInteger]) <- mapM (SBV.free . flip showVar "") fvs
310    let varmap = Map.fromList $ zip fvs vars
311    mapM_ (SBV.constrain . compilec varmap) d
312    return $ compilel varmap a .== compilel varmap b
313
314compilec v (Zero a)  = compilel v a .== (0::SBV.SInteger)
315compilec v (LTC a b) = compilel v a .<  compilel v b
316compilec v (GEC a b) = compilel v a .>= compilel v b
317
318compilel :: Map.Map Int SBV.SInteger -> L -> SBV.SInteger
319compilel v (Op a c b) = case c of 
320    '+' -> al + bl
321    '-' -> al - bl
322    '*' -> al * bl
323    '/' -> al `SBV.sDiv` bl
324    where
325    al = compilel v a
326    bl = compilel v b
327compilel v (Var a) | Just x<-Map.lookup a v = x
328compilel v (Num a) = SBV.literal $ fromIntegral a
329compilel v a = error $ "Cannot compile " ++ show a
Note: See TracBrowser for help on using the repository browser.