Skip to content

Commit 4a5579f

Browse files
committed
wip
1 parent 834d2ed commit 4a5579f

File tree

12 files changed

+215
-81
lines changed

12 files changed

+215
-81
lines changed

src/Comparison/Types.hs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
-- License : BSD-3
66
-- Maintainer : jrasheed178@gmail.com
77
-- Stability : experimental
8-
module Comparison.Types where
8+
module Comparison.Types
9+
( MixedComparison (..),
10+
getLHS,
11+
getRHS,
12+
)
13+
where
914

1015
import Control.Applicative (liftA2)
1116
import Foreign.C.Types (CBool)
@@ -18,21 +23,27 @@ data MixedComparison a b = a :<= b | a :>= b | a :== b
1823
instance (Arbitrary a, Arbitrary b) => Arbitrary (MixedComparison a b) where
1924
arbitrary =
2025
oneof
21-
[ liftA2 (:<=) arbitrary arbitrary
22-
, liftA2 (:>=) arbitrary arbitrary
23-
, liftA2 (:==) arbitrary arbitrary
26+
[ liftA2 (:<=) arbitrary arbitrary,
27+
liftA2 (:>=) arbitrary arbitrary,
28+
liftA2 (:==) arbitrary arbitrary
2429
]
2530

26-
getMixedComparisonLHS :: MixedComparison a b -> a
27-
getMixedComparisonLHS (a :<= _) = a
28-
getMixedComparisonLHS (a :>= _) = a
29-
getMixedComparisonLHS (a :== _) = a
31+
getLHS :: MixedComparison a b -> a
32+
getLHS (a :<= _) = a
33+
getLHS (a :>= _) = a
34+
getLHS (a :== _) = a
3035

31-
getMixedComparisonRHS :: MixedComparison a b -> b
32-
getMixedComparisonRHS (_ :<= b) = b
33-
getMixedComparisonRHS (_ :>= b) = b
34-
getMixedComparisonRHS (_ :== b) = b
36+
getRHS :: MixedComparison a b -> b
37+
getRHS (_ :<= b) = b
38+
getRHS (_ :>= b) = b
39+
getRHS (_ :== b) = b
3540

41+
{- Using a class here and staying 'generic' (as in, be permissive on allowed
42+
types) is awkward. I think it's simpler to just stick with the data type.
43+
If we want a class, how do we best define the comparison ops? We'd need a way
44+
for LhsType and RhsType to be compared. Maybe we can use something like
45+
MixedTypesNum, but that's going to take some work.
46+
-}
3647
class MixedComparison2 c where
3748
type LhsType c :: *
3849
type RhsType c :: *

src/Linear/Constraint/Types.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
-- Stability: experimental
88
module Linear.Constraint.Types where
99

10-
import Comparison.Types (MixedComparison)
10+
import Comparison.Types
11+
( MixedComparison,
12+
getLHS,
13+
getRHS,
14+
)
1115
import qualified Data.Set as Set
1216
import GHC.Generics (Generic)
1317
import Linear.Expr.Types (Expr)

src/Linear/Simplex/Solver/Types.hs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ module Linear.Simplex.Solver.Types where
33
import qualified Data.Map as Map
44
import GHC.Generics (Generic)
55
import Linear.Expr.Types (ExprVarsOnly)
6-
import Linear.System.Linear.Types (CanBeLinearSystem)
6+
import Linear.System.Linear.Types (LinearSystem)
77
import Linear.Var.Types (SimplexNum, Var)
8+
import Linear.SlackForm.Types (SlackForm)
9+
import System.Posix.Types (CMode)
810

911
data OptimisationDirection = Minimize | Maximize
1012
deriving (Show, Eq, GHC.Generics.Generic)
@@ -15,11 +17,64 @@ data Objective = Objective
1517
}
1618
deriving (Show, Eq, GHC.Generics.Generic)
1719

20+
-- TODO: Is it useful to include the system in the result?
1821
data Result = Result
22+
23+
-- TODO: Include the canonical form?
24+
data OptimisationResult = OptimisationResult
1925
{ varMap :: Map.Map Var SimplexNum
2026
, objVal :: SimplexNum
2127
}
2228
deriving (Show, Read, Eq, GHC.Generics.Generic)
2329

