Skip to content

Commit d5aeb83

Browse files
committed
refactor: add explicit import lists to all unqualified Haskell imports
1 parent d9a5f83 commit d5aeb83

6 files changed

Lines changed: 142 additions & 55 deletions

File tree

src/Linear/Simplex/Prettify.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@
1212
-- Converts "Linear.Simplex.Types" types into human-readable 'String's
1313
module Linear.Simplex.Prettify where
1414

15-
import Control.Lens
1615
import Data.Generics.Labels ()
1716
import Data.Map qualified as M
18-
import Data.Ratio
19-
import Linear.Simplex.Types
17+
import Data.Ratio (denominator, numerator)
18+
import Linear.Simplex.Types (ObjectiveFunction (..), PolyConstraint (..), VarLitMapSum)
2019

2120
-- | Convert a 'VarLitMapSum' into a human-readable 'String'
2221
prettyShowVarLitMapSum :: VarLitMapSum -> String

src/Linear/Simplex/Solver/TwoPhase.hs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,11 @@ module Linear.Simplex.Solver.TwoPhase
3434

3535
import Prelude hiding (EQ)
3636

37-
import qualified Control.Applicative as LPPaver
38-
import Control.Lens
37+
import Control.Lens ((%~), (&), (.~), (<&>))
3938
import Control.Monad (unless)
4039
import Control.Monad.IO.Class (MonadIO)
41-
import Control.Monad.Logger
42-
import Data.Bifunctor
43-
import Data.List
40+
import Control.Monad.Logger (LogLevel (LevelError, LevelInfo, LevelWarn), MonadLogger)
41+
import Data.Bifunctor (second)
4442
import qualified Data.Map as M
4543
import Data.Maybe (fromJust, fromMaybe, mapMaybe)
4644
import Data.Ratio (denominator, numerator, (%))
@@ -49,7 +47,38 @@ import qualified Data.Set as Set
4947
import qualified Data.Text as Text
5048
import GHC.Real (Ratio)
5149
import Linear.Simplex.Types
50+
( Dict
51+
, DictValue (..)
52+
, FeasibleSystem (..)
53+
, ObjectiveFunction (..)
54+
, ObjectiveResult (..)
55+
, OptimisationOutcome (..)
56+
, PivotObjective (..)
57+
, PolyConstraint (..)
58+
, SimplexNum
59+
, SimplexResult (..)
60+
, Tableau
61+
, TableauRow (..)
62+
, Var
63+
, VarDomain (..)
64+
, VarDomainMap (..)
65+
, VarLitMap
66+
, VarLitMapSum
67+
, VarTransform (..)
68+
, nonNegative
69+
, unbounded
70+
)
5271
import Linear.Simplex.Util
72+
( combineVarLitMapSums
73+
, dictionaryFormToTableau
74+
, foldVarLitMap
75+
, insertPivotObjectiveToDict
76+
, isMax
77+
, logMsg
78+
, showT
79+
, simplifySystem
80+
, tableauInDictionaryForm
81+
)
5382

5483
-- | Find a feasible solution for the given system of 'PolyConstraint's by performing the first phase of the two-phase simplex method
5584
-- All variables in the 'PolyConstraint' must be positive.

src/Linear/Simplex/Types.hs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@
77
-- Stability : experimental
88
module Linear.Simplex.Types where
99

10-
import Control.Lens
1110
import Data.Generics.Labels ()
1211
import Data.List (sort)
1312
import qualified Data.Map as M
1413
import GHC.Generics (Generic)
1514

16-
-- | Variable identifier used in maps and constraints.
17-
-- Conventionally this maps to x1, x2, ... in examples.
15+
-- | Variable identifier
1816
type Var = Int
1917

20-
-- | Numeric type used throughout simplex computations.
18+
-- | Numeric type used in this library
2119
type SimplexNum = Rational
2220

