Skip to content

Commit 20960f3

Browse files
authored
Run ormolu and Add formatter to GitHub actions (#3)
* Run ormolu formatter * Add ormolu formatter to GitHub actions
1 parent d0734d3 commit 20960f3

File tree

9 files changed

+645
-765
lines changed

9 files changed

+645
-765
lines changed

.github/workflows/haskell.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ permissions:
1010
contents: read
1111

1212
jobs:
13+
ormolu:
14+
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- uses: actions/checkout@v3
19+
- uses: haskell-actions/run-ormolu@v11
1320
build:
1421

1522
runs-on: ubuntu-latest

Setup.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
import Distribution.Simple
2+
23
main = defaultMain

src/Linear/Simplex/Prettify.hs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,37 @@
1-
{-|
2-
Module : Linear.Simplex.Prettify
3-
Description : Prettifier for "Linear.Simplex.Types" types
4-
Copyright : (c) Junaid Rasheed, 2020-2022
5-
License : BSD-3
6-
Maintainer : [email protected]
7-
Stability : experimental
8-
9-
Converts "Linear.Simplex.Types" types into human-readable 'String's
10-
-}
1+
-- |
2+
-- Module : Linear.Simplex.Prettify
3+
-- Description : Prettifier for "Linear.Simplex.Types" types
4+
-- Copyright : (c) Junaid Rasheed, 2020-2022
5+
-- License : BSD-3
6+
-- Maintainer : [email protected]
7+
-- Stability : experimental
8+
--
9+
-- Converts "Linear.Simplex.Types" types into human-readable 'String's
1110
module Linear.Simplex.Prettify where
1211

13-
import Linear.Simplex.Types as T
1412
import Data.Ratio
13+
import Linear.Simplex.Types as T
1514

16-
-- |Convert a 'VarConstMap' into a human-readable 'String'
15+
-- | Convert a 'VarConstMap' into a human-readable 'String'
1716
prettyShowVarConstMap :: VarConstMap -> String
1817
prettyShowVarConstMap [] = ""
19-
prettyShowVarConstMap [(v, c)] = prettyShowRational c ++ " * x" ++ show v ++ ""
18+
prettyShowVarConstMap [(v, c)] = prettyShowRational c ++ " * x" ++ show v ++ ""
2019
where
21-
prettyShowRational r =
20+
prettyShowRational r =
2221
if r < 0
2322
then "(" ++ r' ++ ")"
2423
else r'
2524
where
2625
r' = if denominator r == 1 then show (numerator r) else show (numerator r) ++ " / " ++ show (numerator r)
27-
2826
prettyShowVarConstMap ((v, c) : vcs) = prettyShowVarConstMap [(v, c)] ++ " + " ++ prettyShowVarConstMap vcs
2927

30-
-- |Convert a 'PolyConstraint' into a human-readable 'String'
28+
-- | Convert a 'PolyConstraint' into a human-readable 'String'
3129
prettyShowPolyConstraint :: PolyConstraint -> String
3230
prettyShowPolyConstraint (LEQ vcm r) = prettyShowVarConstMap vcm ++ " <= " ++ show r
3331
prettyShowPolyConstraint (GEQ vcm r) = prettyShowVarConstMap vcm ++ " >= " ++ show r
34-
prettyShowPolyConstraint (T.EQ vcm r) = prettyShowVarConstMap vcm ++ " == " ++ show r
32+
prettyShowPolyConstraint (T.EQ vcm r) = prettyShowVarConstMap vcm ++ " == " ++ show r
3533

36-
-- |Convert an 'ObjectiveFunction' into a human-readable 'String'
34+
-- | Convert an 'ObjectiveFunction' into a human-readable 'String'
3735
prettyShowObjectiveFunction :: ObjectiveFunction -> String
3836
prettyShowObjectiveFunction (Min vcm) = "min: " ++ prettyShowVarConstMap vcm
3937
prettyShowObjectiveFunction (Max vcm) = "max: " ++ prettyShowVarConstMap vcm

src/Linear/Simplex/Simplex.hs

Lines changed: 134 additions & 141 deletions
Large diffs are not rendered by default.

src/Linear/Simplex/Types.hs

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
1-
{-|
2-
Module : Linear.Simplex.Types
3-
Description : Custom types
4-
Copyright : (c) Junaid Rasheed, 2020-2022
5-
License : BSD-3
6-
Maintainer : [email protected]
7-
Stability : experimental
8-
-}
1+
-- |
2+
-- Module : Linear.Simplex.Types
3+
-- Description : Custom types
4+
-- Copyright : (c) Junaid Rasheed, 2020-2022
5+
-- License : BSD-3
6+
-- Maintainer : [email protected]
7+
-- Stability : experimental
98
module Linear.Simplex.Types where
109

11-
-- |List of 'Integer' variables with their 'Rational' coefficients.
12-
-- There is an implicit addition between elements in this list.
13-
-- Users must only provide positive integer variables.
14-
--
15-
-- Example: [(2, 3), (6, (-1), (2, 1))] is equivalent to 3x2 + (-x6) + x2.
10+
-- | List of 'Integer' variables with their 'Rational' coefficients.
11+
-- There is an implicit addition between elements in this list.
12+
-- Users must only provide positive integer variables.
13+
--
14+
-- Example: [(2, 3), (6, (-1), (2, 1))] is equivalent to 3x2 + (-x6) + x2.
1615
type VarConstMap = [(Integer, Rational)]
1716

18-
-- |For specifying constraints in a system.
19-
-- The LHS is a 'VarConstMap', and the RHS, is a 'Rational' number.
20-
-- LEQ [(1, 2), (2, 1)] 3.5 is equivalent to 2x1 + x2 <= 3.5.
21-
-- Users must only provide positive integer variables.
22-
--
23-
-- Example: LEQ [(2, 3), (6, (-1), (2, 1))] 12.3 is equivalent to 3x2 + (-x6) + x2 <= 12.3.
24-
data PolyConstraint =
25-
LEQ VarConstMap Rational |
26-
GEQ VarConstMap Rational |
27-
EQ VarConstMap Rational deriving (Show, Eq);
17+
-- | For specifying constraints in a system.
18+
-- The LHS is a 'VarConstMap', and the RHS, is a 'Rational' number.
19+
-- LEQ [(1, 2), (2, 1)] 3.5 is equivalent to 2x1 + x2 <= 3.5.
20+
-- Users must only provide positive integer variables.
21+
--
22+
-- Example: LEQ [(2, 3), (6, (-1), (2, 1))] 12.3 is equivalent to 3x2 + (-x6) + x2 <= 12.3.
23+
data PolyConstraint
24+
= LEQ VarConstMap Rational
25+
| GEQ VarConstMap Rational
26+
| EQ VarConstMap Rational
27+
deriving (Show, Eq)
2828

29-
-- |Create an objective function.
30-
-- We can either 'Max'imize or 'Min'imize a 'VarConstMap'.
29+
-- | Create an objective function.
30+
-- We can either 'Max'imize or 'Min'imize a 'VarConstMap'.
3131
data ObjectiveFunction = Max VarConstMap | Min VarConstMap deriving (Show, Eq)
3232

33-
-- |A 'Tableau' of equations.
34-
-- Each pair in the list is a row.
35-
-- The first item in the pair specifies which 'Integer' variable is basic in the equation.
36-
-- The second item in the pair is an equation.
37-
-- The 'VarConstMap' in the second equation is a list of variables with their coefficients.
38-
-- The RHS of the equation is a 'Rational' constant.
33+
-- | A 'Tableau' of equations.
34+
-- Each pair in the list is a row.
35+
-- The first item in the pair specifies which 'Integer' variable is basic in the equation.
36+
-- The second item in the pair is an equation.
37+
-- The 'VarConstMap' in the second equation is a list of variables with their coefficients.
38+
-- The RHS of the equation is a 'Rational' constant.
3939
type Tableau = [(Integer, (VarConstMap, Rational))]
4040

41-
-- |Type representing equations.
42-
-- Each pair in the list is one equation.
43-
-- The first item of the pair is the basic variable, and is on the LHS of the equation with a coefficient of one.
44-
-- The RHS is represented using a `VarConstMap`.
45-
-- The integer variable -1 is used to represent a 'Rational' on the RHS
41+
-- | Type representing equations.
42+
-- Each pair in the list is one equation.
43+
-- The first item of the pair is the basic variable, and is on the LHS of the equation with a coefficient of one.
44+
-- The RHS is represented using a `VarConstMap`.
45+
-- The integer variable -1 is used to represent a 'Rational' on the RHS
4646
type DictionaryForm = [(Integer, VarConstMap)]

src/Linear/Simplex/Util.hs

Lines changed: 80 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,152 +1,144 @@
11
{-# LANGUAGE LambdaCase #-}
22

3-
{-|
4-
Module : Linear.Simplex.Util
5-
Description : Helper functions
6-
Copyright : (c) Junaid Rasheed, 2020-2022
7-
License : BSD-3
8-
Maintainer : [email protected]
9-
Stability : experimental
10-
11-
Helper functions for performing the two-phase simplex method.
12-
-}
3+
-- |
4+
-- Module : Linear.Simplex.Util
5+
-- Description : Helper functions
6+
-- Copyright : (c) Junaid Rasheed, 2020-2022
7+
-- License : BSD-3
8+
-- Maintainer : [email protected]
9+
-- Stability : experimental
10+
--
11+
-- Helper functions for performing the two-phase simplex method.
1312
module Linear.Simplex.Util where
1413

15-
import Prelude hiding (EQ);
16-
import Linear.Simplex.Types
17-
import Data.List
1814
import Data.Bifunctor
15+
import Data.List
16+
import Linear.Simplex.Types
17+
import Prelude hiding (EQ)
1918

20-
-- |Is the given 'ObjectiveFunction' to be 'Max'imized?
19+
-- | Is the given 'ObjectiveFunction' to be 'Max'imized?
2120
isMax :: ObjectiveFunction -> Bool
2221
isMax (Max _) = True
2322
isMax (Min _) = False
2423

25-
-- |Extract the objective ('VarConstMap') from an 'ObjectiveFunction'
24+
-- | Extract the objective ('VarConstMap') from an 'ObjectiveFunction'
2625
getObjective :: ObjectiveFunction -> VarConstMap
2726
getObjective (Max o) = o
2827
getObjective (Min o) = o
2928

30-
-- |Simplifies a system of 'PolyConstraint's by first calling 'simplifyPolyConstraint',
31-
-- then reducing 'LEQ' and 'GEQ' with same LHS and RHS (and other similar situations) into 'EQ',
32-
-- and finally removing duplicate elements using 'nub'.
29+
-- | Simplifies a system of 'PolyConstraint's by first calling 'simplifyPolyConstraint',
30+
-- then reducing 'LEQ' and 'GEQ' with same LHS and RHS (and other similar situations) into 'EQ',
31+
-- and finally removing duplicate elements using 'nub'.
3332
simplifySystem :: [PolyConstraint] -> [PolyConstraint]
3433
simplifySystem = nub . reduceSystem . map simplifyPolyConstraint
3534
where
3635
reduceSystem :: [PolyConstraint] -> [PolyConstraint]
3736
reduceSystem [] = []
3837
-- Reduce LEQ with matching GEQ and EQ into EQ
3938
reduceSystem ((LEQ lhs rhs) : pcs) =
40-
let
41-
matchingConstraints =
42-
filter
43-
(\case
44-
GEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
45-
EQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
46-
_ -> False
47-
)
48-
pcs
49-
in
50-
if null matchingConstraints
51-
then LEQ lhs rhs : reduceSystem pcs
52-
else EQ lhs rhs : reduceSystem (pcs \\ matchingConstraints)
39+
let matchingConstraints =
40+
filter
41+
( \case
42+
GEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
43+
EQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
44+
_ -> False
45+
)
46+
pcs
47+
in if null matchingConstraints
48+
then LEQ lhs rhs : reduceSystem pcs
49+
else EQ lhs rhs : reduceSystem (pcs \\ matchingConstraints)
5350
-- Reduce GEQ with matching LEQ and EQ into EQ
5451
reduceSystem ((GEQ lhs rhs) : pcs) =
55-
let
56-
matchingConstraints =
57-
filter
58-
(\case
59-
LEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
60-
EQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
61-
_ -> False
62-
)
63-
pcs
64-
in
65-
if null matchingConstraints
66-
then GEQ lhs rhs : reduceSystem pcs
67-
else EQ lhs rhs : reduceSystem (pcs \\ matchingConstraints)
52+
let matchingConstraints =
53+
filter
54+
( \case
55+
LEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
56+
EQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
57+
_ -> False
58+
)
59+
pcs
60+
in if null matchingConstraints
61+
then GEQ lhs rhs : reduceSystem pcs
62+
else EQ lhs rhs : reduceSystem (pcs \\ matchingConstraints)
6863
-- Reduce EQ with matching LEQ and GEQ into EQ
6964
reduceSystem ((EQ lhs rhs) : pcs) =
70-
let
71-
matchingConstraints =
72-
filter
73-
(\case
74-
LEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
75-
GEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
76-
_ -> False
77-
)
78-
pcs
79-
in
80-
if null matchingConstraints
81-
then EQ lhs rhs : reduceSystem pcs
82-
else EQ lhs rhs : reduceSystem (pcs \\ matchingConstraints)
65+
let matchingConstraints =
66+
filter
67+
( \case
68+
LEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
69+
GEQ lhs' rhs' -> lhs == lhs' && rhs == rhs'
70+
_ -> False
71+
)
72+
pcs
73+
in if null matchingConstraints
74+
then EQ lhs rhs : reduceSystem pcs
75+
else EQ lhs rhs : reduceSystem (pcs \\ matchingConstraints)
8376

84-
-- |Simplify an 'ObjectiveFunction' by first 'sort'ing and then calling 'foldSumVarConstMap' on the 'VarConstMap'.
77+
-- | Simplify an 'ObjectiveFunction' by first 'sort'ing and then calling 'foldSumVarConstMap' on the 'VarConstMap'.
8578
simplifyObjectiveFunction :: ObjectiveFunction -> ObjectiveFunction
8679
simplifyObjectiveFunction (Max varConstMap) = Max (foldSumVarConstMap (sort varConstMap))
8780
simplifyObjectiveFunction (Min varConstMap) = Min (foldSumVarConstMap (sort varConstMap))
8881

89-
-- |Simplify a 'PolyConstraint' by first 'sort'ing and then calling 'foldSumVarConstMap' on the 'VarConstMap'.
82+
-- | Simplify a 'PolyConstraint' by first 'sort'ing and then calling 'foldSumVarConstMap' on the 'VarConstMap'.
9083
simplifyPolyConstraint :: PolyConstraint -> PolyConstraint
9184
simplifyPolyConstraint (LEQ varConstMap rhs) = LEQ (foldSumVarConstMap (sort varConstMap)) rhs
9285
simplifyPolyConstraint (GEQ varConstMap rhs) = GEQ (foldSumVarConstMap (sort varConstMap)) rhs
93-
simplifyPolyConstraint (EQ varConstMap rhs) = EQ (foldSumVarConstMap (sort varConstMap)) rhs
86+
simplifyPolyConstraint (EQ varConstMap rhs) = EQ (foldSumVarConstMap (sort varConstMap)) rhs
9487

95-
-- |Add a sorted list of 'VarConstMap's, folding where the variables are equal
88+
-- | Add a sorted list of 'VarConstMap's, folding where the variables are equal
9689
foldSumVarConstMap :: [(Integer, Rational)] -> [(Integer, Rational)]
97-
foldSumVarConstMap [] = []
98-
foldSumVarConstMap [(v, c)] = [(v, c)]
90+
foldSumVarConstMap [] = []
91+
foldSumVarConstMap [(v, c)] = [(v, c)]
9992
foldSumVarConstMap ((v1, c1) : (v2, c2) : vcm) =
10093
if v1 == v2
101-
then
94+
then
10295
let newC = c1 + c2
103-
in
104-
if newC == 0
105-
then foldSumVarConstMap vcm
106-
else foldSumVarConstMap $ (v1, c1 + c2) : vcm
96+
in if newC == 0
97+
then foldSumVarConstMap vcm
98+
else foldSumVarConstMap $ (v1, c1 + c2) : vcm
10799
else (v1, c1) : foldSumVarConstMap ((v2, c2) : vcm)
108100

109-
-- |Get a map of the value of every 'Integer' variable in a 'Tableau'
101+
-- | Get a map of the value of every 'Integer' variable in a 'Tableau'
110102
displayTableauResults :: Tableau -> [(Integer, Rational)]
111103
displayTableauResults = map (\(basicVar, (_, rhs)) -> (basicVar, rhs))
112104

113-
-- |Get a map of the value of every 'Integer' variable in a 'DictionaryForm'
105+
-- | Get a map of the value of every 'Integer' variable in a 'DictionaryForm'
114106
displayDictionaryResults :: DictionaryForm -> [(Integer, Rational)]
115-
displayDictionaryResults dict = displayTableauResults$ dictionaryFormToTableau dict
107+
displayDictionaryResults dict = displayTableauResults $ dictionaryFormToTableau dict
116108

117-
-- |Map the given 'Integer' variable to the given 'ObjectiveFunction', for entering into 'DictionaryForm'.
109+
-- | Map the given 'Integer' variable to the given 'ObjectiveFunction', for entering into 'DictionaryForm'.
118110
createObjectiveDict :: ObjectiveFunction -> Integer -> (Integer, VarConstMap)
119111
createObjectiveDict (Max obj) objectiveVar = (objectiveVar, obj)
120112
createObjectiveDict (Min obj) objectiveVar = (objectiveVar, map (second negate) obj)
121113

122-
-- |Converts a 'Tableau' to 'DictionaryForm'.
123-
-- We do this by isolating the basic variable on the LHS, ending up with all non basic variables and a 'Rational' constant on the RHS.
124-
-- (-1) is used to represent the rational constant.
114+
-- | Converts a 'Tableau' to 'DictionaryForm'.
115+
-- We do this by isolating the basic variable on the LHS, ending up with all non basic variables and a 'Rational' constant on the RHS.
116+
-- (-1) is used to represent the rational constant.
125117
tableauInDictionaryForm :: Tableau -> DictionaryForm
126-
tableauInDictionaryForm [] = []
127-
tableauInDictionaryForm ((basicVar, (vcm, r)) : rows) =
118+
tableauInDictionaryForm [] = []
119+
tableauInDictionaryForm ((basicVar, (vcm, r)) : rows) =
128120
(basicVar, (-1, r / basicCoeff) : map (\(v, c) -> (v, negate c / basicCoeff)) nonBasicVars) : tableauInDictionaryForm rows
129121
where
130122
basicCoeff = if null basicVars then 1 else snd $ head basicVars
131123
(basicVars, nonBasicVars) = partition (\(v, _) -> v == basicVar) vcm
132124

133-
-- |Converts a 'DictionaryForm' to a 'Tableau'.
134-
-- This is done by moving all non-basic variables from the right to the left.
135-
-- The rational constant (represented by the 'Integer' variable -1) stays on the right.
136-
-- The basic variables will have a coefficient of 1 in the 'Tableau'.
125+
-- | Converts a 'DictionaryForm' to a 'Tableau'.
126+
-- This is done by moving all non-basic variables from the right to the left.
127+
-- The rational constant (represented by the 'Integer' variable -1) stays on the right.
128+
-- The basic variables will have a coefficient of 1 in the 'Tableau'.
137129
dictionaryFormToTableau :: DictionaryForm -> Tableau
138130
dictionaryFormToTableau [] = []
139-
dictionaryFormToTableau ((basicVar, row) : rows) =
140-
(basicVar, ((basicVar, 1) : map (second negate) nonBasicVars, r)) : dictionaryFormToTableau rows
131+
dictionaryFormToTableau ((basicVar, row) : rows) =
132+
(basicVar, ((basicVar, 1) : map (second negate) nonBasicVars, r)) : dictionaryFormToTableau rows
141133
where
142-
(rationalConstant, nonBasicVars) = partition (\(v,_) -> v == (-1)) row
134+
(rationalConstant, nonBasicVars) = partition (\(v, _) -> v == (-1)) row
143135
r = if null rationalConstant then 0 else (snd . head) rationalConstant -- If there is no rational constant found in the right side, the rational constant is 0.
144136

145-
-- |If this function is given 'Nothing', return 'Nothing'.
146-
-- Otherwise, we 'lookup' the 'Integer' given in the first item of the pair in the map given in the second item of the pair.
147-
-- This is typically used to extract the value of the 'ObjectiveFunction' after calling 'Linear.Simplex.Simplex.twoPhaseSimplex'.
137+
-- | If this function is given 'Nothing', return 'Nothing'.
138+
-- Otherwise, we 'lookup' the 'Integer' given in the first item of the pair in the map given in the second item of the pair.
139+
-- This is typically used to extract the value of the 'ObjectiveFunction' after calling 'Linear.Simplex.Simplex.twoPhaseSimplex'.
148140
extractObjectiveValue :: Maybe (Integer, [(Integer, Rational)]) -> Maybe Rational
149-
extractObjectiveValue Nothing = Nothing
141+
extractObjectiveValue Nothing = Nothing
150142
extractObjectiveValue (Just (objVar, results)) =
151143
case lookup objVar results of
152144
Nothing -> error "Objective not found in results when extracting objective value"

0 commit comments

Comments
 (0)