limp-cbc-0.3.2.1: examples/Clustering.hs
-- Example program based on one generated by our fusion/clustering algorithm
--
-- sum1 = fold (+) 0 xs
-- nor1 = map (/ sum1) xs
-- ys = filter (> 0) xs
-- sum2 = fold (+) 0 ys
-- nor2 = map (/ sum2) xs
--
module Clustering (clustering) where
import Base
import Numeric.Limp.Rep
import Numeric.Limp.Program
import qualified Numeric.Limp.Canon as C
import qualified Numeric.Limp.Canon.Pretty as C
-- | One for each combinator
data Node
= Sum1 | Nor1 | Ys | Sum2 | Nor2
deriving (Ord, Eq, Show)
-- | The integer variables:
-- forall a b. 0 <= F a b <= 1 :: Z
-- F a b == 0 iff a and b are fused
data VZ
= F Node Node
deriving (Ord, Eq, Show)
-- | The real variables:
-- forall a b. F a b == 0 ==> O a == O b
-- O a > O b if edge from a to b
data VR
= O Node
deriving (Ord, Eq, Show)
problem1 :: Direction -> Program VZ VR IntDouble
problem1 dir
= program dir
objective
constraints
bounds
--Minimise 5f(sum1, ys) + 1f(sum1, sum2)
-- + 5f(sum1, nor2) + 5f(ys, sum2)
-- + 5f(ys, nor1) + 5f(sum2, nor1)
-- + 5f(nor1, nor2)
objective
= f100 Sum1 Ys .+. f1 Sum1 Sum2
.+. f100 Sum1 Nor2 .+. f100 Ys Sum2
.+. f100 Ys Nor1 .+. f1 Sum2 Nor1
.+. f100 Nor1 Nor2
--Subject to
-- f(sum1, ys) ≤ f(sum1, sum2)
-- f(sum2, ys) ≤ f(sum1, sum2)
-- -5f(sum1, ys) ≤ o(ys) - o(sum1) ≤ 5f(sum1, ys)
-- -5f(sum1, sum2) ≤ o(sum2) - o(sum1) ≤ 5f(sum1, sum2)
-- 1f(ys, sum2) ≤ o(sum2) - o(ys) ≤ 5f(ys, sum2)
-- -5f(nor1, nor2) ≤ o(nor2) - o(nor1) ≤ 5f(nor1, nor2)
-- o(sum1) < o(nor1)
-- o(sum2) < o(nor2)
--
constraints
= filt Sum1 Sum2 Ys
:&& filt Sum2 Nor1 Ys
:&& odiff (-5) Sum1 Ys 5
:&& odiff (-5) Sum1 Sum2 5
:&& odiff 1 Ys Sum2 5
:&& odiff (-5) Ys Nor1 5
:&& odiff (-5) Nor1 Nor2 5
:&& odiff (-5) Sum1 Nor2 5
:&& odiff (-5) Sum2 Nor1 5
:&& o Sum1 `lt` o Nor1
:&& o Sum2 `lt` o Nor2
where
o = r1 . O
lt a b = a .+. c1 :<= b
filt a b c
= f1 a c :<= f1 a b
:&& f1 b c :<= f1 a b
odiff p a b q
= Between (p *. f1 a b) (o b .-. o a) (q *. f1 a b)
bounds
= [ binary $ F Sum1 Sum2
, binary $ F Sum1 Ys
, binary $ F Sum1 Nor2
, binary $ F Ys Sum2
, binary $ F Nor1 Ys
, binary $ F Nor1 Sum2
, binary $ F Nor1 Nor2
]
f100 :: Node -> Node -> Linear VZ VR IntDouble KZ
f100 a b
= 100 *. f1 a b
f1 :: Node -> Node -> Linear VZ VR IntDouble KZ
f1 a b
= z1 $ F (min a b) (max a b)
clustering :: IO ()
clustering
= do solve_problem problem1
putStr (show $ C.program $ problem1 Minimise)