Changeset 21
- Timestamp:
- 07/20/08 20:02:07 (2 years ago)
- Files:
-
- fort/IConstr.hs (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
fort/IConstr.hs
r20 r21 9 9 import Control.Monad.State 10 10 11 import Data.List (sortBy )11 import Data.List (sortBy,groupBy,nub) 12 12 import qualified Data.Map as Map 13 13 import Data.Maybe 14 14 import qualified Data.Set as Set 15 15 16 import Debug.Trace 17 16 18 ------------------------------------------------------------------------------- 17 19 -- Helpers. … … 22 24 sortBySnd list = sortBy (\(_,a) (_,b) -> compare a b) list 23 25 24 type Coef = Rational26 type Coef = Integer 25 27 type MAP k a = Map.Map k a 26 28 … … 30 32 data Vec v = 31 33 Vec (MAP v Coef) Coef -- a set of v*coef and constant. 32 deriving Show 34 deriving (Eq,Show) 35 36 vec vcs co = foldr vecPlus (vecC co) $ map (uncurry vecCV) vcs 33 37 34 38 vecC = Vec Map.empty … … 65 69 vecDelVar v (Vec vcs c) = Vec (Map.delete v vcs) c 66 70 71 vecDivBy (Vec vcs co) gcd = Vec (Map.map (`div` gcd) vcs) (div co gcd) 72 73 vecCoefsGCD (Vec vcs co) = case coefs of 74 [] -> abs co 75 xs -> foldr gcd (abs co) xs 76 where 77 coefs = Map.elems vcs 78 67 79 vecDef vec@(Vec vcs c) = case Map.toList vcs of 68 80 [] -> Nothing 69 ((v,c):_) -> Just (v,vecScale (negate (1/c)) $ vecDelVar v vec) 70 71 vecSubstVar v def vec@(Vec vcs c) = vecMinus vec $ vecScale vc def 81 ((v,c):_) -> Just ((abs c,v),vecScale (negate $ signum c) $ vecReduceGCD $ vecDelVar v vec) 82 83 vecDefVar v vec@(Vec vcs c) = case Map.lookup v vcs of 84 Nothing -> Nothing 85 Just c -> Just ((abs c,v),vecScale (negate $ signum c) $ vecReduceGCD $ vecDelVar v vec) 86 87 vecReduceGCD vec 88 | gcd /= 0 = vecDivBy vec gcd 89 | otherwise = vec 90 where 91 gcd = vecCoefsGCD vec 92 93 vecVarCoef v (Vec vcs _) = maybe 0 id (Map.lookup v vcs) 94 95 vecSubstVar c v def vec@(Vec vcs _) = vecReduceGCD $ vecPlus (vecScale c $ vecDelVar v vec) (vecScale vc def) 72 96 where 73 97 vc = Map.findWithDefault 0 v vcs … … 76 100 ((v,c):_) -> (v,c) 77 101 _ -> error "vecHeadVar: constant vector." 102 103 vecVars (Vec vcs _) = Map.keys vcs 104 105 vecHasVar v vec@(Vec vcs _) = fmap (\c -> (c,v,vecReduceGCD $ vecScale (negate $ signum c) $ vecDelVar v vec)) $ Map.lookup v vcs 78 106 79 107 -------------------------------------------------------------------------------- … … 112 140 HiBound x -> HiBound (x*c) 113 141 PInf -> PInf 114 142 143 -------------------------------------------------------------------------------- 144 -- Inequalities. 145 146 data Rel = LE | GE deriving (Eq, Ord, Show) 115 147 116 148 -------------------------------------------------------------------------------- … … 118 150 119 151 data SolverS v = SolverS { 120 ssDefs :: [(v,Vec v)] 152 ssDefs :: [((Coef,v),Vec v)] 153 -- result of FM elim. 154 -- ((A,x),(u,v)) means that max u<=Ax<=min v 155 ,ssRanges :: [((Coef,v),([Vec v],[Vec v]))] 121 156 ,ssEqs :: [Vec v] 122 ,ssIneqs :: [(Vec v,R ange Coef)]157 ,ssIneqs :: [(Vec v,Rel)] -- vec >= 0 or vec <= 0. 123 158 } 124 159 deriving Show 125 160 126 emptySolverS = SolverS [] [] [] 161 emptySolverS = SolverS [] [] [] [] 127 162 128 163 type SolverM v a = StateT (SolverS v) [] a 129 164 130 runSolver :: Ord v=> SolverM v a -> [((),SolverS v)]165 runSolver :: (Show v, Ord v) => SolverM v a -> [((),SolverS v)] 131 166 runSolver problem = runStateT (problem >> solve) emptySolverS 132 167 … … 143 178 -- Solution process. 144 179 145 solve :: Ord v=> SolverM v ()180 solve :: (Show v, Ord v) => SolverM v () 146 181 solve = do 147 182 checkEqs -- we have to checkEqs once at start. … … 149 184 removeEqs 150 185 -- then we ought to check and combine inequalities. 151 checkCombineInequalities186 removeIneqVars 152 187 -- and restore ranges. 153 188 return () 154 189 155 removeEqs :: Ord v => SolverM v () 190 -------------------------------------------------------------------------------- 191 -- Dealing with equalities. 192 193 removeEqs :: (Show v, Ord v) => SolverM v () 156 194 removeEqs = do 157 195 ss <- getSS … … 159 197 [] -> return () 160 198 (eq:_) -> let 161 def = createDef eq199 def = trace ("creating def from "++show eq) $ createDef eq 162 200 in do 163 addDef def 201 trace ("adding def "++show def) $ addDef def 202 checkEqs 164 203 removeEqs 165 204 where … … 184 223 addDef def = do 185 224 ss <- getSS 186 let ss' = ss {225 let ss' = trace ("ss before removal: "++show ss) $ ss { 187 226 ssDefs = (def:) $ removeDef def snd (\(v,_) vec' -> (v,vec')) $ ssDefs ss 188 227 ,ssEqs = removeDef def id (flip const) $ ssEqs ss 189 228 ,ssIneqs = removeDef def fst (\(_,r) vec -> (vec,r)) $ ssIneqs ss 190 229 } 191 putSS ss' 192 193 removeDef (v,defVec) get chg list = map (\x -> chg x $ vecSubstVar v defVec (get x)) list 194 195 checkCombineInequalities :: Ord v => SolverM v () 196 checkCombineInequalities = do 197 ss <- getSS 198 failMultiVar $ ssIneqs ss 199 let nIneqs = map normIneq $ ssIneqs ss 200 error "We should group normalized inequalities and tighten them and check contradiction." 201 putSS $ ss { ssIneqs = nIneqs } 202 where 203 normIneq (vec,r) = (vecScale m vecMinusCo, rangeScale m rMinusCo) 230 trace ("putting ss after def removal: "++show ss') $ putSS ss' 231 232 removeDef ((c,v),defVec) get chg list = map (\x -> chg x $ vecSubstVar c v defVec (get x)) list 233 234 eq = vecPlus (vecMinus (vecV "i") (vecV "i1")) (vecV "n") 235 tt = removeDef ((1,"i"),vecMinus (vecV "i1") (vecV "n")) id (flip const) [eq] 236 237 -------------------------------------------------------------------------------- 238 -- Dealing with inequalities (Fourier-Motzkin). 239 240 removeIneqVars :: Ord v => SolverM v () 241 removeIneqVars = do 242 checkIneqs 243 ss <- getSS 244 case selectVar $ ssIneqs ss of 245 Just ((c,v),(lows,highs),ineqs) -> do 246 let add = [ (vecMinus l h,LE) | l <- lows, h <- highs] 247 let rng = ((c,v),(lows,highs)) 248 putSS $ ss { 249 ssRanges = rng : ssRanges ss 250 ,ssIneqs = ineqs ++ add 251 } 252 removeIneqVars 253 Nothing -> return () 254 255 checkIneqs = do 256 ss <- getSS 257 let ies = ssIneqs ss 258 ies' <- mapM checkIE ies 259 putSS $ ss { ssIneqs = concat ies' } 260 where 261 checkIE ie@(vec,rel) 262 | Just c <- vecIsConst vec = 263 if contradict c rel then failSS else return [] 264 | otherwise = return [ie] 265 contradict c LE = c > 0 266 contradict c GE = c < 0 267 268 selectVar ineqs = case allGroups of 269 [] -> Nothing 270 (r:_) -> Just r 271 where 272 allVars = nub $ concatMap (vecVars . fst) ineqs 273 allGroups = filter nonEmpty $ map group' allVars 274 nonEmpty (_,(h,l),_) = not (null h) && not (null l) 275 group' var = group [] [] [] [] var ineqs 276 group coefs lows highs ineqs var [] = ((m,var),(map scl lows,map scl highs),ineqs) 204 277 where 205 co = vecConst vec 206 vecMinusCo = vecMinus vec (vecC co) 207 rMinusCo = rangeSubConst r co 208 (v,c) = vecHeadVar vec 209 m = signum c 210 failMultiVar [] = return () 211 failMultiVar ((v,r):vrs) 212 | vecNumVars v > 1 = failSS 213 | otherwise = failMultiVar vrs 278 m = foldr lcm 1 coefs 279 scl (c,def) = vecScale (div m c) def 280 group coefs lows highs ineqs var (ie@(vec,rel):ies) 281 | Just (c,v,def) <- vecHasVar var vec = let 282 (c',lows',highs') = selectRel c def 283 in group (c':coefs) lows' highs' ineqs var ies 284 | otherwise = group coefs lows highs (ie:ineqs) var ies 285 where 286 negateRel c rel 287 | c < 0 = (abs c,invRel) 288 | otherwise = (c,rel) 289 where 290 invRel = case rel of 291 LE -> GE 292 GE -> LE 293 selectRel c def = case rel' of 294 -- cx<=0+def. Adding def to highs. 295 LE -> (c',lows,(c,def):highs) 296 -- vice versa. 297 GE -> (c',(c,def):lows,highs) 298 where 299 (c',rel') = negateRel c rel 300 301 tv1 = Vec (Map.fromList [("i",1),("i1",2)]) 4 302 tv2 = Vec (Map.fromList [("i",-1),("i1",2)]) 4 303 304 ties1 = [ 305 (vec [(1,"i")] (-1),GE) 306 ,(vecMinus (vecV "i") (vecV "n"), LE) 307 ] 308 309 -- SolverS {ssDefs = [((1,"i"),Vec (fromList [("i1",1),("n",-1)]) 0)], ssRanges = [], ssEqs = [Vec (fromList []) 0], ssIneqs = [(Vec (fromList [("n",-1)]) 1,LE),(Vec (fromList [("i1",1),("n",-1)]) 0,LE),(Vec (fromList [("i1",-1)]) 1,LE),(Vec (fromList [("i1",1),("n",-2)]) 0,LE),(Vec (fromList [("i1",-1),("n",1)]) 1,LE)]} 310 ties2 = [(Vec (Map.fromList [("i1",1),("n",-1)]) 0,LE),(Vec (Map.fromList [("i1",-1)]) 1,LE),(Vec (Map.fromList [("i1",1),("n",-2)]) 0,LE),(Vec (Map.fromList [("i1",-1),("n",1)]) 1,LE)] 311 -------------------------------------------------------------------------------- 312 -- Building a problem. 313 314 insertIE a rel b = do 315 ss <- getSS 316 putSS $ ss { ssIneqs = (vecMinus a b,rel):ssIneqs ss } 317 318 insertEQ a b = do 319 ss <- getSS 320 putSS $ ss { ssEqs = vecMinus a b:ssEqs ss } 321 322 between x lo hi = do 323 insertIE lo LE x 324 insertIE x LE hi 325 326 betweens xs lo hi = do 327 mapM (\x -> between x lo hi) xs 328 return () 329 330 -- check solutions for (do i=1,n { a[i+n] = a[i]}) problem. 331 tprob1 = do 332 let [i,i1,n] = map vecV ["i","i1","n"] 333 let one = vecC 1 334 betweens [i,i1] one n 335 -- insertIE (vecPlus one i) LE i1 336 insertEQ (vecPlus i n) i1 214 337 215 338 --------------------------------------------------------------------------------
