-
Notifications
You must be signed in to change notification settings - Fork 6
/
LP.hs
127 lines (100 loc) · 2.54 KB
/
LP.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
{-# LANGUAGE FlexibleContexts, GADTs #-}
import Data.LinearProgram
import Data.LinearProgram.LinExpr
-- import Control.Monad.Supply
-- import Control.Monad.LPMonad
import qualified Data.Map as M
type Gen = LPT Var Double VSupply
type Expr = LinExpr Var Double
type Doc = Expr -> Expr -> Gen (Expr,Expr)
var :: Num c => v -> LinExpr v c
var x = LinExpr (M.singleton x 1) 0
(.<=.) :: Expr -> Expr -> Gen ()
a .<=. b = do
f `geqTo` (negate c)
where LinExpr f c = b ^-^ a
-- a <= b
-- b - a >= 0
-- f + c >= 0
-- f >= -c
space :: Doc
space = text " "
empty :: Doc
empty = text ""
(<+>) :: Doc -> Doc -> Doc
a <+> b = a <> space <> b
(</>) :: Doc -> Doc -> Doc
a </> b = a <> softBreak <> b
sep :: [Doc] -> Doc
sep xs i c = do
v <- choice
(foldr (\x y -> x <> newLineIf v <> y) empty xs) i c
-- fsep = foldr (</>) empty
(<>) :: Doc -> Doc -> Doc
(a <> b) i c0 = do
(h1,c1) <- a i c0
(h2,c2) <- b i c1
return (h1 ^+^ h2, c2)
con :: Int -> Expr
con x = LinExpr zero (fromIntegral x)
text :: String -> Doc
text s _ c = do
return (zero, c ^+^ con (length s))
pageWidth :: Int
pageWidth = 80
newline :: Doc
newline i c = do
c .<=. con pageWidth
return (con 1,i)
lpMax :: Expr -> Expr -> Gen Expr
lpMax a b = do
v <- supplyNew
setVarKind v ContVar
setVarBounds v (LBound 0)
a .<=. var v
b .<=. var v
return (var v)
newLineIf :: Var -> Doc
newLineIf cr i c = do
c .<=. con pageWidth
m <- lpMax i (c ^-^ fromIntegral pageWidth *^ var cr)
return (var cr,m)
choice :: Gen Var
choice = do
v <- supplyNew
setVarKind v BinVar
return v
softBreak :: Doc
softBreak i c = do
v <- choice
newLineIf v i c
render :: Doc -> IO ()
render x = do
let problem = runVSupply $ execLPT $
do (LinExpr h _,c) <- x zero zero
c .<=. con pageWidth
setObjective h
setDirection Min
print problem
solution <- glpSolveVars mipDefaults problem
-- {brTech = HybridP}
print solution
data SExpr where
SExpr :: [SExpr] -> SExpr
Atom :: String -> SExpr
deriving Show
abcd :: SExpr
abcd = SExpr [Atom "a",Atom "b",Atom "c",Atom "d"]
testData :: SExpr
testData = SExpr [SExpr [Atom "12345", abcd4],
SExpr [Atom "12345678", abcd4]]
where abcd4 = SExpr [abcd,abcd,abcd,abcd]
testData2 = SExpr (replicate 10 testData)
testData4 = SExpr (replicate 10 testData2)
testData8 = SExpr (replicate 10 testData4)
pretty :: SExpr -> Doc
pretty (Atom x) = text x
pretty (SExpr xs) = text "(" <> sep (map pretty xs) <> text ")"
main :: IO ()
main = do
render $ pretty $ testData2