24-
class (CanBeLinearSystem s) => Solver s where
25-
solve :: s -> Objective -> Result
30+
-- class (CanBeLinearSystem s) => Solver s where
31+
-- solve :: s -> Objective -> Result
32+
class TwoPhaseSolver inputSystem where
33+
firstPhase :: inputSystem -> Maybe SlackForm
34+
35+
twoPhaseSolve :: inputSystem -> Objective -> Maybe OptimisationResult
36+
twoPhaseSolve inputSystem obj =
37+
let mSf = firstPhase inputSystem
38+
in case mSf of
39+
Nothing -> Nothing
40+
Just sf -> Just $ systemResult $ secondPhase obj sf
41+
where
42+
secondPhase :: Objective -> SlackForm -> SlackForm
43+
secondPhase = undefined
44+
45+
-- This will probably be a proper function
46+
systemResult :: SlackForm -> OptimisationResult
47+
systemResult = undefined
48+
49+
class CanBeStandardForm problem where
50+
findSolution :: problem -> Maybe SlackForm
51+
52+
-- solveStandardForm :: StandardForm -> Objective -> Maybe Result
53+
54+
class LinearSystemProcessor s where
55+
type System s :: *
56+
57+
data FeasibleSystem = FeasibleSystem
58+
{ varVals :: Map.Map Var SimplexNum
59+
, system :: LinearSystem
60+
}
61+
62+
data Model = Model { model :: Map.Map Var SimplexNum }
63+
64+
data SatResult model = Unsat | Sat model
65+
66+
-- s is a system
67+
class (Monad (SatSolverMonad s)) => SatSolver s where
68+
type SatSolverOptions s :: *
69+
type SatSolverMonad s :: * -> *
70+
71+
solve :: SatSolverOptions s -> s -> (SatSolverMonad s) (SatResult Model)
72+
73+
class (Monad (OptSolverMonad s)) => OptSolver s where
74+
type OptSolverOptions s :: *
75+
type OptSolverMonad s :: * -> *
76+
77+
optimise :: OptSolverOptions s -> s -> Objective -> (OptSolverMonad s) (SatResult Model)
78+
79+
-- class (CanBeLinearSystem s) => Solver2 s where
80+
-- solve2 :: s -> Objective -> Result

src/Linear/SlackForm/Types.hs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,48 @@ module Linear.SlackForm.Types where
1010
import qualified Data.Set as Set
1111
import GHC.Generics (Generic)
1212
import Linear.Constraint.Linear.Types (LinearEquation (..))
13-
import Linear.Expr.Types (ExprVarsOnly)
13+
import Linear.Expr.Types (ExprVarsOnly, Expr)
1414
import Linear.Expr.Util (exprVarsOnlyVars)
1515
import Linear.System.Linear.Types (LinearSystem (..))
1616
import Linear.System.Simple.Types
1717
import Linear.Var.Types (SimplexNum, Var)
18+
import qualified Data.Map as Map
1819

1920
-- Expr == SimplexNum
2021
-- TODO: think about a better name for this type, CanonicalForm?
22+
-- TODO: Rename decision: StandardForm? Or, AugmentedForm
23+
-- https://en.wikipedia.org/wiki/Linear_programming#Augmented_form_(slack_form)
2124
data SlackForm = SlackForm
22-
{ maxObjective :: ExprVarsOnly
23-
, constraints :: LinearSystem
24-
, vars :: Set.Set Var -- all vars are non-negative
25+
{ constraints :: LinearSystem
26+
, originalVars :: Set.Set Var -- all vars are non-negative
27+
, slackVars :: Set.Set Var -- all vars are non-negative
28+
, artificialVarsMap :: Map.Map Var Expr -- all vars are non-negative
29+
-- , articialVars :: Set.Set Var -- all vars are non-negative
30+
-- , systemVars :: Set.Set Var -- all vars are non-negative
2531
}
2632
deriving (Show, Eq, Read, Generic)
2733

28-
class CanBeSlackForm a where
29-
toSlackForm :: a -> ExprVarsOnly -> SlackForm
34+
-- data CanonicalForm = CanonicalForm
35+
-- { maxObjective :: ExprVarsOnly
36+
-- , slackForm :: SlackForm
37+
-- }
38+
-- deriving (Show, Eq, Read, Generic)
3039

31-
instance CanBeSlackForm LinearSystem where
32-
toSlackForm ls obj =
33-
SlackForm
34-
obj
35-
ls
36-
(Set.unions $ map (exprVarsOnlyVars . lhs) ls.unLinearSystem)
40+
data CanonicalForm = CanonicalForm
41+
{ constraints :: LinearSystem
42+
, originalVars :: Set.Set Var
43+
, systemVars :: Set.Set Var
44+
, systemSlackVars :: Set.Set Var -- all vars are non-negative
45+
, eliminatedVarsMap :: Map.Map Var Expr
46+
}
47+
deriving (Show, Eq, Read, Generic)
48+
49+
-- class CanBeSlackForm a where
50+
-- toSlackForm :: a -> ExprVarsOnly -> SlackForm
51+
52+
-- instance CanBeSlackForm LinearSystem where
53+
-- toSlackForm ls obj =
54+
-- SlackForm
55+
-- obj
56+
-- ls
57+
-- (Set.unions $ map (exprVarsOnlyVars . lhs) ls.unLinearSystem)

src/Linear/SlackForm/Util.hs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ import Linear.Term.Types
3333
, TermVarsOnly (..)
3434
)
3535
import Linear.Var.Types (Bounds (..), Var, VarBounds)
36+
import Linear.System.Simple.Util (deriveBounds)
37+
import Linear.SlackForm.Types (CanonicalForm(..), SlackForm (..))
38+
import qualified Data.Set as Set
3639

