module Numeric.LinearProgramming.L1 (
    l1Solve, l1SolveGT,
    l1SolveO, lInfSolveO,
    l1SolveU,
) where
import Numeric.LinearAlgebra.HMatrix
import Numeric.LinearProgramming
lInfSolveO :: Matrix Double -> Vector Double -> Vector Double
lInfSolveO a b = fromList (take n x)
  where
    n = cols a
    as = toRows a
    bs = toList b
    c1 = zipWith (mk (1)) as bs
    c2 = zipWith (mk (1)) as bs
    mk sign a_i b_i = (zipWith (#) (toList (scale sign a_i)) [1..] ++ [1#(n+1)]) :<=: (sign * b_i)
    p = Sparse (c1++c2)
    Optimal (_j,x) = simplex (Minimize (replicate n 0 ++ [1])) p (map Free [1..(n+1)])
l1SolveO :: Matrix Double -> Vector Double -> Vector Double
l1SolveO a b = fromList (take n x)
  where
    n = cols a
    m = rows a
    as = toRows a
    bs = toList b
    ks = [1..]
    c1 = zipWith3 (mk (1)) as bs ks
    c2 = zipWith3 (mk (1)) as bs ks
    mk sign a_i b_i k = (zipWith (#) (toList (scale sign a_i)) [1..] ++ [1#(k+n)]) :<=: (sign * b_i)
    p = Sparse (c1++c2)
    Optimal (_j,x) = simplex (Minimize (replicate n 0 ++ replicate m 1)) p (map Free [1..(n+m)])
l1SolveU :: Matrix Double -> Vector Double -> Vector Double
l1SolveU a y = fromList (take n x)
  where
    n = cols a
    c1 = map (\k ->  [ 1#k, 1#k+n] :<=: 0) [1..n]
    c2 = map (\k ->  [1#k, 1#k+n] :<=: 0) [1..n]
    c3 = zipWith (:==:) (map sp $ toRows a) (toList y)
    sp v = zipWith (#) (toList v) [1..]
    p = Sparse (c1 ++ c2 ++ c3)
    Optimal (_j,x) = simplex (Minimize (replicate n 0 ++ replicate n 1)) p (map Free [1..(2*n)])
l1Solve
    :: Double        
    -> Matrix Double 
    -> Vector Double 
    -> Vector Double 
l1Solve λ a b = fromList (take n x)
  where
    n = cols a
    m = rows a
    as = toRows a
    bs = toList b
    c1Res = zipWith3 (mkR (1)) as bs [1..m]
    c2Res = zipWith3 (mkR (1)) as bs [1..m]
    mkR sign a_i b_i k = (zipWith (#) (toList (scale sign a_i)) [1..] ++ [1#(k+2*n)]) :<=: (sign * b_i)
    c1Sol = map (\k ->  [ 1#k, 1#k+n] :<=: 0) [1..n]
    c2Sol = map (\k ->  [1#k, 1#k+n] :<=: 0) [1..n]
    p = Sparse (c1Res++c2Res++c1Sol++c2Sol)
    cost = replicate n 0 ++ replicate n λ ++ replicate m 1
    Optimal (_j,x) = simplex (Minimize cost) p (map Free [1..(2*n+m)])
l1SolveGT
    :: Double        
    -> Matrix Double 
    -> Vector Double 
    -> Vector Double 
l1SolveGT λ a b = fromList (take n x)
  where
    n = cols a
    m = rows a
    as = toRows a
    bs = toList b
    cRes = zipWith3 mkR as bs [1..m]
    mkR a_i b_i k = (zipWith (#) (toList a_i) [1..] ++ [1#(k+2*n)]) :>=: (b_i)
    c1Sol = map (\k ->  [ 1#k, 1#k+n] :<=: 0) [1..n]
    c2Sol = map (\k ->  [1#k, 1#k+n] :<=: 0) [1..n]
    p = Sparse (cRes++c1Sol++c2Sol)
    cost = replicate n 0 ++ replicate n λ ++ replicate m 1
    Optimal (_j,x) = simplex (Minimize cost) p (map Free [1..(2*n)])