limp-0.3.2.0: src/Numeric/Limp/Canon/Analyse/Constants.hs
-- | Analyse a program to find all constants
module Numeric.Limp.Canon.Analyse.Constants where
import Numeric.Limp.Canon.Program
import Numeric.Limp.Rep
import Numeric.Limp.Error
import qualified Data.Map as M
-- | Find the constants in a program, only by looking at the bounds with lo==up.
-- (See "Numeric.Limp.Canon.Simplify.Stride" to convert constraints to bounds)
constantsProgram :: (Ord z, Ord r, Rep c) => Program z r c -> Either Infeasible (Assignment z r c)
constantsProgram p
= mkAss $ concatMap eq $ M.toList $ _bounds p
where
eq (var, (Just lo, Just up))
| lo == up
= [(var, lo)]
eq _
= []
mkAss ms
= do zs <- mapM tkLeft ms
rs <- mapM tkRight ms
return $ Assignment (M.fromList $ concat zs)
(M.fromList $ concat rs)
tkLeft (Left z, v)
-- Wow! What if the bounds aren't integral?
-- Well, I guess the ILP solver will eventually figure out it's infeasible.
-- Maybe it would be nice to trigger that error here.
| v /= (fromZ $ truncate v)
= Left InfeasibleNotIntegral
| otherwise
= return [(z, truncate v)]
tkLeft _
= return []
tkRight (Right r, v)
= return [(r, v)]
tkRight _
= return []