3740
-- | Eliminate non-zero lower bounds via substitution
3841
-- Return the system with the eliminated variables and a map of the eliminated variables to their equivalent expressions
@@ -72,8 +75,9 @@ eliminateNonZeroLowerBounds constraints eliminatedVarsMap = aux [] constraints.u
7275
-- Add slack variables...
7376
-- Second step here https://en.wikipedia.org/wiki/Simplex_algorithm#Standard_form
7477
-- Return system of equalities and the slack variables
75-
addSlackVariables :: SimpleSystem -> ([Var], LinearSystem)
76-
addSlackVariables constraints =
78+
-- TODO: [Var] should be a set
79+
addSlackVars :: SimpleSystem -> ([Var], LinearSystem)
80+
addSlackVars constraints =
7781
let nextAvailableVar = SST.nextAvailableVar constraints
7882
in aux constraints.unSimpleSystem nextAvailableVar []
7983
where
@@ -134,3 +138,35 @@ eliminateUnrestrictedLowerBounds constraints varBoundMap eliminatedVarsMap = aux
134138
(Map.fromList bounds)
135139
updatedEliminatedVarsMap
136140
aux cs (_ : bounds) = aux cs bounds
141+
142+
simpleSystemToCanonicalForm :: SimpleSystem -> CanonicalForm
143+
simpleSystemToCanonicalForm system =
144+
CanonicalForm {
145+
constraints = finalSystem,
146+
originalVars = SST.simpleSystemVars system,
147+
systemVars = SLU.linearSystemVars finalSystem,
148+
systemSlackVars = Set.fromList slackVars,
149+
eliminatedVarsMap = eliminatedVarsMap
150+
}
151+
where
152+
(eliminatedNonZeroLowerBoundVarsMap, system1) = eliminateNonZeroLowerBounds system Map.empty
153+
system1Bounds = deriveBounds system1
154+
(slackVars, linearSystem) = addSlackVars system1
155+
(eliminatedVarsMap, finalSystem)= eliminateUnrestrictedLowerBounds linearSystem system1Bounds eliminatedNonZeroLowerBoundVarsMap
156+
157+
}
158+
simpleSystemToSlackForm :: SimpleSystem -> SlackForm
159+
simpleSystemToSlackForm system =
160+
SlackForm {
161+
constraints = finalSystem,
162+
originalVars = SST.simpleSystemVars system,
163+
-- systemVars = SLU.linearSystemVars finalSystem,
164+
slackVars = Set.fromList slackVars,
165+
artificialVarsMap = eliminatedVarsMap
166+
}
167+
where
168+
(eliminatedNonZeroLowerBoundVarsMap, system1) = eliminateNonZeroLowerBounds system Map.empty
169+
system1Bounds = deriveBounds system1
170+
(slackVars, linearSystem) = addSlackVars system1
171+
(eliminatedVarsMap, finalSystem)= eliminateUnrestrictedLowerBounds linearSystem system1Bounds eliminatedNonZeroLowerBoundVarsMap
172+

src/Linear/System/Linear/Types.hs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,22 @@ module Linear.System.Linear.Types where
1010
import GHC.Generics (Generic)
1111
import Linear.Constraint.Linear.Types (LinearEquation)
1212
import Linear.Expr.Types (Expr)
13+
import Text.ParserCombinators.ReadP (between)
1314

