vertexenum-0.1.1.0: src/Geometry/VertexEnum/Internal.hs
module Geometry.VertexEnum.Internal
( normalizeConstraints
, varsOfConstraint
, iPoint )
where
import Data.IntMap.Strict ( IntMap, mergeWithKey )
import qualified Data.IntMap.Strict as IM
import Data.List ( nub, union )
import Geometry.VertexEnum.Constraint ( Constraint (..), Sense (..) )
import Geometry.VertexEnum.LinearCombination ( LinearCombination (..), VarIndex )
import Numeric.LinearProgramming ( simplex,
Bound(Free, (:<=:)),
Constraints(Dense),
Optimization(Maximize),
Solution(
Undefined
, Feasible
, Infeasible
, NoFeasible
, Optimal
, Unbounded) )
normalizeLinearCombination ::
Num a => [VarIndex] -> LinearCombination a -> IntMap a
normalizeLinearCombination vars (LinearCombination lc) =
IM.union lc (IM.fromList [(i,0) | i <- vars `union` [0]])
varsOfLinearCombo :: LinearCombination a -> [VarIndex]
varsOfLinearCombo (LinearCombination imap) = IM.keys imap
varsOfConstraint :: Constraint a -> [VarIndex]
varsOfConstraint (Constraint lhs _ rhs) =
varsOfLinearCombo lhs `union` varsOfLinearCombo rhs
normalizeConstraint :: Real a => [VarIndex] -> Constraint a -> [Double]
normalizeConstraint vars (Constraint lhs sense rhs) =
if sense == Lt
then xs ++ [x]
else map negate xs ++ [-x]
where
lhs' = normalizeLinearCombination vars lhs
rhs' = normalizeLinearCombination vars rhs
coefs = IM.elems $ mergeWithKey (\_ a b -> Just (a-b)) id id lhs' rhs'
coefs' :: [Double]
coefs' = map realToFrac coefs
(x, xs) = case coefs' of
(xx:xxs) -> (xx, xxs)
[] -> (0, [])
-- let (x:xs) = map realToFrac $
-- IM.elems $ mergeWithKey (\_ a b -> Just (a-b)) id id lhs' rhs'
-- in
-- if sense == Lt
-- then xs ++ [x]
-- else map negate xs ++ [-x]
-- where lhs' = normalizeLinearCombination vars lhs
-- rhs' = normalizeLinearCombination vars rhs
normalizeConstraints :: Real a => [Constraint a] -> [[Double]] -- for qhalf
normalizeConstraints constraints =
map (normalizeConstraint vars) constraints
where
vars = nub $ concatMap varsOfConstraint constraints
inequality :: [Double] -> Bound [Double]
inequality row = (coeffs ++ [1.0]) :<=: bound
where
coeffs = init row
bound = -(last row)
inequalities :: [[Double]] -> Constraints
inequalities normConstraints = Dense (map inequality normConstraints)
iPoint :: [[Double]] -> [Double]
iPoint halfspacesMatrix = case solution of
Optimal (_, point) -> init point
Undefined -> error "Failed to find interior point (undefined)."
Feasible (_, _) -> error "Failed to find interior point (feasible)."
Infeasible (_, _) -> error "Failed to find interior point (infeasible)."
NoFeasible -> error "Failed to find interior point (no feasible)."
Unbounded -> error "Failed to find interior point (unbounded)."
where
constraints' = inequalities halfspacesMatrix
n = length (head halfspacesMatrix)
objective = Maximize (replicate (n-1) 0 ++ [1])
bounds = map Free [1 .. (n-1)]
solution = simplex objective constraints' bounds