text:
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-missing-export-lists #-}
module BenchMnistTools where

import Prelude

import           Control.Arrow ((***))
import           Control.DeepSeq (NFData)
import           Criterion.Main
import           Data.List.Index (imap)
import           Data.Proxy (Proxy (Proxy))
import qualified Data.Vector.Generic as V
import qualified Numeric.LinearAlgebra as HM
import           System.Random

import HordeAd
import HordeAd.Tool.MnistTools

mnistTrainBench2 :: forall r. ( NFData r, HasDelta r
                              , UniformRange r )
                 => String -> Int -> [MnistData r] -> Int -> Int
                 -> r
                 -> Benchmark
mnistTrainBench2 extraPrefix chunkLength xs widthHidden widthHidden2 gamma = do
  let nParams0 = fcnnMnistLen0 widthHidden widthHidden2
      params0Init = V.unfoldrExactN nParams0 (uniformR (-0.5, 0.5))
                    $ mkStdGen 33
      f = fcnnMnistLoss0 widthHidden widthHidden2
      chunk = take chunkLength xs
      grad c = fst $ sgd gamma f c (params0Init, V.empty, V.empty, V.empty)
      name = "" ++ extraPrefix
             ++ unwords [ "s" ++ show nParams0, "v0"
                        , "m0" ++ "=" ++ show nParams0 ]
  bench name $ nf grad chunk

mnistTestBench2
  :: forall r. (UniformRange r, HasDelta r)
  => String -> Int -> [MnistData r] -> Int -> Int -> Benchmark
mnistTestBench2 extraPrefix chunkLength xs widthHidden widthHidden2 = do
  let nParams0 = fcnnMnistLen0 widthHidden widthHidden2
      params0Init = V.unfoldrExactN nParams0 (uniformR (-0.5, 0.5))
                    $ mkStdGen 33
      chunk = take chunkLength xs
      score c = fcnnMnistTest0 (Proxy @r) widthHidden widthHidden2 c params0Init
      name = "test " ++ extraPrefix
             ++ unwords [ "s" ++ show nParams0, "v0"
                        , "m0" ++ "=" ++ show nParams0 ]
  bench name $ whnf score chunk

mnistTrainBGroup2 :: [MnistData Double] -> Int -> Benchmark
mnistTrainBGroup2 xs0 chunkLength =
  env (return $ take chunkLength xs0) $
  \ xs ->
  bgroup ("2-hidden-layer MNIST nn with samples: " ++ show chunkLength)
    [ mnistTestBench2 "30|10 " chunkLength xs 30 10  -- toy width
    , mnistTrainBench2 "30|10 " chunkLength xs 30 10 0.02
    , mnistTestBench2 "300|100 " chunkLength xs 300 100  -- ordinary width
    , mnistTrainBench2 "300|100 " chunkLength xs 300 100 0.02
    , mnistTestBench2 "500|150 " chunkLength xs 500 150  -- another common size
    , mnistTrainBench2 "500|150 " chunkLength xs 500 150 0.02
    ]

mnistTrainBGroup2500 :: [MnistData Double] -> Int -> Benchmark
mnistTrainBGroup2500 xs0 chunkLength =
  env (return (xs0, map (V.map realToFrac *** V.map realToFrac)
                    $ take chunkLength xs0)) $
  \ ~(xs, xsFloat) ->
  bgroup ("huge 2-hidden-layer MNIST nn with samples: " ++ show chunkLength)
    [ mnistTestBench2 "2500|750 " chunkLength xs 2500 750
        -- probably mostly wasted
    , mnistTrainBench2 "2500|750 " chunkLength xs 2500 750 0.02
    , mnistTestBench2 "(Float) 2500|750 " chunkLength xsFloat 2500 750
        -- Float test
    , mnistTrainBench2 "(Float) 2500|750 " chunkLength xsFloat 2500 750
                       (0.02 :: Float)
    ]

mnistTrainBench2V :: String -> Int -> [MnistData Double]
                  -> Int -> Int -> Double
                  -> Benchmark
mnistTrainBench2V extraPrefix chunkLength xs widthHidden widthHidden2 gamma = do
  let (nParams0, nParams1, _, _) = fcnnMnistLen1 widthHidden widthHidden2
      params0Init = HM.randomVector 33 HM.Uniform nParams0 - HM.scalar 0.5
      params1Init = V.fromList $
        imap (\i nPV -> HM.randomVector (33 + nPV + i) HM.Uniform nPV
                        - HM.scalar 0.5)
             nParams1
      f = fcnnMnistLoss1 widthHidden widthHidden2
      chunk = take chunkLength xs
      grad c = fst $ sgd gamma f c (params0Init, params1Init, V.empty, V.empty)
      totalParams = nParams0 + sum nParams1
      name = "" ++ extraPrefix
             ++ unwords [ "s" ++ show nParams0, "v" ++ show (length nParams1)
                        , "m0" ++ "=" ++ show totalParams ]
  bench name $ nf grad chunk

mnistTestBench2V :: String -> Int -> [MnistData Double] -> Int -> Int
                 -> Benchmark
mnistTestBench2V extraPrefix chunkLength xs widthHidden widthHidden2 = do
  let (nParams0, nParams1, _, _) = fcnnMnistLen1 widthHidden widthHidden2
      params0Init = HM.randomVector 33 HM.Uniform nParams0 - HM.scalar 0.5
      params1Init = V.fromList $
        imap (\i nPV -> HM.randomVector (33 + nPV + i) HM.Uniform nPV
                        - HM.scalar 0.5)
             nParams1
      chunk = take chunkLength xs
      score c = fcnnMnistTest1 widthHidden widthHidden2 c
                           (params0Init, params1Init)
      totalParams = nParams0 + sum nParams1
      name = "test " ++ extraPrefix
             ++ unwords [ "s" ++ show nParams0, "v" ++ show (length nParams1)
                        , "m0" ++ "=" ++ show totalParams ]
  bench name $ whnf score chunk

mnistTrainBGroup2V :: [MnistData Double] -> Int -> Benchmark
mnistTrainBGroup2V xs0 chunkLength =
  env (return $ take chunkLength xs0) $
  \ xs ->
  bgroup ("2-hidden-layer V MNIST nn with samples: " ++ show chunkLength)
    [ mnistTestBench2V "30|10 " chunkLength xs 30 10  -- toy width
    , mnistTrainBench2V "30|10 " chunkLength xs 30 10 0.02
    , mnistTestBench2V "300|100 " chunkLength xs 300 100  -- ordinary width
    , mnistTrainBench2V "300|100 " chunkLength xs 300 100 0.02
    , mnistTestBench2V "500|150 " chunkLength xs 500 150  -- another common size
    , mnistTrainBench2V "500|150 " chunkLength xs 500 150 0.02
    ]

mnistTrainBench2L :: String -> Int -> [MnistData Double] -> Int -> Int
                  -> Double
                  -> Benchmark
mnistTrainBench2L extraPrefix chunkLength xs widthHidden widthHidden2 gamma = do
  let ((nParams0, nParams1, nParams2, _), totalParams, _reach, parameters0) =
        initializerFixed 33 0.5 (fcnnMnistLen2 widthHidden widthHidden2)
      -- Using the fused version to benchmark against the manual gradient
      -- from backprop that uses it at least in its forward pass,
      -- not againts the derived gradients that are definitively slower.
      f = fcnnMnistLossFused2
      chunk = take chunkLength xs
      grad c = fst $ sgd gamma f c parameters0
      name = "" ++ extraPrefix
             ++ unwords [ "s" ++ show nParams0, "v" ++ show nParams1
                        , "m" ++ show nParams2
                          ++ "=" ++ show totalParams ]
  bench name $ nf grad chunk

mnistTestBench2L :: String -> Int -> [MnistData Double] -> Int -> Int
                 -> Benchmark
mnistTestBench2L extraPrefix chunkLength xs widthHidden widthHidden2 = do
  let ((nParams0, nParams1, nParams2, _), totalParams, _reach, parameters0) =
        initializerFixed 33 0.5 (fcnnMnistLen2 widthHidden widthHidden2)
      chunk = take chunkLength xs
      score c = fcnnMnistTest2 c parameters0
      name = "test " ++ extraPrefix
             ++ unwords [ "s" ++ show nParams0, "v" ++ show nParams1
                        , "m" ++ show nParams2
                          ++ "=" ++ show totalParams ]
  bench name $ whnf score chunk

mnistTrainBGroup2L :: [MnistData Double] -> Int -> Benchmark
mnistTrainBGroup2L xs0 chunkLength =
  env (return $ take chunkLength xs0) $
  \ xs ->
  bgroup ("2-hidden-layer L MNIST nn with samples: " ++ show chunkLength)
    [ mnistTestBench2L "30|10 " chunkLength xs 30 10  -- toy width
    , mnistTrainBench2L "30|10 " chunkLength xs 30 10 0.02
    , mnistTestBench2L "300|100 " chunkLength xs 300 100  -- ordinary width
    , mnistTrainBench2L "300|100 " chunkLength xs 300 100 0.02
    , mnistTestBench2L "500|150 " chunkLength xs 500 150  -- another common size
    , mnistTrainBench2L "500|150 " chunkLength xs 500 150 0.02
    ]