1415
-- TODO: name this system of equations or something
1516
newtype LinearSystem = LinearSystem {unLinearSystem :: [LinearEquation]}
1617
deriving (Show, Eq, Read, Generic)
1718

18-
class CanBeLinearSystem a where
19-
toLinearSystem :: a -> LinearSystem
19+
{- When would I ever want this? Do I need things to be able to be
20+
able to turn into linear systems? Yes. But do I want other people
21+
to be able to do that? It would be nice, but I think we do that in
22+
the future if people actually want it.
23+
-}
24+
-- class CanBeLinearSystem a where
25+
-- toLinearSystem :: a -> LinearSystem
2026

21-
instance CanBeLinearSystem LinearSystem where
22-
toLinearSystem = id
27+
-- instance CanBeLinearSystem LinearSystem where
28+
-- toLinearSystem = id
2329

24-
instance CanBeLinearSystem LinearEquation where
25-
toLinearSystem id = LinearSystem [id]
30+
-- instance CanBeLinearSystem LinearEquation where
31+
-- toLinearSystem id = LinearSystem [id]

src/Linear/System/Linear/Util.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
-- Stability: experimental
88
module Linear.System.Linear.Util where
99

10+
import qualified Data.Set as Set
11+
1012
import Linear.Constraint.Linear.Types (LinearEquation (..))
1113
import qualified Linear.Constraint.Linear.Util as CLU
1214
import Linear.System.Linear.Types (LinearSystem (..))
13-
import Linear.Var.Types (Var)
15+
import Linear.Var.Types (Var, VarBounds)
1416

1517
-- | Prepend a linear equation to a linear system
1618
prependLinearEquation :: LinearEquation -> LinearSystem -> LinearSystem
@@ -23,3 +25,6 @@ appendLinearEquation eq (LinearSystem eqs) = LinearSystem (eqs ++ [eq])
2325
findHighestVar :: LinearSystem -> Maybe Var
2426
findHighestVar (LinearSystem []) = Nothing
2527
findHighestVar (LinearSystem eqs) = Just $ maximum $ map CLU.findHighestVar eqs
28+
29+
linearSystemVars :: LinearSystem -> Set.Set Var
30+
linearSystemVars = Set.unions . map CLU.linearEquationVars . unLinearSystem

src/Linear/System/Simple/Types.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
-- Stability: experimental
88
module Linear.System.Simple.Types where
99

10-
import Comparison.Types (getMixedComparisonLHS)
10+
import Comparison.Types (getLHS)
1111
import qualified Data.Set as Set
1212
import GHC.Generics (Generic)
1313
import Linear.Constraint.Simple.Types (SimpleConstraint)
1414
import Linear.Constraint.Simple.Util
15-
( simpleConstraintVars
16-
, simplifySimpleConstraint
15+
( simpleConstraintVars,
16+
simplifySimpleConstraint,
1717
)
1818
import Linear.Expr.Util (exprVarsOnlyToList)
1919
import Linear.System.Types (System)
@@ -37,7 +37,7 @@ simpleSystemVars = Set.unions . map simpleConstraintVars . unSimpleSystem
3737
findHighestVar :: SimpleSystem -> Maybe Var
3838
findHighestVar simpleSystem =
3939
let vars = simpleSystemVars simpleSystem
40-
in if Set.null vars
40+
in if Set.null vars
4141
then Nothing
4242
else Just $ Set.findMax vars
4343

src/Linear/System/Simple/Util.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ deriveBounds simpleSystem = foldr updateBounds initialVarBounds simpleSystem.unS
4848

4949
-- Eliminate inequalities which are outside the bounds
5050
-- precondition: no zero coefficients
51-
-- TODO: better name
52-
removeUselessSystemBounds :: SimpleSystem -> VarBounds -> SimpleSystem
53-
removeUselessSystemBounds constraints bounds =
51+
removeObviousInequalities :: SimpleSystem -> VarBounds -> SimpleSystem
52+
removeObviousInequalities constraints bounds =
5453
SimpleSystem $
5554
filter
5655
( \case

src/Linear/Var/Types.hs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,4 @@ data Bounds = Bounds
1515
}
1616
deriving (Show, Read, Eq, Generic)
1717

18-
-- newtype VarBounds = VarBounds { unVarBounds :: M.Map Var Bounds }
19-
-- deriving (Show, Read, Eq, Generic)
20-
2118
type VarBounds = M.Map Var Bounds

0 commit comments

Comments
 (0)