Skip to content

Commit 69de485

Browse files
authored
Switch to fourmolu (#6)
* Switch to fourmolu + Mainly for leading commas * Add .vscode to .gitignore
1 parent 00ec912 commit 69de485

File tree

8 files changed

+564
-474
lines changed

8 files changed

+564
-474
lines changed

.github/workflows/haskell.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ permissions:
1111
contents: read
1212

1313
jobs:
14-
ormolu:
14+
fourmolu:
1515

1616
runs-on: ubuntu-latest
1717

1818
steps:
1919
- uses: actions/checkout@v3
20-
- uses: haskell-actions/run-ormolu@v11
20+
- uses: haskell-actions/run-fourmolu@v7
2121
build:
2222
name: GHC ${{ matrix.ghc-version }} on ${{ matrix.os }}
2323
runs-on: ${{ matrix.os }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.stack-work/
22
*~
33
dist-*/
4+
.vscode/*

fourmolu.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
indentation: 2
2+
column-limit: none
3+
function-arrows: trailing
4+
comma-style: leading
5+
import-export-style: diff-friendly
6+
indent-wheres: true
7+
record-brace-space: true
8+
newlines-between-decls: 1
9+
haddock-style: multi-line
10+
haddock-style-module:
11+
let-style: auto
12+
in-style: right-align
13+
single-constraint-parens: always
14+
unicode: never
15+
respectful: true
16+
fixities: []

src/Linear/Simplex/Prettify.hs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
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
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+
-}
1011
module Linear.Simplex.Prettify where
1112

1213
import Data.Ratio

src/Linear/Simplex/Simplex.hs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
-- |
2-
-- Module : Linear.Simplex.Simplex
3-
-- Description : Implements the twoPhaseSimplex method
4-
-- Copyright : (c) Junaid Rasheed, 2020-2022
5-
-- License : BSD-3
6-
-- Maintainer : [email protected]
7-
-- Stability : experimental
8-
--
9-
-- Module implementing the two-phase simplex method.
10-
-- 'findFeasibleSolution' performs phase one of the two-phase simplex method.
11-
-- 'optimizeFeasibleSystem' performs phase two of the two-phase simplex method.
12-
-- 'twoPhaseSimplex' performs both phases of the two-phase simplex method.
1+
{- |
2+
Module : Linear.Simplex.Simplex
3+
Description : Implements the twoPhaseSimplex method
4+
Copyright : (c) Junaid Rasheed, 2020-2022
5+
License : BSD-3
6+
Maintainer : [email protected]
7+
Stability : experimental
8+
9+
Module implementing the two-phase simplex method.
10+
'findFeasibleSolution' performs phase one of the two-phase simplex method.
11+
'optimizeFeasibleSystem' performs phase two of the two-phase simplex method.
12+
'twoPhaseSimplex' performs both phases of the two-phase simplex method.
13+
-}
1314
module Linear.Simplex.Simplex (findFeasibleSolution, optimizeFeasibleSystem, twoPhaseSimplex) where
1415

1516
import Data.Bifunctor
@@ -24,10 +25,11 @@ import Prelude hiding (EQ)
2425

2526
trace s a = a
2627

27-
-- | Find a feasible solution for the given system of 'PolyConstraint's by performing the first phase of the two-phase simplex method
28-
-- All 'Integer' variables in the 'PolyConstraint' must be positive.
29-
-- If the system is infeasible, return 'Nothing'
30-
-- Otherwise, return the feasible system in 'DictionaryForm' as well as a list of slack variables, a list artificial variables, and the objective variable.
28+
{- | Find a feasible solution for the given system of 'PolyConstraint's by performing the first phase of the two-phase simplex method
29+
All 'Integer' variables in the 'PolyConstraint' must be positive.
30+
If the system is infeasible, return 'Nothing'
31+
Otherwise, return the feasible system in 'DictionaryForm' as well as a list of slack variables, a list artificial variables, and the objective variable.
32+
-}
3133
findFeasibleSolution :: [PolyConstraint] -> Maybe (DictionaryForm, [Integer], [Integer], Integer)
3234
findFeasibleSolution unsimplifiedSystem =
3335
if null artificialVars -- No artificial vars, we have a feasible system
@@ -137,11 +139,12 @@ findFeasibleSolution unsimplifiedSystem =
137139
negatedSum = foldSumVarConstMap ((sort . concat) negatedRows)
138140
negatedSumWithoutArtificialVars = filter (\(v, _) -> v `notElem` artificialVars) negatedSum
139141

140-
-- | Optimize a feasible system by performing the second phase of the two-phase simplex method.
141-
-- We first pass an 'ObjectiveFunction'.
142-
-- Then, the feasible system in 'DictionaryForm' as well as a list of slack variables, a list artificial variables, and the objective variable.
143-
-- Returns a pair with the first item being the 'Integer' variable equal to the 'ObjectiveFunction'
144-
-- and the second item being a map of the values of all 'Integer' variables appearing in the system, including the 'ObjectiveFunction'.
142+
{- | Optimize a feasible system by performing the second phase of the two-phase simplex method.
143+
We first pass an 'ObjectiveFunction'.
144+
Then, the feasible system in 'DictionaryForm' as well as a list of slack variables, a list artificial variables, and the objective variable.
145+
Returns a pair with the first item being the 'Integer' variable equal to the 'ObjectiveFunction'
146+
and the second item being a map of the values of all 'Integer' variables appearing in the system, including the 'ObjectiveFunction'.
147+
-}
145148
optimizeFeasibleSystem :: ObjectiveFunction -> DictionaryForm -> [Integer] -> [Integer] -> Integer -> Maybe (Integer, [(Integer, Rational)])
146149
optimizeFeasibleSystem unsimplifiedObjFunction phase1Dict slackVars artificialVars objectiveVar =
147150
if null artificialVars
@@ -152,8 +155,8 @@ optimizeFeasibleSystem unsimplifiedObjFunction phase1Dict slackVars artificialVa
152155

153156
displayResults :: Tableau -> (Integer, [(Integer, Rational)])
154157
displayResults tableau =
155-
( objectiveVar,
156-
case objFunction of
158+
( objectiveVar
159+
, case objFunction of
157160
Max _ ->
158161
map
159162
(second snd)
@@ -176,10 +179,11 @@ optimizeFeasibleSystem unsimplifiedObjFunction phase1Dict slackVars artificialVa
176179

177180
phase2ObjFunction = if isMax objFunction then Max phase2Objective else Min phase2Objective
178181

179-
-- | Perform the two phase simplex method with a given 'ObjectiveFunction' a system of 'PolyConstraint's.
180-
-- Assumes the 'ObjectiveFunction' and 'PolyConstraint' is not empty.
181-
-- Returns a pair with the first item being the 'Integer' variable equal to the 'ObjectiveFunction'
182-
-- and the second item being a map of the values of all 'Integer' variables appearing in the system, including the 'ObjectiveFunction'.
182+
{- | Perform the two phase simplex method with a given 'ObjectiveFunction' a system of 'PolyConstraint's.
183+
Assumes the 'ObjectiveFunction' and 'PolyConstraint' is not empty.
184+
Returns a pair with the first item being the 'Integer' variable equal to the 'ObjectiveFunction'
185+
and the second item being a map of the values of all 'Integer' variables appearing in the system, including the 'ObjectiveFunction'.
186+
-}
183187
twoPhaseSimplex :: ObjectiveFunction -> [PolyConstraint] -> Maybe (Integer, [(Integer, Rational)])
184188
twoPhaseSimplex objFunction unsimplifiedSystem =
185189
case findFeasibleSolution unsimplifiedSystem of

src/Linear/Simplex/Types.hs

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,52 @@
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
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+
-}
89
module Linear.Simplex.Types where
910

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.
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.
16+
-}
1517
type VarConstMap = [(Integer, Rational)]
1618

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.
19+
{- | For specifying constraints in a system.
20+
The LHS is a 'VarConstMap', and the RHS, is a 'Rational' number.
21+
LEQ [(1, 2), (2, 1)] 3.5 is equivalent to 2x1 + x2 <= 3.5.
22+
Users must only provide positive integer variables.
23+
24+
Example: LEQ [(2, 3), (6, (-1), (2, 1))] 12.3 is equivalent to 3x2 + (-x6) + x2 <= 12.3.
25+
-}
2326
data PolyConstraint
2427
= LEQ VarConstMap Rational
2528
| GEQ VarConstMap Rational
2629
| EQ VarConstMap Rational
2730
deriving (Show, Eq)
2831

29-
-- | Create an objective function.
30-
-- We can either 'Max'imize or 'Min'imize a 'VarConstMap'.
32+
{- | Create an objective function.
33+
We can either 'Max'imize or 'Min'imize a 'VarConstMap'.
34+
-}
3135
data ObjectiveFunction = Max VarConstMap | Min VarConstMap deriving (Show, Eq)
3236

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.
37+
{- | A 'Tableau' of equations.
38+
Each pair in the list is a row.
39+
The first item in the pair specifies which 'Integer' variable is basic in the equation.
40+
The second item in the pair is an equation.
41+
The 'VarConstMap' in the second equation is a list of variables with their coefficients.
42+
The RHS of the equation is a 'Rational' constant.
43+
-}
3944
type Tableau = [(Integer, (VarConstMap, Rational))]
4045

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
46+
{- | Type representing equations.
47+
Each pair in the list is one equation.
48+
The first item of the pair is the basic variable, and is on the LHS of the equation with a coefficient of one.
49+
The RHS is represented using a `VarConstMap`.
50+
The integer variable -1 is used to represent a 'Rational' on the RHS
51+
-}
4652
type DictionaryForm = [(Integer, VarConstMap)]

src/Linear/Simplex/Util.hs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
-- |
2-
-- Module : Linear.Simplex.Util
3-
-- Description : Helper functions
4-
-- Copyright : (c) Junaid Rasheed, 2020-2022
5-
-- License : BSD-3
6-
-- Maintainer : [email protected]
7-
-- Stability : experimental
8-
--
9-
-- Helper functions for performing the two-phase simplex method.
1+
{- |
2+
Module : Linear.Simplex.Util
3+
Description : Helper functions
4+
Copyright : (c) Junaid Rasheed, 2020-2022
5+
License : BSD-3
6+
Maintainer : [email protected]
7+
Stability : experimental
8+
9+
Helper functions for performing the two-phase simplex method.
10+
-}
1011
module Linear.Simplex.Util where
1112

1213
import Data.Bifunctor
@@ -24,9 +25,10 @@ getObjective :: ObjectiveFunction -> VarConstMap
2425
getObjective (Max o) = o
2526
getObjective (Min o) = o
2627

27-
-- | Simplifies a system of 'PolyConstraint's by first calling 'simplifyPolyConstraint',
28-
-- then reducing 'LEQ' and 'GEQ' with same LHS and RHS (and other similar situations) into 'EQ',
29-
-- and finally removing duplicate elements using 'nub'.
28+
{- | Simplifies a system of 'PolyConstraint's by first calling 'simplifyPolyConstraint',
29+
then reducing 'LEQ' and 'GEQ' with same LHS and RHS (and other similar situations) into 'EQ',
30+
and finally removing duplicate elements using 'nub'.
31+
-}
3032
simplifySystem :: [PolyConstraint] -> [PolyConstraint]
3133
simplifySystem = nub . reduceSystem . map simplifyPolyConstraint
3234
where
@@ -109,9 +111,10 @@ createObjectiveDict :: ObjectiveFunction -> Integer -> (Integer, VarConstMap)
109111
createObjectiveDict (Max obj) objectiveVar = (objectiveVar, obj)
110112
createObjectiveDict (Min obj) objectiveVar = (objectiveVar, map (second negate) obj)
111113

112-
-- | Converts a 'Tableau' to 'DictionaryForm'.
113-
-- 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.
114-
-- (-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.
117+
-}
115118
tableauInDictionaryForm :: Tableau -> DictionaryForm
116119
tableauInDictionaryForm [] = []
117120
tableauInDictionaryForm ((basicVar, (vcm, r)) : rows) =
@@ -120,10 +123,11 @@ tableauInDictionaryForm ((basicVar, (vcm, r)) : rows) =
120123
basicCoeff = if null basicVars then 1 else snd $ head basicVars
121124
(basicVars, nonBasicVars) = partition (\(v, _) -> v == basicVar) vcm
122125

123-
-- | Converts a 'DictionaryForm' to a 'Tableau'.
124-
-- This is done by moving all non-basic variables from the right to the left.
125-
-- The rational constant (represented by the 'Integer' variable -1) stays on the right.
126-
-- The basic variables will have a coefficient of 1 in the 'Tableau'.
126+
{- | Converts a 'DictionaryForm' to a 'Tableau'.
127+
This is done by moving all non-basic variables from the right to the left.
128+
The rational constant (represented by the 'Integer' variable -1) stays on the right.
129+
The basic variables will have a coefficient of 1 in the 'Tableau'.
130+
-}
127131
dictionaryFormToTableau :: DictionaryForm -> Tableau
128132
dictionaryFormToTableau [] = []
129133
dictionaryFormToTableau ((basicVar, row) : rows) =
@@ -132,9 +136,10 @@ dictionaryFormToTableau ((basicVar, row) : rows) =
132136
(rationalConstant, nonBasicVars) = partition (\(v, _) -> v == (-1)) row
133137
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.
134138

135-
-- | If this function is given 'Nothing', return 'Nothing'.
136-
-- Otherwise, we 'lookup' the 'Integer' given in the first item of the pair in the map given in the second item of the pair.
137-
-- This is typically used to extract the value of the 'ObjectiveFunction' after calling 'Linear.Simplex.Simplex.twoPhaseSimplex'.
139+
{- | If this function is given 'Nothing', return 'Nothing'.
140+
Otherwise, we 'lookup' the 'Integer' given in the first item of the pair in the map given in the second item of the pair.
141+
This is typically used to extract the value of the 'ObjectiveFunction' after calling 'Linear.Simplex.Simplex.twoPhaseSimplex'.
142+
-}
138143
extractObjectiveValue :: Maybe (Integer, [(Integer, Rational)]) -> Maybe Rational
139144
extractObjectiveValue Nothing = Nothing
140145
extractObjectiveValue (Just (objVar, results)) =

0 commit comments

Comments
 (0)