How to use Linear.V to write static type checked matrix operations (Haskell)? - haskell

I'm interested in using Linear.V from the Linear library to write matrix operations on sizes that are known at compile time. However, I'm not sure how to use this library. Where can I find more references on how to use it?

This is a little tricky to ask without a bit more knowledge of what exactly you want to do, but I'll take a stab. Linear.V gives you n-dimensional vectors for any n. In linear, matrices are defined as vectors-of-vectors - Linear.Matrix defines the operations on such values. Linear.Matrix works over various sizes of matrix by being parameterized over two functors, and Linear.V is indeed a Functor so we're good to use those operations.
The following boring example shows how you could work with Linear.V:
{-# LANGUAGE DataKinds #-}
import Linear
import Linear.V
import Data.Vector
identity :: V 2 (V 2 Float)
identity = V (fromList [ V (fromList [1, 0]), V (fromList [0, 1]) ])
calculation :: V 2 (V 2 Float)
calculation = identity !*! identity
It's boring in that it just calculates the product of two identity matrices, but it should give you an idea how to put these pieces together. I'm using GHC 7.6+ type literals to specify that identity is a 2x2 matrix.
Note that using the V constructor is somewhat dangerous - it allows you to "lie" about the size of the vector. For example, if you do the following:
identity :: V 2 (V 2 Float)
identity = V (fromList [ V (fromList [1, 0]) ])
things are likely to go very wrong. It's safer to use fromVector, or perhaps tabulate (tabulate uses the representation of V - which is basically a function from element index to its value).

Related

Efficient way to do n-ary branch / tabulated functions?

I'm trying to get some basic information on the performance characteristics of branches in SBV.
Let's suppose I have an SInt16 and a very sparse lookup table Map Int16 a. I can implement the lookup with nested ite:
sCase :: (Mergeable a) => SInt16 -> a -> Map Int16 a -> a
sCase x def = go . toList
where
go [] = def
go ((k,v):kvs) = ite (x .== literal k) v (go kvs)
However, this means the generated tree will be very deep.
Does that matter?
If yes, is it better to instead generate a balanced tree of branches, effectively mirroring the Map's structure? Or is there some other scheme that would give even better performance?
If there are less than 256 entries in the map, would it change anything to "compress" it so that sCase works on an SInt8 and a Map Int8 a?
Is there some built-in SBV combinator for this use case that works better than iterated ite?
EDIT: It turns out that it matters a lot what my a is, so let me add some more detail to that. I am currently using sCase to branch in a stateful computation modeled as an RWS r w s a, with the following instances:
instance forall a. Mergeable a => Mergeable (Identity a) where
symbolicMerge force cond thn els = Identity $ symbolicMerge force cond (runIdentity thn) (runIdentity els)
instance (Mergeable s, Mergeable w, Mergeable a, forall a. Mergeable a => Mergeable (m a)) => Mergeable (RWST r w s m a) where
symbolicMerge force cond thn els = Lazy.RWST $
symbolicMerge force cond (runRWST thn) (runRWST els)
So stripping away all the newtypes, I'd like to branch into something of type r -> s -> (a, s, w) s.t. Mergeable s, Mergeable w and Mergeable a.
Symbolic look-ups are expensive
Symbolic array lookup will be expensive regardless of what data-structure you use. It boils down to the fact that there's no information available to the symbolic execution engine to cut-down on the state-space, so it ends up doing more or less what you coded yourself.
SMTLib Arrays
However, the best solution in these cases is to actually use SMT's support for arrays: http://smtlib.cs.uiowa.edu/theories-ArraysEx.shtml
SMTLib arrays are different than what you'd consider as an array in a regular programming language: It does not have bounds. In that sense, it's more of a map from inputs to outputs, spanning the entire domain. (i.e., they are equivalent to functions.) But SMT has custom theories to deal with arrays and thus they can handle problems involving arrays much more efficiently. (On the down-side, there's no notion of index-out-of-bounds or somehow controlling the range of elements you can access. You can code those up yourself on top of the abstraction though, leaving it up to you to decide how you want to handle such invalid accesses.)
If you are interested in learning more about how SMT solvers deal with arrays, the classic reference is: http://theory.stanford.edu/~arbrad/papers/arrays.pdf
Arrays in SBV
SBV supports arrays, through the SymArray class: https://hackage.haskell.org/package/sbv-8.7/docs/Data-SBV.html#t:SymArray
The SFunArray type actually does not use SMTLib arrays. This was designed to support solvers that didn't understand Arrays, such as ABC: https://hackage.haskell.org/package/sbv-8.7/docs/Data-SBV.html#t:SFunArray
The SArray type fully supports SMTLib arrays: https://hackage.haskell.org/package/sbv-8.7/docs/Data-SBV.html#t:SArray
There are some differences between these types, and the above links describe them. However, for most purposes, you can use them interchangeably.
Converting a Haskell map to an SBV array
Going back to your original question, I'd be tempted to use an SArray to model such a look up. I'd code it as:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.SBV
import qualified Data.Map as M
import Data.Int
-- Fill an SBV array from a map
mapToSArray :: (SymArray array, SymVal a, SymVal b) => M.Map a (SBV b) -> array a b -> array a b
mapToSArray m a = foldl (\arr (k, v) -> writeArray arr (literal k) v) a (M.toList m)
And use it as:
g :: Symbolic SBool
g = do let def = 0
-- get a symbolic array, initialized with def
arr <- newArray "myArray" (Just def)
let m :: M.Map Int16 SInt16
m = M.fromList [(5, 2), (10, 5)]
-- Fill the array from the map
let arr' :: SArray Int16 Int16 = mapToSArray m arr
-- A simple problem:
idx1 <- free "idx1"
idx2 <- free "idx2"
pure $ 2 * readArray arr' idx1 + 1 .== readArray arr' idx2
When I run this, I get:
*Main> sat g
Satisfiable. Model:
idx1 = 5 :: Int16
idx2 = 10 :: Int16
You can run it as satWith z3{verbose=True} g to see the SMTLib output it generates, which avoids costly lookups by simply delegating those tasks to the backend solver.
Efficiency
The question of whether this will be "efficient" really depends on how many elements your map has that you're constructing the array from. The larger the number of elements and the trickier the constraints, the less efficient it will be. In particular, if you ever write to an index that is symbolic, I'd expect slow-downs in solving time. If they're all constants, it should be relatively performant. As is usual in symbolic programming, it's really hard to predict any performance without seeing the actual problem and experimenting with it.
Arrays in the query context
The function newArray works in the symbolic context. If you're in a query context, instead use freshArray: https://hackage.haskell.org/package/sbv-8.7/docs/Data-SBV-Control.html#v:freshArray

Haskell: how to write code that interacts with the internals of two wrapped types?

I'm wondering how to create two encapsulated types that interact with each other, without exposing the internal implementation to other modules.
As an example, consider my two modules, Vector.hs and Matrix.hs, that wrap Linear.V4 (a 4-element vector) and Linear.M44 (a 4x4 element matrix). I wish to write a function that multiplies a Matrix by a Vector, returning a Vector, and using the wrapped data types to perform the operation.
In this example, in Vector.hs I have:
-- Vector.hs
module Vector (Vector, vector) where
import Linear (V4 (V4))
newtype Vector = Vector (V4 Double) deriving (Eq, Show, Read)
vector :: (Double, Double, Double, Double) -> Vector
vector (x, y, z, w) = Vector (V4 x y z w)
Note that I'm only exporting the new type and the factory function - the data constructor Vector is not exported. As far as I understand, this hides the internal implementation of Vector (i.e. that it's really a V4).
And in Matrix.hs I have something similar:
-- Matrix.hs
module Matrix (Matrix, vector)
import Linear (V4 (V4), M44)
type Row = (Double, Double, Double, Double)
newtype Matrix = Matrix (M44 Double) deriving (Eq, Show, Read)
matrix :: (Row, Row, Row, Row) -> Matrix
--matrix ((a00, a01, a02, a03), (a10, ... ) = Matrix (V4 (V4 a00 a01 a02 a03) (V4 a10 ...))
These two modules can be used by client code pretty effectively - the client code is not aware that they are implemented with Linear data structures, and there's apparently no way for client code to exploit that (is that true?).
The problem arises when those two types need to interact with each other at the level of their wrapped types - in this particular case, multiplying a Matrix by a Vector yields a new Vector. However to implement this operation, the code performing it needs access to the internal implementation of both Vector and Matrix, in order to do something like this:
-- Matrix.hs
-- ... include earlier definitions
{-# LANGUAGE FlexibleInstances #-}
import qualified Linear.Matrix ((!*))
class MatrixMultiplication a b c | a b -> c where
infixl 7 |*| -- set same precedence and associativity as *
(|*|) :: a -> b -> c
instance MatrixMultiplication Matrix Vector Vector where
(|*|) (Matrix a) q0 =
let (V4 x y z w) = a Linear.Matrix.!* _impl q0
in vector (x, y, z, w)
To do this I need a function, _impl, that allows the Matrix module to get at the internals of Vector:
-- Vector.hs
-- ... include earlier definitions
_impl :: Vector -> V4 Double
_impl (Vector q) = q
-- also added to export list
So after carefully hiding the internals of Vector (by not exporting the data constructor function of Vector), it seems I must expose them with a different exported function, and the only defence I have is some documentation telling client code they shouldn't be using it. This seems unfortunate - I've effectively just renamed the data constructor.
In a language like C++, the friend keyword could be used to provide a function access to the private data member of one of the types. Is there a similar concept in Haskell?
I suppose I could implement both Vector and Matrix in the same module. They'd then have access to each others' data constructors. However this isn't really a satisfying solution as it just works around the issue.
Is there a better approach?

In Haskell, how to bind one list-like monad to another list-like monad

Say you want to implement very general operations on a directed graph making as few assumptions about the structure as possible.
It is impossible to make absolutely no assumptions, so I am still assuming that I will represent my graph as some sort of adjacency list, but the spirit is to try to be as opaque as possible about the nature of manipulated things.
Assume you have the two following operations: one operation to list all nodes in a graph, and one operation to list all outgoing edges from some vertex.
class List_Nodes graph list vertex where
list_nodes :: graph -> list vertex
class List_Edges_From graph vertex list edge where
list_edges_from :: graph -> vertex -> list edge
Then, just for the fun of it I decided I might want want to iterate over all edges
class List_Edges graph vertex list edge where
list_edges :: graph -> list edge
No matter what the concrete implementation of a graph will be, I believe I can express very generally that listing edges can be understood as listing nodes, and listing edges from each of them.
So I decided to write an instance as general as possible like this:
instance (
Monad node_list,
Monad edge_list,
List_Nodes graph node_list vertex,
List_Edges_From graph vertex edge_list edge
) => List_Edges graph vertex edge_list edge where
list_edges graph = (list_nodes graph :: node_list vertex) >>= list_edges_from graph
-- I added :: node_list vertex to help GHC infer the type.
However, this code does not work as is. This code works only with an additional instance requirement that edge_list ~ node_list,. That's because binding happens only in one monad, the returned one: edge_list.
But to be as general as possible I do not want to assume that the way I store nodes, is necessarily the same way I store outgoing edges in a node. For example one might want to use a list to store nodes, and a vector to store edges out of a node.
Question:
How can I express the monadic bind list_nodes graph >>= list_edges_from graph between two possibly different list like containers?
More generally, how can I say convert a list to a vector without being specific about them? I am only assuming they are "list-like" whatever that means. Somehow these list like things are themselves functors, so I'm looking to convert some functor into some other functor. Am I looking for natural transformations of category theory? How can I do this in Haskell?
Language extensions used and imports used:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Lib () where
import Prelude
import Control.Monad
If you want to be very general about the monad in which your nodes and edges are stored, you can't really do anything. Two monads in general do not compose with each other: what should the return type be if nodes are "stored" as IO String and edges as String -> Maybe String?
I would suggest doing a lot less of this work at the type level. There is little need for type classes: instead, define a concrete type that contains the functions that you need, and a single typeclass for converting to that canonical type. Then the various implementations of your graph type can simply create a "canonical view" of their graph, representing it in the type that you use to implement generic algorithms. This way, you have only one canonical representation to perform these algorithms on, despite having many representations for the graphs themselves.
The graph type can be as simple as
data Graph v e = Graph { nodes :: [v]
, edges :: v -> [e]
}
class AsGraph t v e where
asGraph :: t v e -> Graph v e
and you can implement allEdges generically in terms of that quite easily. If you have a graph with vector edges, it can be converted to this generic graph type in order to participate in generic operations like allEdges:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Data.Foldable (toList)
data Graph v e = Graph { nodes :: [v]
, edges :: v -> [e]
}
class AsGraph t v e where
asGraph :: t v e -> Graph v e
data VectorEdges v e = VectorEdges { vs :: [v]
, es :: v -> Vector e
}
instance AsGraph VectorEdges v e where
asGraph g = Graph (vs g) (toList . es g)
allEdges :: AsGraph t v e => t v e -> [e]
allEdges g = let g' = asGraph g
in nodes g' >>= edges g'
There does not seem to be something standard in Haskell to achieve my purpose, so I ended up adding a class specific for list conversion leaving me room to implement it for what I believe should be convertable lists.
class Convert_List list1 list2 element where
convert_list :: list1 element -> list2 element
Then I am free to implement it on my own.
The advantage of having such a class is that you can then write the graph operation like this:
class List_Nodes graph list vertex where
list_nodes :: graph -> list vertex
class List_Edges_From graph vertex list edge where
list_edges_from :: graph -> vertex -> list edge
class List_Edges graph vertex list edge where
list_edges :: graph -> list edge
instance (
Monad list,
List_Nodes graph l1 vertex,
List_Edges_From graph vertex l2 edge,
Convert_List l1 list vertex,
Convert_List l2 list edge
) => List_Edges graph vertex list edge where
list_edges graph =
convert_list (list_nodes graph :: l1 vertex) >>= \u ->
convert_list (list_edges_from graph u :: l2 edge)
Here you see that I implement list_edge in an very general way making few assumptions, i'm not even assuming the return list has to be the same as the graph internal representation.
This is also why I splitted each operation in its own class. Although this may seem counterintuitive at first I believe that there is more potential for factorization as shown here. If I had only one class containing the 3 operations, I could not implement only list_edges without enforcing constraints on the other operations as well.
It's only my opinion, but I believe more and more this sort of approach for code design has more potential for factoring.

Haskell data type for hmatrix Vector and Matrix

I am just starting out with Haskell, I have read up to the defining data types section of LYAH and am attempting to implement the Sum-Product algorithm for Belief Propagation. One of the rudimentary tasks is to define the Probabilistic Graphical Model.
As shown below, I have attempted to create a graph by tying the knot to represent the graph where each node represents a Gaussian distribution and has constant weight links(for now) to it's neighbours. However, when trying to define the Mean and Covariance types I am having some difficulty in specifying the types of the Matrix and Vector types, i.e. Float or Double.
module Graph(Graph) where
import Numeric.LinearAlgebra
data Mean = Mean Vector
data Covariance = Covariance Matrix
data Gaussian = Gaussian Mean Covariance
data Node = Node [Node] Gaussian
data Graph = Graph [Node]
In this simple example, what is the syntax to define Mean as a Vector of type Double and Covariance as a Matrix of type Double. Additionally, how would one generalise so that Mean and Covariance can be of type Float or Double?
I currently get the following from GHCi
Graph.hs:5:18: error:
• Expecting one more argument to ‘Vector’
Expected a type, but ‘Vector’ has kind ‘* -> *’
• In the type ‘Vector’
In the definition of data constructor ‘Mean’
In the data declaration for ‘Mean’
Failed, modules loaded: none.
I am using the hmatrix package as described here
Vector and Matrix are parameterised on the scalar type (so you can not only have matrices of floating-point “real numbers”, but also matrices of integers, complex numbers etc.). This is what GHC tells you by ‘Vector’ has kind ‘* -> *’: by itself, Vector is not a type (types have kind *, aka Type). Rather it is a type function mapping types of kind * to types of kind *. Scalars like Double are already plain types, so you can just apply Vector to them.
GHCi> :kind Vector
Vector :: * -> *
GHCi> :k Double
Double :: *
GHCi> :k Vector Double
Vector Double :: *
Thus you need
newtype Mean = Mean (Vector Double)
newtype Covariance = Covariance (Matrix Double)
(newtype does the same thing as data here, but it's a bit more efficient because no extra box/pointer is needed).
Alternatively, you may use more meaningfully-typed vector spaces, e.g.
import Math.LinearMap.Category
newtype Mean v = Mean v
newtype Covariance v = Covariance (v +> DualVector v)
The advantage of this is that dimensions are checked at compile time, which prevents nasty runtime errors (and can in principle also improve performance, though frankly the linearmap-category library is not optimised at all yet).
You'd then also parameterise the other types over the vector space:
data Gaußian v = Gaußian (Mean v) (Covariance v)
data Node v = Node [Node v] (Gaussian v)
data Graph v = Graph [Node v]
Somewhat unrelated to your question: this knot-tying sure feels elegant, but it's not really a suitable way to represent a graph, because nodes can't be identity-checked. Any cycles in the graph lead to, for all distinguishable means, an infinite structure. In practice, you won't get around giving your nodes e.g. Int labels and keeping a separate structure for the edges.

Haskell converting between vector types

I'm starting to learn Haskell, but I'm finding it hard to figure out the small, little things that the tutorials jumps over. Right now I'm working with tuples in the form of Vector.Fixed:
import qualified Data.Vector.Fixed as VF
import qualified Data.Vector.Fixed.Unboxed (Vec 2)
import qualified Data.Vector.Unboxed as VU
let a = VF.mk2 7 7 :: (Int, Int)
let b = VF.mk2 7 7 :: (Vec2 Int)
What's difference between a and b?
How can I make a VF vector f equivalent of
[a, a] = [(7,7), (7,7)]?
How can I make a VU vector g equivalent of [[a], [a,a]] = [[(7,7)], [(7,7), (7,7)]]?
For question 2 and 3, I can't get past the type errors when trying to use the convert function.
I know that my tuples always will be of length 2, but I need a list
(or whatever) f of tuples that can be fixed size, and another g
that is two-dimensional (e.g. [[(1,2),(3,4)],[(1,2)]] where
neither the top list nor the sub lists can be of fixed size. Should
I stick to the same type for f and g?
Data.Vector.Fixed and Data.Vector.Unboxed both seem to come from the
same package, but they have different maintainers. Are they both
official, so to speak, or do they not share any similarities other
than that they both are vector implementations?

Resources