text:
{-# LANGUAGE FlexibleContexts #-}

module AI.Visualizations
( networkHistogram
, weightList
, biasList
) where

import           AI.Layer
import           AI.Network
import           AI.Network.FeedForwardNetwork
import           AI.Neuron
import           Numeric.LinearAlgebra

import           Data.Foldable                      (foldMap)
import           GHC.Float
import           Graphics.Histogram
import           AI.Trainer

weightList :: FeedForwardNetwork -> [Double]
weightList = toList . flatten . weightMatrix <=< layers

biasList :: FeedForwardNetwork -> [Double]
biasList = toList . biasVector <=< layers

networkHistogram :: FilePath -> (FeedForwardNetwork -> [Double]) -> FeedForwardNetwork -> IO ()
networkHistogram filename listFunction n = do
  let hist = histogram binSturges (listFunction n)
  plot filename hist
  return ()

ext: hs

max_stars_repo_name: jbarrow/LambdaNet

max_issues_repo_name: jbarrow/LambdaNet

max_forks_repo_name: jbarrow/LambdaNet


text:
import Criterion.Main
import FFT.Orig
import FFT.FFTControl
import FFT.FFTData
import FFT.DFTData
import FFT.DFTControl
import FFT.Samples
import Data.Complex
import System.Environment

main = defaultMain [
                bgroup "dft-data" [
                    bench "orig" $ nf sum (dft (samples 1 1000)),
                    bench "foldMap" $ nf sum (dftFoldMap (samples 1 1000))
                ],
                bgroup "dft-control" [

                ],
                bgroup "fft-control" [
                    bench "orig" $ nf sum (fft (samples 1 100000)),
                    bench "bflySPipeline" $ nf sum (fftbflySPipeline (samples 1 100000))
                ],
                bgroup "fft-data" [
                ]
    ]

max_stars_repo_name: BNJHope/parallel-fourier-transforms

max_issues_repo_name: BNJHope/parallel-fourier-transforms

max_forks_repo_name: BNJHope/parallel-fourier-transforms


text:
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}
{-# OPTIONS_GHC -Wno-deprecations #-}
module BlueRipple.Model.PreferenceBayes
  (
    -- * MLE
    cgOptimize
  , cgOptimizeAD
  , invFisher
  , mleCovEigens
  , variances
  , covar
  , correlFromCov

    -- * MCMC
  , Sample
  , Chain
  , runMany
    -- * Re-exports
  , dispf
  , disps
  )
where

import qualified Statistics.Types              as S
import qualified Control.Foldl                 as FL
import           Control.Lens.At                ( IxValue
                                                , Index
                                                , Ixed
                                                )
import           Control.Lens.Indexed           ( FunctorWithIndex )
import           Control.Monad                  ( sequence )

import qualified Numeric.AD                    as AD
import qualified Numeric.LinearAlgebra         as LA
import           Numeric.LinearAlgebra          ( dispf
                                                , disps
                                                )
import           Numeric.MathFunctions.Constants
                                                ( m_ln_sqrt_2_pi )
import qualified Numeric.MCMC                  as MC
import Numeric (log)

import           Math.Gamma                     ( gamma
                                                , Gamma
                                                )
import           System.Random                  ( randomRIO )
import qualified Control.Concurrent            as CC
import qualified Control.Concurrent.MVar       as CC
import qualified Data.Vector.Unboxed           as VU
import qualified Data.Vector.Storable          as VS
import qualified Data.Vector.Generic           as VG
import qualified Data.Vector                   as VB

import qualified Numeric.Optimization.Algorithms.HagerZhang05
                                               as CG

import qualified Numeric.Optimization.Algorithms.HagerZhang05.AD
                                               as CGAD

newtype ObservedVote = ObservedVote { dem :: Int}

data Pair a b = Pair !a !b

binomialNormalParams :: RealFrac a => VB.Vector Int -> VB.Vector a -> (a, a)
binomialNormalParams turnoutCounts demProbs =
  let np = VB.zip turnoutCounts demProbs
      meanVarUpdate :: RealFrac a => Pair a a -> (Int, a) -> Pair a a
      meanVarUpdate (Pair m v) (n, p) =
        let m' = realToFrac n * p in Pair (m + m') (v + m' * (1 - p))
      foldMeanVar = FL.Fold meanVarUpdate (Pair 0 0) id
      Pair m v    = FL.fold foldMeanVar np
  in  (m, v)

logBinomialObservedVote
  :: (RealFrac a, Floating a) => VB.Vector a -> (Int, VB.Vector Int) -> a
logBinomialObservedVote demProbs (demVote, turnoutCounts) =
  let (m, v) = binomialNormalParams turnoutCounts demProbs
  in  negate $ log v + ((realToFrac demVote - m) ^ 2 / (2 * v))

gradLogBinomialObservedVote
  :: (Floating a, RealFrac a)
  => VB.Vector a
  -> (Int, VB.Vector Int)
  -> VB.Vector a
gradLogBinomialObservedVote demProbs (demVote, turnoutCounts) =
  let (m, v) = binomialNormalParams turnoutCounts demProbs
      np     = VB.zip turnoutCounts demProbs
      dv     = fmap (\(n, p) -> let n' = realToFrac n in n' * (1 - 2 * p)) np
      dm     = turnoutCounts
      dmv    = VB.zip dm dv
      a1     = negate (1 / v) -- d (log v)
      a2     = (realToFrac demVote - m)
      a3     = (a2 * a2) / (2 * v * v)
      a4     = (a2 / v)
  in  fmap (\(dm, dv) -> (a1 + a3) * dv + a4 * realToFrac dm) dmv

logBinomialObservedVotes
  :: (Functor f, Foldable f, Floating a, RealFrac a)
  => f (Int, VB.Vector Int)
  -> VB.Vector a
  -> a
logBinomialObservedVotes votesAndTurnout demProbs =
  FL.fold FL.sum $ fmap (logBinomialObservedVote demProbs) votesAndTurnout

gradLogBinomialObservedVotes
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> VB.Vector Double
gradLogBinomialObservedVotes votesAndTurnout demProbs =
  let
    n           = VG.length demProbs
    indexVector = VG.generate n id
    sumEach =
      sequenceA $ (\n -> FL.premap (VG.! n) (FL.sum @Double)) <$> indexVector
  in
    FL.fold sumEach
      $ fmap (gradLogBinomialObservedVote demProbs) votesAndTurnout

cgOptimize
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> IO (VS.Vector Double, CG.Result, CG.Statistics)
cgOptimize votesAndVoters guess = do
  let params = CG.defaultParameters { CG.printFinal  = False
                                    , CG.printParams = False
                                    , CG.verbose     = CG.Quiet
                                    }
      grad_tol = 0.0000001
  CG.optimize
    params
    grad_tol
    guess
    (CG.VFunction (negate . logBinomialObservedVotes votesAndVoters))
    (CG.VGradient (fmap negate . gradLogBinomialObservedVotes votesAndVoters))
    Nothing

cgOptimizeAD
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> IO (VB.Vector Double, CG.Result, CG.Statistics)
cgOptimizeAD votesAndVoters guess = do
  let params = CG.defaultParameters { CG.printFinal  = False
                                    , CG.printParams = False
                                    , CG.verbose     = CG.Quiet
                                    }
      grad_tol = 0.0000001
  CGAD.optimize params
                grad_tol
                guess
                (negate . logBinomialObservedVotes votesAndVoters)

-- I'm not sure about row/column order her. But it doesn't
-- matter since the Hessian is symmetric.
hessianLL
  :: (Foldable f, Functor f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> LA.Matrix Double
hessianLL votesAndVoters x =
  LA.fromRows $ fmap VS.convert $ VB.toList $ AD.hessian
    (negate . logBinomialObservedVotes votesAndVoters)
    x

invFisher
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> LA.Matrix Double
invFisher votesAndVoters x = LA.inv $ hessianLL votesAndVoters x

variances
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> LA.Vector Double
variances votesAndVoters x = LA.takeDiag $ invFisher votesAndVoters x

covar
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> LA.Matrix Double
covar = invFisher

correlFromCov :: LA.Matrix Double -> LA.Matrix Double
correlFromCov cov =
  let vars = LA.takeDiag cov
      mISD = LA.diag $ LA.cmap (\x -> 1 / sqrt x) vars
  in  mISD LA.<> cov LA.<> mISD

correl
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> LA.Matrix Double
correl votesAndVoters x =
  let cov          = invFisher votesAndVoters x
      sds          = LA.cmap sqrt $ LA.takeDiag cov
      (rows, cols) = LA.size cov
      rho n m = cov `LA.atIndex` (n, m) / ((sds LA.! n) * (sds LA.! m))
  in  LA.assoc
        (rows, cols)
        0
        [ ((n, m), rho n m) | n <- [0 .. (rows - 1)], m <- [0 .. (cols - 1)] ]

mleCovEigens
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> VB.Vector Double
  -> (LA.Vector Double, LA.Matrix Double)
mleCovEigens votesAndVoters x =
  LA.eigSH $ LA.trustSym $ invFisher votesAndVoters x

betaDist :: (Floating a, RealFrac a, Gamma a) => a -> a -> a -> a
betaDist alpha beta x =
  let b = gamma (alpha + beta) / (gamma alpha + gamma beta)
  in  if (x >= 0) && (x <= 1)
        then b * (x ** (alpha - 1)) * ((1 - x) ** (beta - 1))
        else 0

logBetaDist :: (Floating a, RealFrac a, Gamma a) => a -> a -> a -> a
logBetaDist alpha beta x =
  let lb = log $ gamma (alpha + beta) / (gamma alpha + gamma beta)
  in  lb + (alpha - 1) * log x + (beta - 1) * log (1 - x)

betaPrior :: (Floating a, RealFrac a, Gamma a) => a -> a -> VB.Vector a -> a
betaPrior a b xs = FL.fold FL.product $ fmap (betaDist a b) xs

{-
--logBetaPrior :: Double -> Double -> [Double] -> Double
--logBetaPrior = FL.fold FL.product $ fmap (logBetabDist a b) xs

f :: [(Int, [Int])] -> [Double] -> Double
f votesAndTurnout demProbs =
  let v = demProbs
  in  (exp $ logProbObservedVotes votesAndTurnout v) * (betaPrior 2 2 v)
-}

logBinomialWithPrior
  :: (Functor f, Foldable f, Floating a, RealFrac a, Gamma a)
  => f (Int, VB.Vector Int)
  -> VB.Vector a
  -> a
logBinomialWithPrior votesAndTurnout demProbs =
  let x = demProbs
  in  logBinomialObservedVotes votesAndTurnout x + log (betaPrior 2 2 x)

type Sample = VB.Vector Double
type Chain = [Sample]

-- TODO: withSystemRandom is deprecated in mwc-random but comes from "declarative" so would be a pain to fix.
runMCMC
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> Int
  -> Sample
  -> IO Chain
runMCMC votesAndTurnout numIters start =
  fmap (fmap MC.chainPosition) . MC.withSystemRandom . MC.asGenIO $ MC.chain
    numIters
    start
    (MC.frequency [(1, MC.hamiltonian 0.0001 10), (1, MC.hamiltonian 0.00001 5)]
    )
    (MC.Target (logBinomialWithPrior votesAndTurnout)
               (Just $ gradLogBinomialObservedVotes votesAndTurnout)
    )

-- launch each action on its own thread, writing the result to an MVar.
-- as each MVar is written to,
-- place each result in the appropriate place in the structure.
-- return the new structure when all results are available.
sequenceConcurrently :: Traversable t => t (IO a) -> IO (t a)
sequenceConcurrently actions = do
  let f :: IO a -> IO (CC.MVar a, CC.ThreadId)
      f action = do
        mvar     <- newEmptyMVar
        threadId <- CC.forkIO (action >>= putMVar mvar)
        return (mvar, threadId)
      g :: (CC.MVar a, CC.ThreadId) -> IO a
      g (mvar, _) = takeMVar mvar
  forked <- traverse f actions -- IO (t (MVar a, ThreadId))
  traverse g forked

runMany
  :: (Functor f, Foldable f)
  => f (Int, VB.Vector Int)
  -> Int
  -> Int
  -> Int
  -> Int
  -> IO [Chain]
runMany votesAndTurnout nParams nChains nSamplesPerChain nBurnPerChain = do
  let
    randomStart :: Int -> IO Sample
    randomStart n = VG.fromList <$> replicateM n (randomRIO (0, 1))
    randomStarts :: Int -> Int -> IO [Sample]
    randomStarts n m = replicateM m (randomStart n)
    doEach =
      fmap (drop nBurnPerChain) . runMCMC votesAndTurnout nSamplesPerChain
  starts <- randomStarts nParams nChains
  sequenceConcurrently $ fmap doEach starts

{-
data Normal = Normal { m :: Double, v :: Double } deriving (Show)

instance Semigroup Normal where
  (Normal m1 v1) <> (Normal m2 v2) = Normal (m1 + m2) (v1 + v2)

logNormalObservedVote :: [Normal] -> (Int, [Int]) -> Double
logNormalObservedVote demProbs (demVote, turnoutCounts) =
  let Normal m' v' = mconcat $ fmap (\(t,Normal m v) -> Normal (t*m) (v*m))$ zip turnoutCounts demProbs
  in  negate $ log v'  + ((realToFrac demVote - m')) ^ 2 / (2 * v'))

gradLogNormalObservedVote :: [Normal] -> (Int, [Int]) -> [Normal]
gradLogNormalObservedVote demProbs (demVote, turnoutCounts) =
  let Normal m' v' = mconcat $ fmap (\(t,Normal m v) -> Normal (t*m) (v*m))$ zip turnoutCounts demProbs
      np     = zip turnoutCounts demProbs
      dv     = fmap (\(n, p) -> let n' = realToFrac n in n' * (1 - 2 * p)) np
      dm     = turnoutCounts
      dmv    = zip dm dv
      a1     = negate (1 / v) -- d (log v)
      a2     = (realToFrac demVote - m)
      a3     = (a2 * a2) / (2 * v * v)
      a4     = (a2 / v)
  in  fmap (\(dm, dv) -> (a1 + a3) * dv + a4 * realToFrac dm) dmv

logBinomialObservedVotes :: [(Int, [Int])] -> [Double] -> Double
logBinomialObservedVotes votesAndTurnout demProbs =
  FL.fold FL.sum $ fmap (logBinomialObservedVote demProbs) votesAndTurnout

gradLogBinomialObservedVotes :: [(Int, [Int])] -> [Double] -> [Double]
gradLogBinomialObservedVotes votesAndTurnout demProbs =
  let n = length demProbs
      sumEach =
        sequenceA
          $ fmap (\n -> FL.premap (!! n) (FL.sum @Double))
          $ [0 .. (n - 1)]
  in  FL.fold sumEach $ fmap (gradLogBinomialObservedVote demProbs) votesAndTurnout

-}
{-
--gradLogProbObservedVotes2 :: [(Int, [Int])] -> [Double] -> [Double]
gradLogProbObservedVotes2 votesAndTurnout =
  grad (logProbObservedVotes votesAndTurnout)
-}

{-
data VPSummary = VPSummary { mean :: Double, stDev :: Double, rHat :: Double } deriving (Show)

summarize :: (Sample -> Double) -> [Chain] -> VPSummary -- FL.Fold Chain VPSummary
summarize integrandF chains =
  -- build up the fold
  let n = (length $ head chains) `div` 2
      splitChains :: [Chain]
      splitChains =
        concat $ fmap (\c -> let (a, b) = splitAt n c in [a, b]) chains
      meanVarF = (,) <$> FL.mean <*> FL.variance
      meanVars = fmap (FL.fold (FL.premap integrandF meanVarF)) splitChains
      bVar     = FL.fold (FL.premap fst FL.variance) meanVars -- variance of the means
      wVar     = FL.fold (FL.premap snd FL.mean) meanVars -- mean of the variances
      v        = (realToFrac n / realToFrac (n + 1)) * wVar + bVar
      rhat     = sqrt (v / wVar)
  in  VPSummary (FL.fold (FL.premap fst FL.mean) meanVars)
                (FL.fold (FL.premap snd FL.mean) meanVars)
                rhat

-- . foldTo (meanOfVariances, varianceOfMeans) . fmap (compute meanVar . fmap integrandF) . splitChains
-}

max_stars_repo_name: blueripple/preference-model

max_issues_repo_name: blueripple/preference-model

max_forks_repo_name: blueripple/preference-model


text:
module Commands where

import Statistics
import Expense
import Parser
import Extras
import Errors
import Data.List
import Data.Maybe

-- arguments -> original -> filtered -> message/result
type CmdFunc = [String] -> [Expense] -> [Expense] -> Either String [Expense]

getCommandFunction :: String -> Maybe CmdFunc
getCommandFunction cmd = lookup cmd $ commandList

commandList :: [(String, CmdFunc)]
commandList = [("ls",   lsElements),
               -- ("add",  addElement),
               ("show", showElements)]

showElements :: CmdFunc
showElements []           _ _ = Left $ show $ MissingArgs "show"
showElements ["tags"]     _ l = Left $ tagStats l
showElements ["stats"]    o l = Left $ showStats o l
showElements ["months"]   _ l = Left $ monthStats l
showElements ("tags":_)   _ _ = Left $ show $ ExcessiveArgs "show tags"
showElements ("stats":_)  _ _ = Left $ show $ ExcessiveArgs "show stats"
showElements ("months":_) _ _ = Left $ show $ ExcessiveArgs "show months"
showElements (_:_)        _ _ = Left $ show $ UnknownArg "show"

addElement :: CmdFunc
addElement args _ expL
  | argsLen < 3 = Left $ show $ MissingArgs "add"
  | argsLen > 3 = Left $ show $ ExcessiveArgs "add"
  | otherwise   = case parseExpense $ unwords args of
    Right es -> Left  $ show es
    Left  e  -> Right $ resExpL e
  where argsLen   = length args
        resExpL e = expL ++ [e]

lsCommandList :: [(String, CmdFunc)]
lsCommandList = [("tags",   lsWithTags),
                 ("dates",  lsWithDates),
                 ("months", lsWithMonths),
                 ("years",  lsWithYears)]

lsElements :: CmdFunc
lsElements []  _ expL = Right expL
lsElements [x] _ _    = case lookup x lsCommandList of
  Nothing -> Left $ show $ UnknownArg "ls"
  Just _  -> Left $ show $ MissingArgs x
lsElements (x:xs) _ expL = case lookup x lsCommandList of
  Nothing -> lsElements [x] [] []
  Just f  -> f xs [] expL

lsWithDates :: CmdFunc
lsWithDates dates_ _ l
  | (length $ filter (== []) $ dates1) > 0 = Left $ show ParserErrDates
  | (length $ resL) > 0                    = Right resL
  | otherwise                              = Left $ show NoEntries
  where dates1 = map (maybeToList . parseDate) dates_
        dates  = map (!! 0) dates1
        resL   = foldl (\a e -> a ++ filterByDate e l) [] dates

lsWithMonths :: CmdFunc
lsWithMonths months_ _ expL
  | (length $ filter (== []) $ months1) > 0 = Left $ show ParserErrMonths
  | (length $ resL) > 0                     = Right resL
  | otherwise                               = Left $ show NoEntries
  where months1 = map (maybeToList . parseMonth) months_
        months  = map (!! 0) months1
        resL    = filter (\e -> (yearOf e `elem` map yearFrom months) &&
                                (monthOf e `elem` map monthFrom months)) expL

lsWithYears :: CmdFunc
lsWithYears years_ _ expL
  | (length $ filter (== []) $ years1) > 0 = Left $ show ParserErrYears
  | (length $ resL) > 0                    = Right resL
  | otherwise                              = Left $ show NoEntries
  where years1 = map (maybeToList . parseYear) years_
        years  = map (!! 0) years1
        resL   = filter (\e -> yearOf e `elem` map yearFrom years) expL

lsWithTags :: CmdFunc
lsWithTags tags_ _ l =
  if (length $ resL) > 0 then Right $ sort resL else Left $ show NoEntries
  where resL = foldl (\a e -> a ++ filterByTag e l) [] tags_

max_stars_repo_path: Projects/Personal Expenses Tracker (C)/archive/pet_haskell_master_complete/Commands.hs

max_stars_repo_name: fredmorcos/attic

max_issues_repo_name: fredmorcos/attic

max_forks_repo_name: fredmorcos/attic


text:
{-# LANGUAGE TemplateHaskell #-}
module Myelin.Nest.Types.Synapse where
{-

This file is autogenerated to regenerate it execute

python python/nest/generate.py > Types.hs

-}

import Control.Lens
import Data.Aeson.TH

import Numeric.LinearAlgebra

type Ndarray = [Float]
type Tuple = [Float]
type Str = String

-- | Representation of the synapse types available in Nest
data Synapse =
    BernoulliSynapse {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _p_transmit :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | BernoulliSynapseLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _p_transmit :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | ContDelaySynapse {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | ContDelaySynapseHpc {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | ContDelaySynapseLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | DiffusionConnection {
        _delay :: Float,
        _diffusion_factor :: Float,
        _drift_factor :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | DiffusionConnectionLbl {
        _delay :: Float,
        _diffusion_factor :: Float,
        _drift_factor :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | GapJunction {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | GapJunctionLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | HtSynapse {
        _delay :: Float,
        _delta_p :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _p :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_p :: Float,
        _weight :: Float
    }
    | HtSynapseHpc {
        _delay :: Float,
        _delta_p :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _p :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_p :: Float,
        _weight :: Float
    }
    | HtSynapseLbl {
        _delay :: Float,
        _delta_p :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _p :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_p :: Float,
        _weight :: Float
    }
    | QuantalStpSynapse {
        _n :: Float,
        _a :: Int,
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float
    }
    | QuantalStpSynapseHpc {
        _n :: Float,
        _a :: Int,
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float
    }
    | QuantalStpSynapseLbl {
        _n :: Float,
        _a :: Int,
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_fac :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float
    }
    | RateConnectionDelayed {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | RateConnectionDelayedLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | RateConnectionInstantaneous {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | RateConnectionInstantaneousLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | StaticSynapse {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | StaticSynapseHomW {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | StaticSynapseHomWHpc {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | StaticSynapseHomWLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | StaticSynapseHpc {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _weight :: Float
    }
    | StaticSynapseLbl {
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _weight :: Float
    }
    | StdpDopamineSynapse {
        _n :: Float,
        _a_minus :: Float,
        _a_plus :: Float,
        _b :: Float,
        _c :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_c :: Float,
        _tau_n :: Float,
        _tau_plus :: Float,
        _vt :: Int,
        _weight :: Float,
        _wmax :: Float,
        _wmin :: Float
    }
    | StdpDopamineSynapseHpc {
        _n :: Float,
        _a_minus :: Float,
        _a_plus :: Float,
        _b :: Float,
        _c :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_c :: Float,
        _tau_n :: Float,
        _tau_plus :: Float,
        _vt :: Int,
        _weight :: Float,
        _wmax :: Float,
        _wmin :: Float
    }
    | StdpDopamineSynapseLbl {
        _n :: Float,
        _a_minus :: Float,
        _a_plus :: Float,
        _b :: Float,
        _c :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_c :: Float,
        _tau_n :: Float,
        _tau_plus :: Float,
        _vt :: Int,
        _weight :: Float,
        _wmax :: Float,
        _wmin :: Float
    }
    | StdpFacetshwSynapseHom {
        _a_acausal :: Float,
        _a_causal :: Float,
        _a_thresh_th :: Float,
        _a_thresh_tl :: Float,
        _configbit_0 :: Ndarray,
        _configbit_1 :: Ndarray,
        _delay :: Float,
        _driver_readout_time :: Float,
        _has_delay :: Bool,
        _init_flag :: Bool,
        _lookuptable_0 :: Ndarray,
        _lookuptable_1 :: Ndarray,
        _lookuptable_2 :: Ndarray,
        _next_readout_time :: Float,
        _no_synapses :: Int,
        _num_connections :: Int,
        _readout_cycle_duration :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _reset_pattern :: Ndarray,
        _synapse_id :: Int,
        _synapses_per_driver :: Int,
        _tau_minus_stdp :: Float,
        _tau_plus :: Float,
        _weight :: Float,
        _weight_per_lut_entry :: Float,
        _wmax :: Float
    }
    | StdpFacetshwSynapseHomHpc {
        _a_acausal :: Float,
        _a_causal :: Float,
        _a_thresh_th :: Float,
        _a_thresh_tl :: Float,
        _configbit_0 :: Ndarray,
        _configbit_1 :: Ndarray,
        _delay :: Float,
        _driver_readout_time :: Float,
        _has_delay :: Bool,
        _init_flag :: Bool,
        _lookuptable_0 :: Ndarray,
        _lookuptable_1 :: Ndarray,
        _lookuptable_2 :: Ndarray,
        _next_readout_time :: Float,
        _no_synapses :: Int,
        _num_connections :: Int,
        _readout_cycle_duration :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _reset_pattern :: Ndarray,
        _synapse_id :: Int,
        _synapses_per_driver :: Int,
        _tau_minus_stdp :: Float,
        _tau_plus :: Float,
        _weight :: Float,
        _weight_per_lut_entry :: Float,
        _wmax :: Float
    }
    | StdpFacetshwSynapseHomLbl {
        _a_acausal :: Float,
        _a_causal :: Float,
        _a_thresh_th :: Float,
        _a_thresh_tl :: Float,
        _configbit_0 :: Ndarray,
        _configbit_1 :: Ndarray,
        _delay :: Float,
        _driver_readout_time :: Float,
        _has_delay :: Bool,
        _init_flag :: Bool,
        _lookuptable_0 :: Ndarray,
        _lookuptable_1 :: Ndarray,
        _lookuptable_2 :: Ndarray,
        _next_readout_time :: Float,
        _no_synapses :: Int,
        _num_connections :: Int,
        _readout_cycle_duration :: Float,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _reset_pattern :: Ndarray,
        _synapse_id :: Int,
        _synapse_label :: Int,
        _synapses_per_driver :: Int,
        _tau_minus_stdp :: Float,
        _tau_plus :: Float,
        _weight :: Float,
        _weight_per_lut_entry :: Float,
        _wmax :: Float
    }
    | StdpPlSynapseHom {
        _lambda :: Float,
        _mu :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _weight :: Float
    }
    | StdpPlSynapseHomHpc {
        _lambda :: Float,
        _mu :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _weight :: Float
    }
    | StdpPlSynapseHomLbl {
        _lambda :: Float,
        _mu :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_plus :: Float,
        _weight :: Float
    }
    | StdpSynapse {
        _lambda :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _mu_minus :: Float,
        _mu_plus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpSynapseHom {
        _lambda :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _mu_minus :: Float,
        _mu_plus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpSynapseHomHpc {
        _lambda :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _mu_minus :: Float,
        _mu_plus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpSynapseHomLbl {
        _lambda :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _mu_minus :: Float,
        _mu_plus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_plus :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpSynapseHpc {
        _lambda :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _mu_minus :: Float,
        _mu_plus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpSynapseLbl {
        _lambda :: Float,
        _alpha :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _mu_minus :: Float,
        _mu_plus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_plus :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpTripletSynapse {
        _aminus :: Float,
        _aminus_triplet :: Float,
        _aplus :: Float,
        _aplus_triplet :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _kplus_triplet :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _tau_plus_triplet :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpTripletSynapseHpc {
        _aminus :: Float,
        _aminus_triplet :: Float,
        _aplus :: Float,
        _aplus_triplet :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _kplus_triplet :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_plus :: Float,
        _tau_plus_triplet :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | StdpTripletSynapseLbl {
        _aminus :: Float,
        _aminus_triplet :: Float,
        _aplus :: Float,
        _aplus_triplet :: Float,
        _delay :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _kplus_triplet :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_plus :: Float,
        _tau_plus_triplet :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | Tsodyks2Synapse {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float
    }
    | Tsodyks2SynapseHpc {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float
    }
    | Tsodyks2SynapseLbl {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_fac :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float
    }
    | TsodyksSynapse {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_psc :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float,
        _y :: Float
    }
    | TsodyksSynapseHom {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_psc :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float,
        _y :: Float
    }
    | TsodyksSynapseHomHpc {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_psc :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float,
        _y :: Float
    }
    | TsodyksSynapseHomLbl {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_fac :: Float,
        _tau_psc :: Float,
        _tau_rec :: Float,
        -- _u :: Float,
        _weight :: Float,
        _x :: Float,
        _y :: Float
    }
    | TsodyksSynapseHpc {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau_fac :: Float,
        _tau_psc :: Float,
        _tau_rec :: Float,
        -- _U :: Float,
        _weight :: Float,
        _x :: Float,
        _y :: Float
    }
    | TsodyksSynapseLbl {
        _delay :: Float,
        _u :: Float,
        _has_delay :: Bool,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau_fac :: Float,
        _tau_psc :: Float,
        _tau_rec :: Float,
        -- _ :: Float,
        _weight :: Float,
        _x :: Float,
        _y :: Float
    }
    | VogelsSprekelerSynapse {
        _alpha :: Float,
        _delay :: Float,
        _eta :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | VogelsSprekelerSynapseHpc {
        _alpha :: Float,
        _delay :: Float,
        _eta :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _tau :: Float,
        _weight :: Float,
        _wmax :: Float
    }
    | VogelsSprekelerSynapseLbl {
        _alpha :: Float,
        _delay :: Float,
        _eta :: Float,
        _has_delay :: Bool,
        _kplus :: Float,
        _num_connections :: Int,
        _receptor_type :: Int,
        _requires_symmetric :: Bool,
        _synapse_label :: Int,
        _tau :: Float,
        _weight :: Float,
        _wmax :: Float
    } deriving (Show, Read, Eq, Ord)

deriveJSON defaultOptions ''Synapse
makeLenses ''Synapse
makePrisms ''Synapse

bernoulli_synapse = BernoulliSynapse {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _p_transmit = 1.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
bernoulli_synapse_lbl = BernoulliSynapseLbl {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _p_transmit = 1.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 1.0
}
cont_delay_synapse = ContDelaySynapse {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
cont_delay_synapse_hpc = ContDelaySynapseHpc {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
cont_delay_synapse_lbl = ContDelaySynapseLbl {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 1.0
}
diffusion_connection = DiffusionConnection {
    _delay = 1.0,
    _diffusion_factor = 1.0,
    _drift_factor = 1.0,
    _has_delay = False,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 0.0
}
diffusion_connection_lbl = DiffusionConnectionLbl {
    _delay = 1.0,
    _diffusion_factor = 1.0,
    _drift_factor = 1.0,
    _has_delay = False,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 0.0
}
gap_junction = GapJunction {
    _delay = 1.0,
    _has_delay = False,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = True,
    _weight = 1.0
}
gap_junction_lbl = GapJunctionLbl {
    _delay = 1.0,
    _has_delay = False,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = True,
    _synapse_label = -1,
    _weight = 1.0
}
ht_synapse = HtSynapse {
    _delay = 1.0,
    _delta_p = 0.125,
    _has_delay = True,
    _num_connections = 0,
    _p = 1.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_p = 500.0,
    _weight = 1.0
}
ht_synapse_hpc = HtSynapseHpc {
    _delay = 1.0,
    _delta_p = 0.125,
    _has_delay = True,
    _num_connections = 0,
    _p = 1.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_p = 500.0,
    _weight = 1.0
}
ht_synapse_lbl = HtSynapseLbl {
    _delay = 1.0,
    _delta_p = 0.125,
    _has_delay = True,
    _num_connections = 0,
    _p = 1.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_p = 500.0,
    _weight = 1.0
}
quantal_stp_synapse = QuantalStpSynapse {
    _n = 1,
    _a = 1,
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 10.0,
    _tau_rec = 800.0,
    _weight = 1.0
}
quantal_stp_synapse_hpc = QuantalStpSynapseHpc {
    _n = 1,
    _a = 1,
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 10.0,
    _tau_rec = 800.0,
    _weight = 1.0
}
quantal_stp_synapse_lbl = QuantalStpSynapseLbl {
    _n = 1,
    _a = 1,
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_fac = 10.0,
    _tau_rec = 800.0,
    _weight = 1.0
}
rate_connection_delayed = RateConnectionDelayed {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
rate_connection_delayed_lbl = RateConnectionDelayedLbl {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 1.0
}
rate_connection_instantaneous = RateConnectionInstantaneous {
    _delay = 1.0,
    _has_delay = False,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
rate_connection_instantaneous_lbl = RateConnectionInstantaneousLbl {
    _delay = 1.0,
    _has_delay = False,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 1.0
}
static_synapse = StaticSynapse {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
static_synapse_hom_w = StaticSynapseHomW {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
static_synapse_hom_w_hpc = StaticSynapseHomWHpc {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
static_synapse_hom_w_lbl = StaticSynapseHomWLbl {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 1.0
}
static_synapse_hpc = StaticSynapseHpc {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _weight = 1.0
}
static_synapse_lbl = StaticSynapseLbl {
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _weight = 1.0
}
stdp_dopamine_synapse = StdpDopamineSynapse {
    _n = 0.0,
    _a_minus = 1.5,
    _a_plus = 1.0,
    _b = 0.0,
    _c = 0.0,
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_c = 1000.0,
    _tau_n = 200.0,
    _tau_plus = 20.0,
    _vt = -1,
    _weight = 1.0,
    _wmax = 200.0,
    _wmin = 0.0
}
stdp_dopamine_synapse_hpc = StdpDopamineSynapseHpc {
    _n = 0.0,
    _a_minus = 1.5,
    _a_plus = 1.0,
    _b = 0.0,
    _c = 0.0,
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_c = 1000.0,
    _tau_n = 200.0,
    _tau_plus = 20.0,
    _vt = -1,
    _weight = 1.0,
    _wmax = 200.0,
    _wmin = 0.0
}
stdp_dopamine_synapse_lbl = StdpDopamineSynapseLbl {
    _n = 0.0,
    _a_minus = 1.5,
    _a_plus = 1.0,
    _b = 0.0,
    _c = 0.0,
    _delay = 1.0,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_c = 1000.0,
    _tau_n = 200.0,
    _tau_plus = 20.0,
    _vt = -1,
    _weight = 1.0,
    _wmax = 200.0,
    _wmin = 0.0
}
stdp_facetshw_synapse_hom = StdpFacetshwSynapseHom {
    _a_acausal = 0.0,
    _a_causal = 0.0,
    _a_thresh_th = 21.835,
    _a_thresh_tl = 21.835,
    _configbit_0 = [0, 0, 1, 0],
    _configbit_1 = [0, 1, 0, 0],
    _delay = 1.0,
    _driver_readout_time = 15.0,
    _has_delay = True,
    _init_flag = False,
    _lookuptable_0 = [2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15],
    _lookuptable_1 = [0, 0, 1, 2, 3, 4, 5, 6, 7,  8,  9, 10, 10, 11, 12, 13],
    _lookuptable_2 = [0, 1, 2, 3, 4, 5, 6, 7, 8,  9, 10, 11, 12, 13, 14, 15],
    _next_readout_time = 0.0,
    _no_synapses = 0,
    _num_connections = 0,
    _readout_cycle_duration = 0.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _reset_pattern = [1, 1, 1, 1, 1, 1],
    _synapse_id = 0,
    _synapses_per_driver = 50,
    _tau_minus_stdp = 20.0,
    _tau_plus = 20.0,
    _weight = 1.0,
    _weight_per_lut_entry = 6.666666666666667,
    _wmax = 100.0
}
stdp_facetshw_synapse_hom_hpc = StdpFacetshwSynapseHomHpc {
    _a_acausal = 0.0,
    _a_causal = 0.0,
    _a_thresh_th = 21.835,
    _a_thresh_tl = 21.835,
    _configbit_0 = [0, 0, 1, 0],
    _configbit_1 = [0, 1, 0, 0],
    _delay = 1.0,
    _driver_readout_time = 15.0,
    _has_delay = True,
    _init_flag = False,
    _lookuptable_0 = [2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15],
    _lookuptable_1 = [0, 0, 1, 2, 3, 4, 5, 6, 7,  8,  9, 10, 10, 11, 12, 13],
    _lookuptable_2 = [0, 1, 2, 3, 4, 5, 6, 7, 8,  9, 10, 11, 12, 13, 14, 15],
    _next_readout_time = 0.0,
    _no_synapses = 0,
    _num_connections = 0,
    _readout_cycle_duration = 0.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _reset_pattern = [1, 1, 1, 1, 1, 1],
    _synapse_id = 0,
    _synapses_per_driver = 50,
    _tau_minus_stdp = 20.0,
    _tau_plus = 20.0,
    _weight = 1.0,
    _weight_per_lut_entry = 6.666666666666667,
    _wmax = 100.0
}
stdp_facetshw_synapse_hom_lbl = StdpFacetshwSynapseHomLbl {
    _a_acausal = 0.0,
    _a_causal = 0.0,
    _a_thresh_th = 21.835,
    _a_thresh_tl = 21.835,
    _configbit_0 = [0, 0, 1, 0],
    _configbit_1 = [0, 1, 0, 0],
    _delay = 1.0,
    _driver_readout_time = 15.0,
    _has_delay = True,
    _init_flag = False,
    _lookuptable_0 = [ 2,  3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15],
    _lookuptable_1 = [ 0,  0, 1, 2, 3, 4, 5, 6, 7,  8,  9, 10, 10, 11, 12, 13],
    _lookuptable_2 = [ 0,  1, 2, 3, 4, 5, 6, 7, 8,  9, 10, 11, 12, 13, 14, 15],
    _next_readout_time = 0.0,
    _no_synapses = 0,
    _num_connections = 0,
    _readout_cycle_duration = 0.0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _reset_pattern = [1, 1, 1, 1, 1, 1],
    _synapse_id = 0,
    _synapse_label = -1,
    _synapses_per_driver = 50,
    _tau_minus_stdp = 20.0,
    _tau_plus = 20.0,
    _weight = 1.0,
    _weight_per_lut_entry = 6.666666666666667,
    _wmax = 100.0
}
stdp_pl_synapse_hom = StdpPlSynapseHom {
    _lambda = 0.1,
    _mu = 0.4,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 20.0,
    _weight = 1.0
}
stdp_pl_synapse_hom_hpc = StdpPlSynapseHomHpc {
    _lambda = 0.1,
    _mu = 0.4,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 20.0,
    _weight = 1.0
}
stdp_pl_synapse_hom_lbl = StdpPlSynapseHomLbl {
    _lambda = 0.1,
    _mu = 0.4,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_plus = 20.0,
    _weight = 1.0
}
stdp_synapse = StdpSynapse {
    _lambda = 0.01,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _mu_minus = 1.0,
    _mu_plus = 1.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 20.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_synapse_hom = StdpSynapseHom {
    _lambda = 0.01,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _mu_minus = 1.0,
    _mu_plus = 1.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 20.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_synapse_hom_hpc = StdpSynapseHomHpc {
    _lambda = 0.01,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _mu_minus = 1.0,
    _mu_plus = 1.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 20.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_synapse_hom_lbl = StdpSynapseHomLbl {
    _lambda = 0.01,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _mu_minus = 1.0,
    _mu_plus = 1.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_plus = 20.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_synapse_hpc = StdpSynapseHpc {
    _lambda = 0.01,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _mu_minus = 1.0,
    _mu_plus = 1.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 20.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_synapse_lbl = StdpSynapseLbl {
    _lambda = 0.01,
    _alpha = 1.0,
    _delay = 1.0,
    _has_delay = True,
    _mu_minus = 1.0,
    _mu_plus = 1.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_plus = 20.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_triplet_synapse = StdpTripletSynapse {
    _aminus = 0.007,
    _aminus_triplet = 0.00023,
    _aplus = 5e-10,
    _aplus_triplet = 0.0062,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _kplus_triplet = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 16.8,
    _tau_plus_triplet = 101.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_triplet_synapse_hpc = StdpTripletSynapseHpc {
    _aminus = 0.007,
    _aminus_triplet = 0.00023,
    _aplus = 5e-10,
    _aplus_triplet = 0.0062,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _kplus_triplet = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_plus = 16.8,
    _tau_plus_triplet = 101.0,
    _weight = 1.0,
    _wmax = 100.0
}
stdp_triplet_synapse_lbl = StdpTripletSynapseLbl {
    _aminus = 0.007,
    _aminus_triplet = 0.00023,
    _aplus = 5e-10,
    _aplus_triplet = 0.0062,
    _delay = 1.0,
    _has_delay = True,
    _kplus = 0.0,
    _kplus_triplet = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_plus = 16.8,
    _tau_plus_triplet = 101.0,
    _weight = 1.0,
    _wmax = 100.0
}
tsodyks2_synapse = Tsodyks2Synapse {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 0.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0
}
tsodyks2_synapse_hpc = Tsodyks2SynapseHpc {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 0.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0
}
tsodyks2_synapse_lbl = Tsodyks2SynapseLbl {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_fac = 0.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0
}
tsodyks_synapse = TsodyksSynapse {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 0.0,
    _tau_psc = 3.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0,
    _y = 0.0
}
tsodyks_synapse_hom = TsodyksSynapseHom {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 0.0,
    _tau_psc = 3.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0,
    _y = 0.0
}
tsodyks_synapse_hom_hpc = TsodyksSynapseHomHpc {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 0.0,
    _tau_psc = 3.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0,
    _y = 0.0
}
tsodyks_synapse_hom_lbl = TsodyksSynapseHomLbl {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_fac = 0.0,
    _tau_psc = 3.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0,
    _y = 0.0
}
tsodyks_synapse_hpc = TsodyksSynapseHpc {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau_fac = 0.0,
    _tau_psc = 3.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0,
    _y = 0.0
}
tsodyks_synapse_lbl = TsodyksSynapseLbl {
    _delay = 1.0,
    _u = 0.5,
    _has_delay = True,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau_fac = 0.0,
    _tau_psc = 3.0,
    _tau_rec = 800.0,
    _weight = 1.0,
    _x = 1.0,
    _y = 0.0
}
vogels_sprekeler_synapse = VogelsSprekelerSynapse {
    _alpha = 0.12,
    _delay = 1.0,
    _eta = 0.001,
    _has_delay = True,
    _kplus = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau = 20.0,
    _weight = 0.5,
    _wmax = 1.0
}
vogels_sprekeler_synapse_hpc = VogelsSprekelerSynapseHpc {
    _alpha = 0.12,
    _delay = 1.0,
    _eta = 0.001,
    _has_delay = True,
    _kplus = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _tau = 20.0,
    _weight = 0.5,
    _wmax = 1.0
}
vogels_sprekeler_synapse_lbl = VogelsSprekelerSynapseLbl {
    _alpha = 0.12,
    _delay = 1.0,
    _eta = 0.001,
    _has_delay = True,
    _kplus = 0.0,
    _num_connections = 0,
    _receptor_type = 0,
    _requires_symmetric = False,
    _synapse_label = -1,
    _tau = 20.0,
    _weight = 0.5,
    _wmax = 1.0
}

max_stars_repo_name: volr/myelin

max_issues_repo_name: volr/myelin

max_forks_repo_name: volr/myelin


text:
{-# LANGUAGE ConstraintKinds, ScopedTypeVariables, TypeApplications, AllowAmbiguousTypes, NoImplicitPrelude,
    GeneralizedNewtypeDeriving, FlexibleContexts
#-}
module LinRel where

import Numeric.LinearAlgebra
import Prelude hiding ((<>))
import Debug.Trace
type BEnum a = (Enum a, Bounded a)
enumAll :: (BEnum a) => [a] -- What about Void?
enumAll = [minBound .. maxBound]

-- A Hacked "Void" type to get card @Void = 0
data Void = Void' | Void'' -- SORRY MOM.
instance Enum Void where
  fromEnum Void' =  1
  fromEnum Void'' = 0
  toEnum 1 = Void'
  toEnum 0 = Void''
instance Bounded Void where
  maxBound = Void''
  minBound = Void'

instance (Enum a, Enum b, Bounded a) => Enum (Either a b) where
  fromEnum (Left a) = fromEnum a
  fromEnum (Right b) = fromEnum b + fromEnum (maxBound @a) + 1
  toEnum n | n <= ((fromEnum (maxBound @a)) - (fromEnum (minBound @a))) = Left (toEnum n)
           | otherwise = Right (toEnum (n - fromEnum (maxBound @a)))

instance (Bounded a, Bounded b) => Bounded (Either a b) where
  maxBound = Right maxBound
  minBound = Left minBound

card :: forall a. (BEnum a) => Int
card = (fromEnum (maxBound @a)) - (fromEnum (minBound @a)) + 1

-- HLinRel holds A x = b constraint
data HLinRel a b = HLinRel (Matrix Double) (Vector Double) deriving Show

-- x = A l + b. Generator constraint.
data VLinRel a b = VLinRel (Matrix Double) (Vector Double) deriving Show

-- f(x) = xQx + bx
data QuadOp a b = QuadOp (Matrix Double) (Vector Double)
{-
qid :: QuadOp a a
qid = ? -- a = a ? Need Relations too.

qcompose :: QuadOp b c -> QuadOp a b -> QuadOp a c
qcompose (QuadOp q c) (QuadOp q' c') = QuadOp q'' c'' where
        where
                ca = card @a
                cb = card @b
                cc = card @c
                a = subMatrix (cb, cb) q
                b = subMatrix (cb,cc) q
                c = subMatrix (cc, cb) q
                d = subMatrix (cc,cc) q
                a' = subMatrix (ca, ca) q'
                b' = subMatrix (ca, cb) q'
                c' = subMatrix (cb, ca  q'
                d' = subMatrix (cb, cb) q'
                m = - (a + d')
                q'' = fromBlocks [[a' + b' <> m </> c'   , b' <> m </> c ],  -- can memoize some of this
                                  [b <> m </> c' , d - ]]

                a'' =  a' - b' <> m </> c'
                [v1', v2'] = takesV [ca,cb] c'
                [v1,  v2] = takesV [cb, cc] c
                v3 = (v2' + v1)
                c'' = vJoin [v1' + m </> c #>  v3, ]

        -}
    {-

    Any cost outside the constraint space is irrelevant.
    Q = V m V where m is fullrank.
    c = Vc also

    minimal sets
    -}

        -- break into pieces, form schur complement.

-- if A x = b then x is in the nullspace + a vector b' solves the equation
h2v :: HLinRel a b -> VLinRel a b
h2v (HLinRel a b) = VLinRel a' b' where
        b' = a <\> b -- least squares solution
        a' = nullspace a

-- if x = A l + b, then A' . x = A' A l + A' b = A' b because A' A = 0
v2h :: VLinRel a b -> HLinRel a b
v2h (VLinRel a' b') = HLinRel a b where
        b = a #> b' -- matrix multiply
        a = tr $ nullspace (tr a') -- orthogonal space to range of a.

hid :: forall a. BEnum a => HLinRel a a
hid =  HLinRel (i ||| (- i)) (vzero s) where
                            s = card @a
                            i = ident s

vzero :: Konst Double d c => d -> c Double
vzero = konst 0

hcompose :: forall a b c. (BEnum a, BEnum b, BEnum c) => HLinRel b c -> HLinRel a b -> HLinRel a c
hcompose (HLinRel m b) (HLinRel m' b') = let a'' = fromBlocks [[       ma',           mb' ,    0       ],
                                                               [         0 ,    mb,        mc          ]] in
                                         let b'' = vjoin [b', b] in
                                         let (VLinRel q p) = h2v (HLinRel a'' b'') in -- kind of a misuse
                                         let q' = (takeRows ca q)  -- drop rows belonging to @b
                                                       ===
                                                  (dropRows (ca + cb) q) in
                                         let [x,y,z] =  takesV [ca,cb,cc] p in
                                         let p'=  vjoin [x,z] in -- rebuild without rows for @b
                                         v2h (VLinRel q' p') -- reconstruct HLinRel
                                       where
                                           ca = card @a
                                           cb = card @b
                                           cc = card @c
                                           sb = size b -- number of constraints in first relation
                                           sb' = size b' -- number of constraints in second relation
                                           ma' = takeColumns ca m'
                                           mb' = dropColumns ca m'
                                           mb = takeColumns cb m
                                           mc = dropColumns cb m

(<<<) :: forall a b c. (BEnum a, BEnum b, BEnum c) => HLinRel b c -> HLinRel a b -> HLinRel a c
(<<<) = hcompose
-- stack the constraints
hmeet :: HLinRel a b -> HLinRel a b -> HLinRel a b
hmeet (HLinRel a b) (HLinRel a' b') = HLinRel (a === a') (vjoin [b,b'])

{- If they don't meet are we still ok?

I am not sure. Might be weird corner cases?

-}

hjoin :: HLinRel a b -> HLinRel a b -> HLinRel a b
hjoin v w = v2h $ vjoin' (h2v v) (h2v w)

-- hmatrix took vjoin from me :(
-- joining means combining generators and adding a new generator
-- Closed under affine combination l * x1 + (1 - l) * x2
vjoin' :: VLinRel a b -> VLinRel a b -> VLinRel a b
vjoin' (VLinRel a b) (VLinRel a' b') = VLinRel (a ||| a' ||| (asColumn (b - b'))) b

-- no constraints, everything
-- trivially true
htop :: forall a b. (BEnum a, BEnum b) => HLinRel a b
htop = HLinRel (vzero (1,ca + cb)) (konst 0 1) where
                                      ca = card @a
                                      cb = card @b
{-
hbottom :: forall a b. (BEnum a, BEnum b) => HLinRel a b
hbottom = HLinRel (vzero (1,ca + cb)) (konst 1 1) where
                                      ca = card @a
                                      cb = card @b
                                      -}
-- all the constraints! Only the origin.
-- no. it should be the empty set. Impossible to satisfy.
-- 0 x = 1 is impossible
-- not gonna play nice.
{-
hbottom :: forall a b. (BEnum a, BEnum b) => HLinRel a b
hbottom = HLinRel (ident (ca + cb)) (konst 0 (ca + cb)) where
                                    ca = card @a
                                    cb = card @b
  -}

hconverse :: forall a b. (BEnum a, BEnum b) => HLinRel a b -> HLinRel b a
hconverse (HLinRel a b) = HLinRel ( (dropColumns ca a) |||  (takeColumns ca a)) b where
    ca = card @a
    cb = card @b

    -- this is numerically unacceptable
-- forall l. A' ( A l + b) == b'
vhsub :: VLinRel a b -> HLinRel a b -> Bool
vhsub (VLinRel a b) (HLinRel a' b') = (naa' <=  1e-10 * (norm_2 a') * (norm_2 a)  ) && ((norm_2 ((a' #> b) - b')) <= 1e-10 * (norm_2 b')  ) where
          naa' = norm_2 (a' <> a)

hsub :: HLinRel a b -> HLinRel a b -> Bool
hsub h1 h2 = vhsub (h2v h1) h2

heq :: HLinRel a b -> HLinRel a b -> Bool
heq a b = (hsub a b) && (hsub b a)

instance Ord (HLinRel a b) where
  (<=) = hsub
  (>=) = flip hsub

instance Eq (HLinRel a b) where
  (==) = heq

-- I can't do this right?
-- hcomplement :: HLinRel a b -> HLinRel a b
-- hcomplement

hpar :: HLinRel a b -> HLinRel c d -> HLinRel (Either a c) (Either b d)
hpar (HLinRel mab v) (HLinRel mcd v') = HLinRel (fromBlocks [ [mab, 0], [0 , mcd]]) (vjoin [v, v']) where

hassoc :: forall a b c. (BEnum a, BEnum b, BEnum c) => HLinRel (Either (Either a b) c) (Either a (Either b c))
hassoc = HLinRel m v where HLinRel m v = hid @((Either (Either a b) c))

hassoc' :: forall a b c. (BEnum a, BEnum b, BEnum c) => HLinRel  (Either a (Either b c)) (Either (Either a b) c)
hassoc' = HLinRel m v where HLinRel m v = hid @((Either (Either a b) c))

{-
        -- Void is unit for Either.
-- void has no inhabitants.... This is a bad boy.

hcup :: HLinRel Void (Either a a)
hcap :: HLinRel (Either a a) Void

-}
hleft :: forall a b. (BEnum a, BEnum b) => HLinRel a (Either a b)
hleft = HLinRel ( i ||| (- i) ||| (konst 0 (ca,cb))) (konst 0 ca) where
    ca = card @a
    cb = card @b
    i = ident ca

hright :: forall a b. (BEnum a, BEnum b) => HLinRel b (Either a b)
hright = HLinRel ( i ||| (konst 0 (cb,ca)) ||| (- i) ) (konst 0 cb) where
    ca = card @a
    cb = card @b
    i = ident cb

hfan ::  forall a b c. BEnum a => HLinRel a b -> HLinRel a c -> HLinRel a (Either b c)
hfan (HLinRel m v) (HLinRel m' v') = HLinRel (fromBlocks [ [ma, mb, 0], [ma', 0, mc']]) (vjoin [v,v']) where
        ca = card @a
        ma = takeColumns ca m
        mb = dropColumns ca m
        ma' = takeColumns ca m'
        mc' = dropColumns ca m'

hdump :: HLinRel a Void
hdump = HLinRel 0 0
{-
hlabsorb :: HLinRel a b -> HLinRel (Either Void a) b
hlabsorb (HLinRel m v) = (HLinRel m v)
-}
hlabsorb ::forall a. BEnum a => HLinRel (Either Void a) a
hlabsorb = HLinRel m v where (HLinRel m v) = hid @a

htrans :: HLinRel a (Either b c) -> HLinRel (Either a b) c
htrans (HLinRel m v) = HLinRel m v

hswap :: forall a b. (BEnum a, BEnum b) => HLinRel (Either a b) (Either b a)
hswap = HLinRel (fromBlocks [[ia ,0,0 ,-ia], [0, ib,-ib,0]]) (konst 0 (ca + cb)) where
        ca = card @a
        cb = card @b
        ia = ident ca
        ib = ident cb

hsum :: forall a. BEnum a => HLinRel (Either a a) a
hsum = HLinRel ( i ||| i ||| - i ) (konst 0 ca)  where
        ca = card @a
        i= ident ca

hdup :: forall a. BEnum a => HLinRel a (Either a a)
hdup = HLinRel (fromBlocks [[i, -i,0 ], [i, 0, -i]]) (konst 0 (ca + ca))  where
        ca = card @a
        i= ident ca

-- hcup :: forall a. BEnum a => HLinRel Void (Either a a)
-- hcup = -- or mainulate hid

-- hcap :: forall a. BEnum a => HLinRel (Either a a) Void

-- smart constructors
hLinRel :: forall a b. (BEnum a, BEnum b) => Matrix Double -> Vector Double -> Maybe (HLinRel a b)
hLinRel m v | cols m == (ca + cb) && (size v == rows m)  = Just (HLinRel m v)
            |  otherwise = Nothing  where
                 ca = card @a
                 cb = card @b

-- a 2d space at every wire or current and voltage.
data IV = I | V deriving (Show, Enum, Bounded, Eq, Ord)

resistor :: Double -> HLinRel IV IV
resistor r = HLinRel ( (2><4)  [ 1,0,-1,   0,
                                 r, 1, 0, -1]) (konst 0 2)

bridge :: Double -> HLinRel (Either IV IV) (Either IV IV)
bridge r = HLinRel (  (4><8) [ 1,0, 1,  0, -1, 0, -1,  0, -- current conservation
                               0, 1, 0, 0, 0, -1 , 0,  0, --voltage maintained
                               0, 0, 0, 1, 0,  0,  0, -1, -- voltage maintained
                               r, 1, 0,-1, -r,  0,  0, 0  ]) (konst 0 4)
short = bridge 0

first :: BEnum c => HLinRel a b -> HLinRel (Either a c) (Either b c)
first f = hpar f hid

second :: BEnum a => HLinRel b c -> HLinRel (Either a b) (Either a c)
second f = hpar hid f

type HLinRel2D u d l r = HLinRel (Either u l) (Either d r)

{-
A stencil  of 2d resistors for tiling

          u
          /
          \
          /
         |
l -/\/\/----/\/\/\-  r
         |
         /
         \
         /
         |
         d

        -}
stencil :: HLinRel2D IV IV IV IV
stencil = (hpar r10 r10) <<< short <<< (hpar r10 r10) where r10 = resistor 10

horicomp :: forall w w' w'' w''' a b c. (BEnum w, BEnum w', BEnum a, BEnum w''', BEnum b, BEnum w'', BEnum c ) => HLinRel2D w' w'' b c -> HLinRel2D w w''' a b -> HLinRel2D (Either w' w) (Either w'' w''') a c
horicomp f g = hcompose f' g' where
               f' :: HLinRel (Either (Either w' w''') b) (Either (Either w'' w''') c)
               f' = (first hswap) <<< hassoc' <<< (hpar hid f) <<< hassoc <<<  (first hswap)
               g' :: HLinRel (Either (Either w' w) a) (Either (Either w' w''') b)
               g' = hassoc' <<< (hpar hid g) <<< hassoc

rotate :: (BEnum w, BEnum w', BEnum a, BEnum b) => HLinRel2D w w' a b -> HLinRel2D a b w w'
rotate f = hswap <<< f <<< hswap

vertcomp :: (BEnum w, BEnum w', BEnum a, BEnum d, BEnum b, BEnum w'', BEnum c ) => HLinRel2D w'  w'' c d -> HLinRel2D w w' a b -> HLinRel2D w w'' (Either c a) (Either d b)
vertcomp f g = rotate (horicomp (rotate f)  (rotate g) )

{-
traceV :: ->
traceH :: ->

  -}

stencil2 = vertcomp h h where h = stencil `horicomp` stencil

{- Legendre transformations in thermo are for open systems. SOmething to that -}
{- Dependent sources. Well, these are goddamn cheating.
We could do it though
|   |
I   alpha I
|   |

small signal models of transistor, op amps etc

gyrator - would need polynomials from caps and inds
would be kind of nice for boundary models

kron instead of dsum - Quantum fields
Kron relation might be nice for discussing remnant space of topological matter

-}

{-

A wire in a circuit has a potential (questionably) and a current running through it
So our wires should have both of these variables.

-}
newtype VProbe = VProbe () deriving (Enum, Bounded, Show, Eq, Ord)
vprobe :: HLinRel IV VProbe
vprobe = HLinRel ( (2><3)  [1,0,0,
                            0,1,-1]) (konst 0 2)

vsource :: Double -> HLinRel IV IV
vsource v = HLinRel ( (2><4) [ 1,0,-1,   0,
                               0, 1, 0, -1]) (fromList [0,v])

isource :: Double -> HLinRel IV IV
isource i = HLinRel ( (2><4) [  1,0, -1,   0 , -- current conservation
                                 1, 0, 0,  0]) (fromList [0,i])

-- the currents add, but the voltages dup. sum and dup are dual
-- Or should it be |--|   a parallel short?
-- Ad then we could open circuit one of them and absorb the Void
-- to derive this
cmerge :: HLinRel (Either IV IV) IV
cmerge = HLinRel ( (3><4)  [1, 0, 1, 0, -1, 0,
                            0,1,0,0,0 ,  -1  ,
                            0,0,0,1, 0, -1])  (konst 0 3)

open :: HLinRel IV Void
open = HLinRel ( (1><2) [1,0]) (konst 0 1)

cap :: HLinRel  (Either IV IV) Void
cap  = hcompose open cmerge

cup :: HLinRel Void (Either IV IV)
cup = hconverse cap

ground :: HLinRel IV Void
ground = HLinRel ( (1><2) [ 0 , 1 ]) (vzero 1)

-- resistors in parallel.

ex1 = hcompose (bridge 10) (bridge 10)
ex2 = hcompose (resistor 10) (resistor 30) -- resistors in series.
r20 :: HLinRel IV IV
r20 = resistor 20

divider :: Double -> Double -> HLinRel (Either IV IV) (Either IV IV)
divider r1 r2 = hcompose (bridge r2) (hpar (resistor r1) hid)

{-
type StateCoState s = Either s s
type ValueD s = s

dynamics :: HLinRel (Either SHOState Control) SHOState
dynamics = HLinRel ((2><5)  [ 1,  dt, 0, -1 ,  0,
                              -dt, 1, dt, 0, -1 ])  (vzero 2)
   where dt = 0.01

-- labsorb <<< (par initial_cond id)
-}

-- state of an oscillator
data SHOState = X | P deriving (Show, Enum, Bounded, Eq, Ord)
data Control = F  deriving (Show, Enum, Bounded, Eq, Ord)
-- Costate newtype wrapper
newtype Co a = Co a deriving (Show, Enum, Bounded, Eq, Ord)

type M = Matrix Double
dynamics :: forall x u. (BEnum x, BEnum u) =>  Matrix Double -> Matrix Double ->
  HLinRel (Either x u) x
dynamics a b =  HLinRel (a ||| b ||| -i )  (vzero cx) where
  cx = card @x
  cu = card @u
  i = ident cx

initial_cond :: forall x. BEnum x => Vector Double-> HLinRel Void x
initial_cond x0 =  HLinRel i x0 where
  cx = card @x
  i = ident cx

valueUpdate :: forall x l. (BEnum x, BEnum l) =>  M -> M -> HLinRel (Either x l) l
valueUpdate a q = HLinRel ((tr a) ||| q ||| i)  (vzero cl) where
  cl = card @l
  i = ident cl

optimal_u :: forall u l. (BEnum u, BEnum l) =>
     M -> M -> HLinRel u l
optimal_u r b = HLinRel (r ||| tr b) (vzero cu) where
  cu = card @u

step :: forall x u l. (BEnum x, BEnum u, BEnum l) => M -> M -> M -> M
        -> HLinRel (Either x l) (Either x l)
step a b r q =
  f5 <<< f4 <<< hassoc' <<< f3 <<< f2 <<< hassoc <<< f1 where
  f1 :: HLinRel (Either x l) (Either (Either x x) l)
  f1 = first hdup
  f2 :: HLinRel (Either x (Either x l)) (Either x l)
  f2 = second (valueUpdate a q)
  f3 ::  HLinRel (Either x l) (Either x (Either l l))
  f3 = second hdup
  f4 ::  HLinRel (Either (Either x l) l) (Either (Either x u) l)
  f4 = first (second (hconverse (optimal_u r b)))
  f5 ::  HLinRel (Either (Either x u) l) (Either x l)
  f5 = first (dynamics a b)

-- iterate (hcompose (step a b r q)) :: [HLinRel (Either x l) (Either x l)]

 {-
step :: forall x l. (BEnum x, BEnum l) =>
   HLinRel (State + ValueD) (State + ValueD)
step a b q r =
= dynamics,
  valueUpdate <<< fst
  second optimal_u
  par (par hid cup) hid
   ::  , optimal_u
-}
{-
cost :: HLinRel (Either (Co SHOState) SHOState Control) (Co SHOState)
cost = HLinRel ((2><5) [ 1,  0, 0,  -1 ,  0,
                        -dt, 1,  dt,  0,  -1 ])  (vzero 2)
-}

{-

Is there a reasonable intepretation of kron?

-}
{-
everything can be definedc inefficiently via v2s and h2v functions

right division

-}

    {-
Call them affine relations

Join and meet aren't union and intersection.
They are the affine closure of union and intersection.

Linear has some niceness.
Homgeonous coordinates usually do.
For clarity and familiaryt I have chosebn not to do it this way
Or maybe I will do it?

par

-}

{-

import numpy as np

def meet(a,b):
    pass
def compose(a,b): # a after b
    assert(a.inN == b.outN)

    combo = np.block([[a.constraints, np.zeros((a.constraints.shape[0] , b.inN) )     ],
                      [np.zeros((b.constraints.shape[0] , a.outN)) ,      b.constraints]])
    print(combo)
    gens = LinRel(a.inN + a.outN, b.outN, gens=combo).gens
    print("gens",gens)
    gens = np.vstack((gens[:a.outN, :], gens[-b.inN: , :]) )
    print(gens)
    return LinRel(a.outN, b.inN, gens=gens)
def top(outN, inN):
    return LinRel(outN, inN, constraints = np.array([[]]))
def bottom(outN, inN):
    return LinRel(outN, inN, gens = np.array([[]]))

def converse(a):
    return LinRel(a.inN, a.outN, np.hstack((a.constraints[:, a.inN:], a.constraints[:, :a.inN])))
def complement(a):
    return LinRel(a.outN, a.inN, constraints = a.gens.T.conj())

def right_div(a,b):
    pass # return complement( compose(a, complement(b)) ) # something like this
def inclusion(a,b):

    s = a.constraints @ b.gens
    np.all(a.constraints @ b.gens <= tol )

    if rcond is None:
        rcond = np.finfo(s.dtype).eps * max(max(a.shape), max(b.shape))
        tol = max(np.amax(a), np.amax(b))
        tol = np.amax(s) * rcond
def fromMat(mat):
    (outN, inN) = mat.shape
    return LinRel(inN, outN,constraints = np.hstack((mat,-np.eye(outN))))
def id(N):
    return fromMat(np.eye(N))
# make 0,1 first index for in/out? Oh, but then in out have to be same size.
# A[0, ...] @ x + A[1, ...] @ y = 0
# Then I can form the kron of linear relations.
# store sperate A B matrices? A @in + B @ out
class LinRel():
    def __init__(self, outN, inN, constraints = None, gens = None, rcond=None):
        #assert(inN <= constraints.shape[1])
        self.inN = inN
        self.outN = outN
        if constraints is not None: #baiscally scipy.linalg.null_space
            u, s, vh = np.linalg.svd(constraints, full_matrices=True)
            M, N = u.shape[0], vh.shape[1]
            if rcond is None:
                rcond = np.finfo(s.dtype).eps * max(M, N)
            tol = np.amax(s) * rcond
            num = np.sum(s > tol, dtype=int)
            self.gens = vh[num:,:].T.conj()
            self.constraints = vh[:num,:]
        if gens is not None: #basically scipy.linalg.orth
            u, s, vh = np.linalg.svd(gens, full_matrices=True)
            M, N = u.shape[0], vh.shape[1]
            if rcond is None:
                rcond = np.finfo(s.dtype).eps * max(M, N)
            tol = np.amax(s) * rcond
            num = np.sum(s > tol, dtype=int)
            self.gens = u[:, :num]
            self.constraints = u[:, num:].T.conj()

    def shape(self):
        return (self.outN, self.inN)
    def size(self):
        return self.outN + self.inN
    # operator overloadings
    def __matmul__(a,b):
        return compose(a,b)
    def __invert__(a): # ~
        return complement(a)
    def __or__(a,b): # an argument could be made for + and *
        return join(a,b)
    def __and__(a,b):
        return meet(a,b)
    def __sub__(a,b):
        return  (a) & (-b)
    def __le__(a,b): # Are the others automatic?
        return inclusion(a,b)
    def __str__(self):
        return " Constraints: \n%s, \nGens:\n %s\n" % (str(self.constraints), str(self.gens))

ex = LinRel(1,2, np.array([[3,4,0]]))
e2 = LinRel(2,1, np.array([[3,4,0]]))

assert(np.all(LinRel(1,2, ex.constraints).constraints == ex.constraints) )
print( ex.constraints @ ex.gens)
assert(np.all( np.abs(ex.constraints @ ex.gens) <= 1e-15) )
print(ex @ e2)
print(e2 @ ex)
print(e2 @ id(e2.inN))

'''
Quadratic optimization can be mixed in.
Quad && LinRel

AffineRel = maintain homgenous coord, or always insert 1 -1 keeping homoeg coord
+ discrete? Maintain a couple copies of

'''

Linear relations
hrep - Ax = 0
or
vrep - y = sum x_i

hrep <-> vrep = row echelon

in and out variables. In and out subspaces.
in : [] - list of indices
out : []

in is a vrep of input space.

in = projection/injection matrix n x d
out = projection/injection matrix. (d-n) x d
in * out = 0. orthogonal

auxiliary variables allowed

compose relations
in1 out1
in2 out2

in = d x n
stack out1 and in2 into matrix. with them equal.

np.hstack(A1, out1 - in2, A2)
in = no.hatck(in, zeores)
in = no.hatck(zeores, out)

drect sum as monoidal product
block([ A, 0  ],
      [ 0, A  ])
in = [in1, in2]
out = [out1, out2]

converse = flip in out

meet = combine the two constraint matrices
join = convert? combine in out?

1-d as unit object
<= is subspace ordering

negation = orthogonalization
division =>

a linear problem is a linear relation of 1-d.

use in1 and out2 as new in/out

fan
snd(30,10) = project bottom 10 = idetnity matrix stacked.
fst(30, 10) project top 10
id(20)
id(n) = LinRel(np.zeros(0,2*n), [zeros, eye], [eye, zero] )
id(n) = LinRel((0,n), eye(n), eye(n)  )
        LinRel [I, -I], [I, 0], [0,I]

"internal" space
class LinRel():
    def __init__(A, in, out):

svd(in * A , smallest )
1 - A*A

Ax + By = 0

vstack adds constraints
hstack adds variables

def idRel(n):
  return LinRel(sparse.lil_matrix((0,n)), n, n)
def mapRel(A):
  (r,c) = A.shape
  newA = sparse.hstack(A, - sparse.eye(r))
  return LinRel(newA, r, c)

class LinRelV():
class LinRelH():

class LinRel():
  def init(self,A, in, out):
    self.A = A
    self.in = in
    self.out = out
  def compose(self, b):
    assert(self.out == b.in, "Shapes must match")

    i = sparse.eye(b.in)
    cons = sparse.hstack([0, i, -i, 0])
    ina = self.A[:,:self.in]
    auxa = self.A[:,self.in:-self.out]
    outa = self.A[:,-self.out:]
    inb = b.A[:,:b.in]
    auxb = b.A[:,b.in:-b.out]
    outb = b.A[:,-b.out:]

    newA = sparse.bmat(  [[ina, auxa, outa, 0, 0,    0],
                          [0  , 0   , i,   -i, 0 ,   0]
                          [0,  0,   0,    inb, auxb,outb]])
    LinRel(newA, self.in, b.out)
  def meet(self,b):
    #hmm. I suppose we acutlaly should split the thing apart again
    assert(self.in == b.in)
    assert(self.out == b.out)
    assert()
    newA = sparse.vstack([self.A, b.A])
    return ()
  def complement(self):
    linalg.svd(self.A)
    return LinRel(get_nonzeroeigs)
  def __negate__(self):
    return self.complement()
  def rdiv(self):
  def transpose():
    self.converse()
  def T():
    self.converse()

  # the svd gives you most of what you need?
  def inclusion():
    x = linalg.nullspace(self.A)
    return b.A @ x == 0 #check that every generator is in. Makes sense. Except numrically is trash.
  def __leq__(self):
    self.inclusion(b)

  def converse(rel):
      newA = np.hstack( [ rel.A[:,-rel.out: ] , rel.A[:,rel.in:-rel.out], rel.A[:,:rel.in ] ])
      return LinRel(newA, rel.out, rel.in)

compose(A)
linalg.nullspace(A)
range?

(cons1,d1) = self.A.shape
(cons2,d2) = b.A.shape
constrain = np.hstack
newA = sparse.vstack

using bigM I can encode the complement of a H-polytope
but then what?
I do it again I guess?

complementation of relation ->
At least one must be inverted.

polytope inclusion
-> search for point not in B.
Or, do sandardinni encoding

Really It should generate new variables for an instantiation.
Snd should not reuse the same variables every time.
class PolyRel()
  invars = []
  constraints = [] # store >= values, not full constraints?
  outvars = []
  def __init__():
    all fresh variables
  def compose(self,b):
    PolyRel(self.constraints + self., invars = outvars )
  def complement():
    zs = []
    for c in constraints:
      z, constraints = reify(c)
      # z = cvx.Variable(1, boolean=True) # actually make same shape as c
      # c += c + M * z
    sum(zs) >= 1 # one or more constraints is disatisfied.
  def rdiv():

yeah. We should use a dsl, compile it, then encode it.
data Rel a b where
  Compose ::
  Complement ::
  Converse ::

relu

l1 >= 0
l2 >= 0
l1 <= M * z
l2 <= M * (1 - z)
x = lambda1 - lambda2
y = lambda1

Maybe insetado f subspaces, we should be thinking ellipses and svd.

-}