23-
-- | A feasible system produced by phase one, ready for phase two optimization.
21+
-- | A feasible system, typically produced by phase one of
22+
-- the two-phase simplex method.
2423
data FeasibleSystem = FeasibleSystem
2524
{ dict :: Dict
2625
, slackVars :: [Var]

src/Linear/Simplex/Util.hs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,29 @@
99
-- Helper functions for performing the two-phase simplex method.
1010
module Linear.Simplex.Util where
1111

12-
import Control.Lens
1312
import Control.Monad.IO.Class (MonadIO (..))
14-
import Control.Monad.Logger (LogLevel (..), LogLine, MonadLogger, logDebug, logError, logInfo, logWarn)
15-
import Data.Bifunctor
13+
import Control.Monad.Logger (LogLevel (..), MonadLogger, logDebug, logError, logInfo, logWarn)
1614
import Data.Generics.Labels ()
17-
import Data.Generics.Product (field)
18-
import Data.List
15+
import Data.List (nub, (\\))
1916
import qualified Data.Map as Map
2017
import qualified Data.Map.Merge.Lazy as MapMerge
2118
import Data.Maybe (fromMaybe)
2219
import qualified Data.Text as T
2320
import Data.Time (getCurrentTime)
2421
import Data.Time.Format.ISO8601 (iso8601Show)
2522
import Linear.Simplex.Types
23+
( Dict
24+
, DictValue (..)
25+
, ObjectiveFunction (..)
26+
, PivotObjective (..)
27+
, PolyConstraint (..)
28+
, SimplexNum
29+
, Tableau
30+
, TableauRow (..)
31+
, Var
32+
, VarLitMap
33+
, VarLitMapSum
34+
)
2635
import Prelude hiding (EQ)
2736

2837
-- | Is the given 'ObjectiveFunction' to be 'Max'imized?

test/Linear/Simplex/Solver/TwoPhaseSpec.hs

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,47 @@ module Linear.Simplex.Solver.TwoPhaseSpec where
55

66
import Prelude hiding (EQ)
77

8-
import Control.Monad.Logger
8+
import Control.Monad.Logger (LogLevel (LevelInfo), filterLogger, runStdoutLoggingT)
99
import qualified Data.Map as M
1010
import Data.Maybe (isJust)
11-
import Data.Ratio
11+
import Data.Ratio ((%))
1212
import qualified Data.Set as Set
1313

14-
import Test.Hspec
15-
import Test.QuickCheck
14+
import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe, shouldSatisfy)
15+
import Test.QuickCheck (NonEmptyList (..), Positive (..), property, (==>))
1616

17-
import Linear.Simplex.Prettify
17+
import Linear.Simplex.Prettify (prettyShowObjectiveFunction, prettyShowPolyConstraint, prettyShowVarLitMapSum)
1818
import Linear.Simplex.Solver.TwoPhase
19+
( applyShiftToConstraint
20+
, applyShiftToObjective
21+
, applySplitToConstraint
22+
, applySplitToObjective
23+
, applyTransform
24+
, applyTransforms
25+
, collectAllVars
26+
, computeObjective
27+
, generateTransform
28+
, getTransform
29+
, postprocess
30+
, preprocess
31+
, twoPhaseSimplex
32+
, unapplyTransformToVarMap
33+
, unapplyTransformsToVarMap
34+
)
1935
import Linear.Simplex.Types
36+
( ObjectiveFunction (..)
37+
, ObjectiveResult (..)
38+
, OptimisationOutcome (..)
39+
, PolyConstraint (..)
40+
, SimplexResult (..)
41+
, VarDomainMap (..)
42+
, VarTransform (..)
43+
, boundedRange
44+
, lowerBoundOnly
45+
, nonNegative
46+
, unbounded
47+
, upperBoundOnly
48+
)
2049

2150
spec :: Spec
2251
spec = do
@@ -2662,47 +2691,52 @@ spec = do
26622691
it "RHS adjustment follows formula: newRHS = oldRHS - coeff * shiftBy" $
26632692
property $
26642693
\(coeff :: Rational) (oldRHS :: Rational) (shiftBy :: Rational) ->
2665-
coeff /= 0 ==>
2666-
let constraint = LEQ (M.fromList [(1, coeff)]) oldRHS
2667-
LEQ _ newRHS = applyShiftToConstraint 1 10 shiftBy constraint
2668-
in newRHS == oldRHS - coeff * shiftBy
2694+
coeff
2695+
/= 0
2696+
==> let constraint = LEQ (M.fromList [(1, coeff)]) oldRHS
2697+
LEQ _ newRHS = applyShiftToConstraint 1 10 shiftBy constraint
2698+
in newRHS == oldRHS - coeff * shiftBy
26692699

26702700
it "preserves constraint type (LEQ stays LEQ)" $
26712701
property $
26722702
\(coeff :: Rational) (rhs :: Rational) (shiftBy :: Rational) ->
2673-
coeff /= 0 ==>
2674-
let constraint = LEQ (M.fromList [(1, coeff)]) rhs
2675-
in case applyShiftToConstraint 1 10 shiftBy constraint of
2676-
LEQ {} -> True
2677-
_ -> False
2703+
coeff
2704+
/= 0
2705+
==> let constraint = LEQ (M.fromList [(1, coeff)]) rhs
2706+
in case applyShiftToConstraint 1 10 shiftBy constraint of
2707+
LEQ {} -> True
2708+
_ -> False
26782709

