-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | hmatrix operations lifted for backprop
--   
--   hmatrix operations lifted for backprop.
--   
--   Meant to act as a drop-in replacement to the API of
--   Numeric.LinearAlgebra.Static. Just change your imports, and your
--   functions are automatically backpropagatable.
--   
--   See README on Github at
--   <a>https://github.com/mstksg/hmatrix-backprop#readme</a>
@package hmatrix-backprop
@version 0.1.2.0


-- | A wrapper over <a>Numeric.LinearAlgebra.Static</a> (type-safe vector
--   and matrix operations based on blas/lapack) that allows its operations
--   to work with <a>backprop</a>.
--   
--   In short, these functions are "lifted" to work with <a>BVar</a>s.
--   
--   Using <a>evalBP</a> will run the original operation:
--   
--   <pre>
--   <a>evalBP</a> :: (forall s. <a>Reifies</a> s <a>W</a>. <a>BVar</a> s a -&gt; <a>BVar</a> s b) -&gt; a -&gt; b
--   </pre>
--   
--   But using <a>gradBP</a> or <a>backprop</a> will give you the gradient:
--   
--   <pre>
--   <a>gradBP</a> :: (forall s. <a>Reifies</a> s <a>W</a>. <a>BVar</a> s a -&gt; <a>BVar</a> s b) -&gt; a -&gt; a
--   </pre>
--   
--   These can act as a drop-in replacement to the API of
--   <a>Numeric.LinearAlgebra.Static</a>. Just change your imports, and
--   your functions are automatically backpropagatable. Useful types are
--   all re-exported.
--   
--   Also contains <a>sumElements</a> <a>BVar</a> operation.
--   
--   Formulas for gradients come from the following papers:
--   
--   <ul>
--   
--   <li><a>https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf</a></li>
--   <li><a>http://www.dtic.mil/dtic/tr/fulltext/u2/624426.pdf</a></li>
--   
--   <li><a>http://www.cs.cmu.edu/~zkolter/course/15-884/linalg-review.pdf</a></li>
--   <li><a>https://arxiv.org/abs/1602.07527</a></li>
--   </ul>
--   
--   Some functions are notably unlifted:
--   
--   <ul>
--   <li><a>svd</a>: I can't find any resources that allow you to
--   backpropagate if the U and V matrices are used! If you find one, let
--   me know, or feel free to submit a PR! Because of this, Currently only
--   a version that exports only the singular values is exported.</li>
--   <li><a>svdTall</a>, <a>svdFlat</a>: Not sure where to start for
--   these</li>
--   <li><tt>qr</tt>: Same story.
--   <a>https://github.com/tensorflow/tensorflow/issues/6504</a> might
--   yield a clue?</li>
--   <li><a>her</a>: No <a>Num</a> instance for <a>Her</a> makes this
--   impossible at the moment with the current backprop API</li>
--   <li><a>exmp</a>: Definitely possible, but I haven't dug deep enough to
--   figure it out yet! There is a description here
--   <a>https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf</a> but it
--   requires some things I am not familiar with yet. Feel free to submit a
--   PR!</li>
--   <li><a>sqrtm</a>: Also likely possible. Maybe try to translate
--   <a>http://people.cs.umass.edu/~smaji/projects/matrix-sqrt/</a> ? PRs
--   welcomed!</li>
--   <li><a>linSolve</a>: Haven't figured out where to start!</li>
--   <li><a>&lt;/&gt;</a>: Same story</li>
--   <li>Functions returning existential types, like <a>withNullSpace</a>,
--   <a>withOrth</a>, <a>withRows</a>, etc.; not quite sure what the best
--   way to handle these are at the moment.</li>
--   <li><a>withRows</a> and <a>withColumns</a> made "type-safe", without
--   existential types, with <a>fromRows</a> and <a>fromColumns</a>.</li>
--   </ul>
module Numeric.LinearAlgebra.Static.Backprop
data R (n :: Nat) :: Nat -> *
type ℝ = Double
vec2 :: Reifies s W => BVar s ℝ -> BVar s ℝ -> BVar s (R 2)
vec3 :: Reifies s W => BVar s ℝ -> BVar s ℝ -> BVar s ℝ -> BVar s (R 3)
vec4 :: Reifies s W => BVar s ℝ -> BVar s ℝ -> BVar s ℝ -> BVar s ℝ -> BVar s (R 4)
(&) :: (Reifies s W, KnownNat n, 1 <= n, KnownNat (n + 1)) => BVar s (R n) -> BVar s ℝ -> BVar s (R (n + 1))
infixl 4 &
(#) :: (Reifies s W, KnownNat n, KnownNat m) => BVar s (R n) -> BVar s (R m) -> BVar s (R (n + m))
infixl 4 #
split :: forall p n s. (Reifies s W, KnownNat p, KnownNat n, p <= n) => BVar s (R n) -> (BVar s (R p), BVar s (R (n - p)))
headTail :: (Reifies s W, KnownNat n, 1 <= n) => BVar s (R n) -> (BVar s ℝ, BVar s (R (n - 1)))

-- | Potentially extremely bad for anything but short lists!!!
vector :: forall n s. (Reifies s W, KnownNat n) => Vector n (BVar s ℝ) -> BVar s (R n)
linspace :: forall n s. (Reifies s W, KnownNat n) => BVar s ℝ -> BVar s ℝ -> BVar s (R n)
range :: KnownNat n => R n
dim :: KnownNat n => R n
data L (m :: Nat) (n :: Nat) :: Nat -> Nat -> *
type Sq (n :: Nat) = L n n
row :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s (L 1 n)
col :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s (L n 1)
(|||) :: (Reifies s W, KnownNat c, KnownNat r1, KnownNat (r1 + r2)) => BVar s (L c r1) -> BVar s (L c r2) -> BVar s (L c (r1 + r2))
infixl 3 |||
(===) :: (Reifies s W, KnownNat c, KnownNat r1, KnownNat (r1 + r2)) => BVar s (L r1 c) -> BVar s (L r2 c) -> BVar s (L (r1 + r2) c)
infixl 2 ===
splitRows :: forall p m n s. (Reifies s W, KnownNat p, KnownNat m, KnownNat n, p <= m) => BVar s (L m n) -> (BVar s (L p n), BVar s (L (m - p) n))
splitCols :: forall p m n s. (Reifies s W, KnownNat p, KnownNat m, KnownNat n, KnownNat (n - p), p <= n) => BVar s (L m n) -> (BVar s (L m p), BVar s (L m (n - p)))
unrow :: (Reifies s W, KnownNat n) => BVar s (L 1 n) -> BVar s (R n)
uncol :: (Reifies s W, KnownNat n) => BVar s (L n 1) -> BVar s (R n)
tr :: (Reifies s W, Transposable m mt, Transposable mt m, Num m, Num mt) => BVar s m -> BVar s mt
eye :: KnownNat n => Sq n
diag :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s (Sq n)

-- | Potentially extremely bad for anything but short lists!!!
matrix :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => [BVar s ℝ] -> BVar s (L m n)
type ℂ = Complex Double
data C (n :: Nat) :: Nat -> *
data M (m :: Nat) (n :: Nat) :: Nat -> Nat -> *
𝑖 :: Sized ℂ s c => s

-- | Matrix product
(<>) :: (Reifies s W, KnownNat m, KnownNat k, KnownNat n) => BVar s (L m k) -> BVar s (L k n) -> BVar s (L m n)
infixr 8 <>

-- | Matrix-vector product
(#>) :: (Reifies s W, KnownNat m, KnownNat n) => BVar s (L m n) -> BVar s (R n) -> BVar s (R m)
infixr 8 #>

-- | Dot product
(<.>) :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s (R n) -> BVar s ℝ
infixr 8 <.>

-- | Can only get the singular values, for now. Let me know if you find an
--   algorithm that can compute the gradients based on differentials for
--   the other matricies!
svd :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => BVar s (L m n) -> BVar s (R n)

-- | Version of <a>svd</a> that returns the full SVD, but if you attempt to
--   find the gradient, it will fail at runtime if you ever use U or V.
svd_ :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => BVar s (L m n) -> (BVar s (L m m), BVar s (R n), BVar s (L n n))
class Eigen m l v | m -> l, m -> v

-- | <i>NOTE</i> The gradient is not necessarily symmetric! The gradient is
--   not meant to be retireved directly; insteadl, <a>eigenvalues</a> is
--   meant to be used as a part of a larger computation, and the gradient
--   as an intermediate step.
eigensystem :: forall n s. (Reifies s W, KnownNat n) => BVar s (Sym n) -> (BVar s (R n), BVar s (L n n))

-- | <i>NOTE</i> The gradient is not necessarily symmetric! The gradient is
--   not meant to be retireved directly; insteadl, <a>eigenvalues</a> is
--   meant to be used as a part of a larger computation, and the gradient
--   as an intermediate step.
eigenvalues :: forall n s. (Reifies s W, KnownNat n) => BVar s (Sym n) -> BVar s (R n)

-- | Algorithm from <a>https://arxiv.org/abs/1602.07527</a>
--   
--   The paper also suggests a potential imperative algorithm that might
--   help. Need to benchmark to see what is best.
--   
--   <i>NOTE</i> The gradient is not necessarily symmetric! The gradient is
--   not meant to be retireved directly; insteadl, <a>eigenvalues</a> is
--   meant to be used as a part of a larger computation, and the gradient
--   as an intermediate step.
chol :: forall n s. (Reifies s W, KnownNat n) => BVar s (Sym n) -> BVar s (Sq n)

-- | p-norm for vectors, operator norm for matrices
class Normed a

-- | Number of non-zero items
norm_0 :: (Reifies s W, Normed a, Num a) => BVar s a -> BVar s ℝ

-- | Sum of absolute values
norm_1V :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s ℝ

-- | Maximum <a>norm_1</a> of columns
norm_1M :: (Reifies s W, KnownNat n, KnownNat m) => BVar s (L n m) -> BVar s ℝ

-- | Square root of sum of squares
--   
--   Be aware that gradient diverges when the norm is zero
norm_2V :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s ℝ

-- | Maximum singular value
norm_2M :: (Reifies s W, KnownNat n, KnownNat m) => BVar s (L n m) -> BVar s ℝ

-- | Maximum absolute value
norm_InfV :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s ℝ

-- | Maximum <a>norm_1</a> of rows
norm_InfM :: (Reifies s W, KnownNat n, KnownNat m) => BVar s (L n m) -> BVar s ℝ
mean :: (Reifies s W, KnownNat n, 1 <= n) => BVar s (R n) -> BVar s ℝ

-- | Mean and covariance. If you know you only want to use one or the
--   other, use <a>meanL</a> or <a>cov</a>.
meanCov :: forall m n s. (Reifies s W, KnownNat n, KnownNat m, 1 <= m) => BVar s (L m n) -> (BVar s (R n), BVar s (Sym n))

-- | <a>meanCov</a>, but if you know you won't use the covariance.
meanL :: forall m n s. (Reifies s W, KnownNat n, KnownNat m, 1 <= m) => BVar s (L m n) -> BVar s (R n)

-- | <a>cov</a>, but if you know you won't use the covariance.
cov :: forall m n s. (Reifies s W, KnownNat n, KnownNat m, 1 <= m) => BVar s (L m n) -> BVar s (Sym n)
class Disp t
disp :: Disp t => Int -> t -> IO ()
class Domain field (vec :: Nat -> *) (mat :: Nat -> Nat -> *) | mat -> vec field, vec -> mat field, field -> mat vec
mul :: (Reifies s W, KnownNat m, KnownNat k, KnownNat n, Domain field vec mat, Num (mat m k), Num (mat k n), Num (mat m n), Transposable (mat m k) (mat k m), Transposable (mat k n) (mat n k)) => BVar s (mat m k) -> BVar s (mat k n) -> BVar s (mat m n)
app :: (Reifies s W, KnownNat m, KnownNat n, Domain field vec mat, Num (mat m n), Num (vec n), Num (vec m), Transposable (mat m n) (mat n m)) => BVar s (mat m n) -> BVar s (vec n) -> BVar s (vec m)
dot :: (Reifies s W, KnownNat n, Domain field vec mat, Sized field (vec n) d, Num (vec n)) => BVar s (vec n) -> BVar s (vec n) -> BVar s field
cross :: (Reifies s W, Domain field vec mat, Num (vec 3)) => BVar s (vec 3) -> BVar s (vec 3) -> BVar s (vec 3)

-- | Create matrix with diagonal, and fill with default entries
diagR :: forall m n k field vec mat s. (Reifies s W, Domain field vec mat, Num (vec k), Num (mat m n), KnownNat m, KnownNat n, KnownNat k, Container Vector field, Sized field (mat m n) Matrix, Sized field (vec k) Vector) => BVar s field -> BVar s (vec k) -> BVar s (mat m n)

-- | Note: if possible, use the potentially much more performant
--   <a>vmap'</a>.
vmap :: (Reifies s W, KnownNat n) => (BVar s ℝ -> BVar s ℝ) -> BVar s (R n) -> BVar s (R n)

-- | <a>vmap</a>, but potentially more performant. Only usable if the
--   mapped function does not depend on any external <a>BVar</a>s.
vmap' :: (Reifies s W, Num (vec n), Storable field, Sized field (vec n) Vector) => (forall s'. Reifies s' W => BVar s' field -> BVar s' field) -> BVar s (vec n) -> BVar s (vec n)

-- | Note: Potentially less performant than <a>vmap'</a>.
dvmap :: (Reifies s W, KnownNat n, Domain field vec mat, Num (vec n), Num field) => (forall s'. Reifies s' W => BVar s' field -> BVar s' field) -> BVar s (vec n) -> BVar s (vec n)

-- | Note: if possible, use the potentially much more performant
--   <a>mmap'</a>.
mmap :: (Reifies s W, KnownNat n, KnownNat m) => (BVar s ℝ -> BVar s ℝ) -> BVar s (L n m) -> BVar s (L n m)

-- | <a>mmap</a>, but potentially more performant. Only usable if the
--   mapped function does not depend on any external <a>BVar</a>s.
mmap' :: forall n m mat field s. (Reifies s W, KnownNat m, Num (mat n m), Sized field (mat n m) Matrix, Element field) => (forall s'. Reifies s' W => BVar s' field -> BVar s' field) -> BVar s (mat n m) -> BVar s (mat n m)

-- | Note: Potentially less performant than <a>mmap'</a>.
dmmap :: (Reifies s W, KnownNat n, KnownNat m, Domain field vec mat, Num (mat n m), Num field) => (forall s'. Reifies s' W => BVar s' field -> BVar s' field) -> BVar s (mat n m) -> BVar s (mat n m)
outer :: (Reifies s W, KnownNat m, KnownNat n, Domain field vec mat, Transposable (mat n m) (mat m n), Num (vec n), Num (vec m), Num (mat n m)) => BVar s (vec n) -> BVar s (vec m) -> BVar s (mat n m)

-- | Note: if possible, use the potentially much more performant
--   <a>zipWithVector'</a>.
zipWithVector :: (Reifies s W, KnownNat n) => (BVar s ℝ -> BVar s ℝ -> BVar s ℝ) -> BVar s (R n) -> BVar s (R n) -> BVar s (R n)
zipWithVector' :: (Reifies s W, Num (vec n), Storable field, Sized field (vec n) Vector) => (forall s'. Reifies s' W => BVar s' field -> BVar s' field -> BVar s' field) -> BVar s (vec n) -> BVar s (vec n) -> BVar s (vec n)

-- | A version of <a>zipWithVector'</a> that is potentially less performant
--   but is based on <a>zipWithVector</a> from <a>Domain</a>.
dzipWithVector :: (Reifies s W, KnownNat n, Domain field vec mat, Num (vec n), Num field) => (forall s'. Reifies s' W => BVar s' field -> BVar s' field -> BVar s' field) -> BVar s (vec n) -> BVar s (vec n) -> BVar s (vec n)
det :: (Reifies s W, KnownNat n, Num (mat n n), Domain field vec mat, Sized field (mat n n) d, Transposable (mat n n) (mat n n)) => BVar s (mat n n) -> BVar s field

-- | The inverse and the natural log of the determinant together. If you
--   know you don't need the inverse, it is best to use <a>lndet</a>.
invlndet :: forall n mat field vec d s. (Reifies s W, KnownNat n, Num (mat n n), Domain field vec mat, Sized field (mat n n) d, Transposable (mat n n) (mat n n)) => BVar s (mat n n) -> (BVar s (mat n n), (BVar s field, BVar s field))

-- | The natural log of the determinant.
lndet :: forall n mat field vec d s. (Reifies s W, KnownNat n, Num (mat n n), Domain field vec mat, Sized field (mat n n) d, Transposable (mat n n) (mat n n)) => BVar s (mat n n) -> BVar s field
inv :: (Reifies s W, KnownNat n, Num (mat n n), Domain field vec mat, Transposable (mat n n) (mat n n)) => BVar s (mat n n) -> BVar s (mat n n)
toRows :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => BVar s (L m n) -> Vector m (BVar s (R n))
toColumns :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => BVar s (L m n) -> Vector n (BVar s (R m))
fromRows :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => Vector m (BVar s (R n)) -> BVar s (L m n)
fromColumns :: forall m n s. (Reifies s W, KnownNat m, KnownNat n) => Vector n (BVar s (R m)) -> BVar s (L m n)
konst :: forall t s d q. (Reifies q W, Sized t s d, Container d t, Num s) => BVar q t -> BVar q s
sumElements :: forall t s d q. (Reifies q W, Sized t s d, Container d t, Num s) => BVar q s -> BVar q t

-- | If there are extra items in the total derivative, they are dropped. If
--   there are missing items, they are treated as zero.
extractV :: forall t s q. (Reifies q W, Sized t s Vector, Num s, Konst t Int Vector, Container Vector t, Num (Vector t)) => BVar q s -> BVar q (Vector t)

-- | If there are extra items in the total derivative, they are dropped. If
--   there are missing items, they are treated as zero.
extractM :: forall t s q. (Reifies q W, Sized t s Matrix, Num s, Konst t (Int, Int) Matrix, Container Matrix t, Num (Matrix t)) => BVar q s -> BVar q (Matrix t)
create :: forall t s d q. (Reifies q W, Sized t s d, Num s, Num (d t)) => BVar q (d t) -> Maybe (BVar q s)
class Diag m d | m -> d
takeDiag :: (Reifies s W, KnownNat n, Diag (mat n n) (vec n), Domain field vec mat, Num (vec n), Num (mat n n), Num field) => BVar s (mat n n) -> BVar s (vec n)
data Sym (n :: Nat) :: Nat -> *

-- | &lt;math&gt;
sym :: (Reifies s W, KnownNat n) => BVar s (Sq n) -> BVar s (Sym n)

-- | &lt;math&gt;
mTm :: (Reifies s W, KnownNat m, KnownNat n) => BVar s (L m n) -> BVar s (Sym n)

-- | Warning: the gradient is going necessarily symmetric, and so is
--   <i>not</i> meant to be used directly. Rather, it is meant to be used
--   in the middle (or at the end) of a longer computation.
unSym :: (Reifies s W, KnownNat n) => BVar s (Sym n) -> BVar s (Sq n)

-- | Unicode synonym for <tt>&lt;.&gt;&gt;</tt>
(<·>) :: (Reifies s W, KnownNat n) => BVar s (R n) -> BVar s (R n) -> BVar s ℝ
infixr 8 <·>

-- | A <tt><a>BVar</a> s a</tt> is a value of type <tt>a</tt> that can be
--   "backpropagated".
--   
--   Functions referring to <a>BVar</a>s are tracked by the library and can
--   be automatically differentiated to get their gradients and results.
--   
--   For simple numeric values, you can use its <a>Num</a>,
--   <a>Fractional</a>, and <a>Floating</a> instances to manipulate them as
--   if they were the numbers they represent.
--   
--   If <tt>a</tt> contains items, the items can be accessed and extracted
--   using lenses. A <tt><a>Lens'</a> b a</tt> can be used to access an
--   <tt>a</tt> inside a <tt>b</tt>, using <tt>^^.</tt> (<a>viewVar</a>):
--   
--   <pre>
--   (<a>^.</a>)  ::        a -&gt; <a>Lens'</a> a b -&gt;        b
--   (<tt>^^.</tt>) :: <a>BVar</a> s a -&gt; <a>Lens'</a> a b -&gt; <a>BVar</a> s b
--   </pre>
--   
--   There is also <tt>^^?</tt> (<a>previewVar</a>), to use a
--   <tt>Prism'</tt> or <a>Traversal'</a> to extract a target that may or
--   may not be present (which can implement pattern matching),
--   <tt>^^..</tt> (<a>toListOfVar</a>) to use a <a>Traversal'</a> to
--   extract <i>all</i> targets inside a <a>BVar</a>, and <tt>.~~</tt>
--   (<a>setVar</a>) to set and update values inside a <a>BVar</a>.
--   
--   For more complex operations, libraries can provide functions on
--   <a>BVar</a>s using <a>liftOp</a> and related functions. This is how
--   you can create primitive functions that users can use to manipulate
--   your library's values.
--   
--   For example, the <i>hmatrix</i> library has a matrix-vector
--   multiplication function, <tt>#&gt; :: L m n -&gt; R n -&gt; L m</tt>.
--   
--   A library could instead provide a function <tt>#&gt; :: <a>BVar</a> (L
--   m n) -&gt; BVar (R n) -&gt; BVar (R m)</tt>, which the user can then
--   use to manipulate their <a>BVar</a>s of <tt>L m n</tt>s and <tt>R
--   n</tt>s, etc.
--   
--   See <a>Numeric.Backprop#liftops</a> and documentation for
--   <a>liftOp</a> for more information.
data BVar s a :: Type -> * -> *
class Reifies k (s :: k) a | s -> a

-- | An ephemeral Wengert Tape in the environment. Used internally to track
--   of the computational graph of variables.
--   
--   For the end user, one can just imagine <tt><a>Reifies</a> s
--   <a>W</a></tt> as a required constraint on <tt>s</tt> that allows
--   backpropagation to work.
data W :: *
