Skip to content

Commit 7c44b1d

Browse files
committed
rename some types, add some strict fields, add todos
1 parent 834d2ed commit 7c44b1d

File tree

15 files changed

+199
-112
lines changed

15 files changed

+199
-112
lines changed

simplex-method.cabal

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ source-repository head
2828
library
2929
exposed-modules:
3030
Comparison.Types
31+
Linear.CanonicalForm.Types
32+
Linear.CanonicalForm.Util
3133
Linear.Constraint.Linear.Types
3234
Linear.Constraint.Linear.Util
3335
Linear.Constraint.Simple.Types
@@ -42,8 +44,6 @@ library
4244
Linear.Simplex.Standardize
4345
Linear.Simplex.Types
4446
Linear.Simplex.Util
45-
Linear.SlackForm.Types
46-
Linear.SlackForm.Util
4747
Linear.System.Linear.Types
4848
Linear.System.Linear.Util
4949
Linear.System.Simple.Types
@@ -75,9 +75,9 @@ test-suite simplex-method-test
7575
type: exitcode-stdio-1.0
7676
main-is: Spec.hs
7777
other-modules:
78+
Linear.CanonicalForm.UtilSpec
7879
Linear.Constraint.Simple.UtilSpec
7980
Linear.Expr.UtilSpec
80-
Linear.SlackForm.UtilSpec
8181
Linear.System.Simple.UtilSpec
8282
Linear.Term.UtilSpec
8383
Linear.Var.UtilSpec

src/Comparison/Types.hs

Lines changed: 20 additions & 9 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)
@@ -23,16 +28,22 @@ instance (Arbitrary a, Arbitrary b) => Arbitrary (MixedComparison a b) where
2328
, 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/CanonicalForm/Types.hs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-- |
2+
-- Module: Linear.Simplex.CanonicalForm.Types
3+
-- Description: Types for augmented (slack) form of linear programming problems
4+
-- Copyright: (c) Junaid Rasheed, 2024
5+
-- License: BSD-3
6+
-- Maintainer: Junaid Rasheed <jrasheed178@gmail.com>
7+
-- Stability: experimental
8+
module Linear.CanonicalForm.Types where
9+
10+
import qualified Data.Map as Map
11+
import qualified Data.Set as Set
12+
import GHC.Generics (Generic)
13+
import Linear.Constraint.Linear.Types (LinearEquation (..))
14+
import Linear.Expr.Types (Expr, ExprVarsOnly)
15+
import Linear.Expr.Util (exprVarsOnlyVars)
16+
import Linear.System.Linear.Types (LinearSystem (..))
17+
import Linear.System.Simple.Types
18+
import Linear.Var.Types (SimplexNum, Var)
19+
20+
-- https://en.wikipedia.org/wiki/Linear_programming#Augmented_form_(slack_form)
21+
data CanonicalForm = CanonicalForm
22+
{ constraints :: !LinearSystem
23+
, originalVars :: !(Set.Set Var)
24+
, systemVars :: !(Set.Set Var)
25+
, systemSlackVars :: !(Set.Set Var) -- all vars are non-negative
26+
, eliminatedVarsMap :: !(Map.Map Var Expr)
27+
}
28+
deriving (Show, Eq, Read, Generic)

src/Linear/SlackForm/Util.hs renamed to src/Linear/CanonicalForm/Util.hs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
-- License: BSD-3
66
-- Maintainer: Junaid Rasheed <jrasheed178@gmail.com>
77
-- Stability: experimental
8-
module Linear.SlackForm.Util where
8+
module Linear.CanonicalForm.Util where
99

1010
import Comparison.Types
1111
( MixedComparison ((:<=), (:==), (:>=))
1212
)
1313
import qualified Data.Bifunctor as Bifunctor
1414
import qualified Data.Map as Map
1515
import qualified Data.Maybe as Maybe
16+
import qualified Data.Set as Set
1617
import Linear.Constraint.Linear.Types (LinearEquation (..))
1718
import qualified Linear.Constraint.Linear.Util as CLU
1819
import Linear.Constraint.Simple.Types (SimpleConstraint (..))
@@ -21,13 +22,15 @@ import Linear.Constraint.Simple.Util
2122
)
2223
import Linear.Expr.Types (Expr (..), ExprVarsOnly (..))
2324
import Linear.Expr.Util (exprVarsOnlyToExpr)
25+
import Linear.CanonicalForm.Types (CanonicalForm (..))
2426
import Linear.System.Linear.Types (LinearSystem (..))
2527
import qualified Linear.System.Linear.Util as SLU
2628
import Linear.System.Simple.Types
2729
( SimpleSystem (..)
2830
, simplifySimpleSystem
2931
)
3032
import qualified Linear.System.Simple.Types as SST
33+
import Linear.System.Simple.Util (deriveBounds)
3134
import Linear.Term.Types
3235
( Term (..)
3336
, TermVarsOnly (..)
@@ -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,22 @@ 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) =
156+
eliminateUnrestrictedLowerBounds
157+
linearSystem
158+
system1Bounds
159+
eliminatedNonZeroLowerBoundVarsMap

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: 59 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.CanonicalForm.Types (CanonicalForm)
7+
import Linear.System.Linear.Types (LinearSystem)
78
import Linear.Var.Types (SimplexNum, Var)
9+
import System.Posix.Types (CMode)
810

911
data OptimisationDirection = Minimize | Maximize
1012
deriving (Show, Eq, GHC.Generics.Generic)
@@ -15,11 +17,65 @@ 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 CanonicalForm
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 -> CanonicalForm -> CanonicalForm
43+
secondPhase = undefined
44+
45+
-- This will probably be a proper function
46+
systemResult :: CanonicalForm -> OptimisationResult
47+
systemResult = undefined
48+
49+
class CanBeStandardForm problem where
50+
findSolution :: problem -> Maybe CanonicalForm
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 ::
78+
OptSolverOptions s -> s -> Objective -> (OptSolverMonad s) (SatResult Model)
79+
80+
-- class (CanBeLinearSystem s) => Solver2 s where
81+
-- solve2 :: s -> Objective -> Result

src/Linear/SlackForm/Types.hs

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/Linear/System/Linear/Types.hs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,20 @@ import Linear.Constraint.Linear.Types (LinearEquation)
1212
import Linear.Expr.Types (Expr)
1313

1414
-- TODO: name this system of equations or something
15+
-- TODO: OR, should I just get rid of this?
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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
-- Stability: experimental
88
module Linear.System.Linear.Util where
99

10+
import qualified Data.Set as Set
1011
import Linear.Constraint.Linear.Types (LinearEquation (..))
1112
import qualified Linear.Constraint.Linear.Util as CLU
1213
import Linear.System.Linear.Types (LinearSystem (..))
13-
import Linear.Var.Types (Var)
14+
import Linear.Var.Types (Var, VarBounds)
1415

1516
-- | Prepend a linear equation to a linear system
1617
prependLinearEquation :: LinearEquation -> LinearSystem -> LinearSystem
@@ -23,3 +24,6 @@ appendLinearEquation eq (LinearSystem eqs) = LinearSystem (eqs ++ [eq])
2324
findHighestVar :: LinearSystem -> Maybe Var
2425
findHighestVar (LinearSystem []) = Nothing
2526
findHighestVar (LinearSystem eqs) = Just $ maximum $ map CLU.findHighestVar eqs
27+
28+
linearSystemVars :: LinearSystem -> Set.Set Var
29+
linearSystemVars = Set.unions . map CLU.linearEquationVars . unLinearSystem

src/Linear/System/Simple/Types.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
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)

0 commit comments

Comments
 (0)