26792710
it "preserves constraint type (GEQ stays GEQ)" $
26802711
property $
26812712
\(coeff :: Rational) (rhs :: Rational) (shiftBy :: Rational) ->
2682-
coeff /= 0 ==>
2683-
let constraint = GEQ (M.fromList [(1, coeff)]) rhs
2684-
in case applyShiftToConstraint 1 10 shiftBy constraint of
2685-
GEQ {} -> True
2686-
_ -> False
2713+
coeff
2714+
/= 0
2715+
==> let constraint = GEQ (M.fromList [(1, coeff)]) rhs
2716+
in case applyShiftToConstraint 1 10 shiftBy constraint of
2717+
GEQ {} -> True
2718+
_ -> False
26872719

26882720
describe "applySplitToConstraint properties" $ do
26892721
it "preserves RHS value" $
26902722
property $
26912723
\(coeff :: Rational) (rhs :: Rational) ->
2692-
coeff /= 0 ==>
2693-
let constraint = LEQ (M.fromList [(1, coeff)]) rhs
2694-
LEQ _ newRHS = applySplitToConstraint 1 10 11 constraint
2695-
in newRHS == rhs
2724+
coeff
2725+
/= 0
2726+
==> let constraint = LEQ (M.fromList [(1, coeff)]) rhs
2727+
LEQ _ newRHS = applySplitToConstraint 1 10 11 constraint
2728+
in newRHS == rhs
26962729

26972730
it "negVar coefficient is negation of posVar coefficient" $
26982731
property $
26992732
\(coeff :: Rational) (rhs :: Rational) ->
2700-
coeff /= 0 ==>
2701-
let constraint = LEQ (M.fromList [(1, coeff)]) rhs
2702-
LEQ m _ = applySplitToConstraint 1 10 11 constraint
2703-
posCoeff = M.findWithDefault 0 10 m
2704-
negCoeff = M.findWithDefault 0 11 m
2705-
in negCoeff == negate posCoeff
2733+
coeff
2734+
/= 0
2735+
==> let constraint = LEQ (M.fromList [(1, coeff)]) rhs
2736+
LEQ m _ = applySplitToConstraint 1 10 11 constraint
2737+
posCoeff = M.findWithDefault 0 10 m
2738+
negCoeff = M.findWithDefault 0 11 m
2739+
in negCoeff == negate posCoeff
27062740

27072741
describe "unapplyTransformToVarMap Shift properties" $ do
27082742
it "recovers originalVar = shiftedVar + shiftBy" $
@@ -2743,12 +2777,14 @@ spec = do
27432777
it "Shift transform and unapply is identity for variable value" $
27442778
property $
27452779
\(origVal :: Rational) (shiftBy :: Rational) ->
2746-
shiftBy < 0 ==> -- Only negative shifts are valid
2747-
let shiftedVal = origVal - shiftBy -- shiftedVar = originalVar - shiftBy
2748-
varMap = M.fromList [(5, 100), (10, shiftedVal)]
2749-
transform = Shift 1 10 shiftBy
2750-
newVarMap = unapplyTransformToVarMap transform varMap
2751-
in M.lookup 1 newVarMap == Just origVal
2780+
shiftBy
2781+
< 0
2782+
==> let shiftedVal -- Only negative shifts are valid
2783+
= origVal - shiftBy -- shiftedVar = originalVar - shiftBy
2784+
varMap = M.fromList [(5, 100), (10, shiftedVal)]
2785+
transform = Shift 1 10 shiftBy
2786+
newVarMap = unapplyTransformToVarMap transform varMap
2787+
in M.lookup 1 newVarMap == Just origVal
27522788

27532789
it "Split with posVal=origVal and negVal=0 gives correct value for positive origVal" $
27542790
property $

test/Linear/Simplex/UtilSpec.hs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,26 @@ import Prelude hiding (EQ)
66

77
import Control.Exception (evaluate)
88
import qualified Data.Map as M
9-
import Test.Hspec
10-
import Test.QuickCheck
9+
import Test.Hspec (Spec, anyErrorCall, describe, expectationFailure, it, shouldBe, shouldThrow)
10+
import Test.QuickCheck (Positive (..), property)
1111

1212
import Linear.Simplex.Types
13+
( DictValue (..)
14+
, ObjectiveFunction (..)
15+
, PivotObjective (..)
16+
, PolyConstraint (..)
17+
, TableauRow (..)
18+
, VarLitMapSum
19+
)
1320
import Linear.Simplex.Util
21+
( combineVarLitMapSums
22+
, dictionaryFormToTableau
23+
, foldVarLitMap
24+
, insertPivotObjectiveToDict
25+
, isMax
26+
, simplifySystem
27+
, tableauInDictionaryForm
28+
)
1429

1530
spec :: Spec
1631
spec = do

0 commit comments

Comments
 (0)