-- The `matrix` data type wraps a SuiteSparse GrB_Matrix handle and
-- delegates functions from SQL to the library through instances of
-- this type.
--
-- An empty matrix can be constructed many ways, but one of the
-- simplest is casting a type code to the matrix type. In this case
-- `int32` means the SuiteSparse type `GrB_INT32`.
select'int32'::matrix;
-- Another way to create an empty matrix is to use the `matrix()`
-- constructor function:
select matrix('int32');
-- ## Matrix dimensions
--
-- The above matrices are "unbounded", they do not have a fixed number
-- of rows and/or columns. The default possible number of rows and
-- columns is defined by the SuiteSparse library to be `GrB_INDEX_MAX`
-- which is `2^60` power indexes. For the purposes of this
-- documentation this will be referred to as `INDEX_MAX` and matrices
-- and vector dimensions that are `INDEX_MAX` in size are reffered to
-- as "unbounded".
--
-- For matrices with known dimensions, the dimensions can be provided
-- in parentesis after the type code. Here a 4 row by 4 column
-- matrix is created:
select'int32(4:4)'::matrix;
-- Another way to make a new matrix is with the `matrix` constructor
-- function.
select matrix('int32', 4, 4);
-- Either dimension can be ommited, this creates a 4 row by unbounded
-- column matrix.
select'int32(4:)'::matrix;
-- This creates a unbounded row by 4 column matrix.
select'int32(:4)'::matrix;
-- All graphblas operations are exposed by a series of functions and
-- operators. Here we see three very common operations, returning the
-- number of rows, the number of columns, and the number of store
-- values.
select nrows('int32'::matrix),
ncols('int32'::matrix),
nvals('int32'::matrix);
-- Above you can see the matrix has unbounded rows and columns (the
-- very large number is the number of *possible* entries). And the
-- number of stored values is zero. These matrices are empty, they
-- contain no elements.
--
-- Values can be specified after the `type(dimension)` prefix as an
-- array of elements between square brackets. Empty brackets imply no
-- elements, so empty square brackets are the same as no square
-- brackets as above:
select nrows('int32[]'::matrix),
ncols('int32[]'::matrix),
nvals('int32[]'::matrix);
-- Elements are specified between square brackets are coordinates of
-- 'row_id:column_id:value' separated by spaces:
select'int32[1:2:1 2:3:2 3:1:3]'::matrix,
'int32(4:)[1:2:1 2:3:2 3:1:3]'::matrix,
'int32(:4)[1:2:1 2:3:2 3:3:1]'::matrix;
-- ## Elements
--
-- All the elements in a matrix can be iterated with the `elements()`
-- function:
select*from elements((select a from test_fixture));
-- The inverse operation of constructing matrices from rows can be
-- done with `matrix_agg()`:
select matrix_agg(i, i, i) as unbound_matrix from generate_series(0, 10) as i;
-- Aggregate matrices are always unbounded so use `resize()` to bound
-- the matrix:
select print(resize(matrix_agg(i, i, i), 10, 10)) as bound_matrix from generate_series(0, 10) as i;
-- ## Equality
--
-- Two matrices can be compared for equality with the '=' and '!=' operators:
select a != b as"a != b", a = b as"a = b", b = a as"b = a", b = b as"b = b"from test_fixture;
-- ## Setting and Getting individual Elements
-- Elements can be set individually with `set_element`, the modified
-- input is returned:
select print(set_element(a, 1, 1, 1)) as set_element from test_fixture;
-- Scalar elements can be extracted individually with `get_element`
select get_element(a, 3, 2) as get_element from test_fixture;
-- If an element does exist `get_element` will return an "empty"
-- scalar:
select get_element(a, 3, 3) as get_element from test_fixture;
-- ## Elementwise Addition
--
-- The GraphBLAS API has elementwise operations on matrices that
-- operate pairs of matrices. `eadd` computes the element-wise
-- “addition” of two matrices a and b, element-wise using any binary
-- operator. The "add" in the name means that the union of both
-- graphs is taken; elements present on both sides of the operation
-- are included in the result.
select print(a) as a, binaryop, print(b) as b, print(eadd(a, b, binaryop)) as"eadd(a, b, binaryop)"from test_fixture;
-- Eadd can also be accomplished with binary operators specific to
-- OneSparse. Different binaryops are passed to eadd to do different
-- elementwise operations:
select print(a |+ b) as"a |+ b", print(a |- b) as"a |- b", print(a |* b) as"a |* b", print(a |/ b) as"a |/ b"from test_fixture;
-- From a graph standpoint, elementwise addition can be seen as the
-- merging ("union") of two graphs, such that the result has edges
-- from both graphs. Any edges that occur in both graphs are merged
-- with the provided binary operator.
select draw(a) as binop_a_source, draw(b) as binop_b_source, draw(eadd(a, b, binaryop)) as binop_c_source from test_fixture \gset
\i sql/binop.sql
-- ## Elementwise Multiplication
--
-- `emult` multiplies elements of two matrices, taking only the
-- intersection of common elements in both matrices, if an element is
-- missing from either the left or right side, it is ommited from the
-- result:
select print(a) as a, binaryop, print(b) as b, print(emult(a, b, binaryop)) as"emult(a, b, binaryop)"from test_fixture;
-- Emult can also be accomplished with binary operators specific to
-- OneSparse. Different binaryops are passed to emult to do different
-- elementwise operations:
select print(a &+ b) as"a &+ b", print(a &- b) as"a &- b", print(a &* b) as"a &* b", print(a &/ b) as"a &/ b"from test_fixture;
-- From a graph standpoint, elementwise multiplication can be seen as
-- the intersection of two graphs, such that the result has edges that
-- are only present in both graphs. The edges are combined with the
-- provided binary operator.
select draw(a) as binop_a_source, draw(b) as binop_b_source, draw(emult(a, b, binaryop)) as binop_c_source from test_fixture \gset
\i sql/binop.sql
-- ## Elementwise Union
--
-- `eunion` is like `eadd` but differs in how the binary op is
-- applied. A pair of scalars, `alpha` and `beta` define the inputs to
-- the operator when entries are present in one matrix but not the
-- other.
select print(a) as a, binaryop, print(b) as b, print(eunion(a, 3::scalar, b, 4::scalar, binaryop)) as"eunion(a, 3::scalar, b, 4::scalar, binaryop)"from test_fixture;
-- From a graph standpoint, elementwise union is very similar to
-- `eadd()`, and can be seen as the merging ("union") of two graphs,
-- such that the result has edges from both graphs. Any edges that
-- occur in both graphs are merged with the provided binary operator.
-- If an edge occurs in a but not in b, it is combined with the
-- scalar `alpha`, if the edge occurs in the b but not in a, then
-- the edge is combined with scalar `beta`.
select draw(a) as binop_a_source, draw(b) as binop_b_source, draw(eunion(a, 3::scalar, b, 4::scalar, binaryop)) as binop_c_source from test_fixture \gset
\i sql/binop.sql
-- ## Reduction
--
-- The entire matrix can be reduced to a scalar value:
select print(b) as b, 'plus_monoid_int32'as monoid, reduce_scalar(b) from test_fixture;
-- The entire matrix can be reduced to a scalar value with a provided
-- monoid that changes the reduction operation:
select print(b) as b, 'min_monoid_int32'as monoid, reduce_scalar(b, 'min_monoid_int32') from test_fixture;
-- The matrix can also be reduced to a column vector:
select print(b) as b, 'plus_monoid_int32'as monoid, print(reduce_cols(b)) as reduce_cols from test_fixture;
-- To reduce a row vector:
select print(b) as b, 'plus_monoid_int32'as monoid, print(reduce_rows(b)) as reduce_rows from test_fixture;
-- ## Matrix Matrix Multiplication
--
-- Matrix Multiplication is the heart of linear algebra. All matrix
-- multiplication happens over a semiring. For the most common form
-- of matrix multiplication, the outer opperation is to multiply
-- coresponding elements with the "times" operator and then reduce
-- those products with the "plus" operator. This is called the
-- `plus_times` semiring:
select print(a) as a, semiring, print(b) as b, print(mxm(a, b)) as"mxm(a, b)"from test_fixture;
select draw(a) as binop_a_source, draw(b) as binop_b_source, draw(mxm(a, b)) as binop_c_source from test_fixture \gset
\i sql/binop.sql
-- AxB can also be done with the `@` operator, mimicking the Python
-- syntax. The default semiring for numeric types is `plus_times`.
select print(a) as a, '@'as"@", print(b) as b, print(a @ b) as"a @ b"from test_fixture;
-- ## Matrix Vector Multiplication
--
-- Matrices can be multipled by vectors on the right taking the linear
-- combination of the matrices columns using the vectors elements as
-- coefficients:
select print(a) as a, '@'as"@", semiring, print(u) as u, print(mxv(a, u)) as"mxv(a, u)"from test_fixture;
-- From a graph standpoint, matrix vector multiplication is used to
-- "pull" back to adjacent nodes from their incoming edges. When
-- iterated, it forms the basis for working back along incoming links.
select draw(a) as binop_a_source, draw(u) as binop_b_source, draw(mxv(a, u)) as binop_c_source from test_fixture \gset
\i sql/binop.sql
-- 'mxv' is also supported by the `@` operator:
select print(a) as a, '@'as"@", print(u) as u, print(a @ u) as"a @ u"from test_fixture;
-- ## Vector Matrix Multiplication
--
-- Matrices can be multipled by vectors on the right taking the linear
-- combination of the matrices rows using the vectors elements as
-- coefficients:
select print(v) as v, semiring, print(b) as b, print(vxm(v, b, semiring)) as"vxm(v, b, semiring)"from test_fixture;
-- From a graph standpoint, vector matrix multiplication is used to
-- "push" forward to adjacent nodes from their outgoing edges. When
-- iterated, it forms the basis for working forward along outgoing
-- edges.
select draw(v) as binop_a_source, draw(b) as binop_b_source, draw(vxm(v, b)) as binop_c_source from test_fixture \gset
\i sql/binop.sql
-- 'vxm' is also supported by the `@` operator:
select print(v) as v, '@'as"@", print(b) as b, print(v @ b) as"v @ b"from test_fixture;
-- ## Choosing Elements
--
-- The `choose` method calls the `GrB_select()` API function. The
-- name `choose` was chosen not to conflict with the SQL keyword
-- `select`. Selection provides a conditional operator called an
-- `indexunaryop` and a parameter for the operator to use to compare
-- elements in the matrix. Below, all elements with values greater
-- than 1 are returned:
select print(a) as a, indexunaryop, print(choose(a, indexunaryop, 1)) as selected from test_fixture;
select draw(a) as uop_a_source, draw(choose(a, indexunaryop, 1)) as uop_b_source from test_fixture \gset
\i sql/uop.sql
-- ## Choosing Operators
-- Selection can also be done with scalars and operators:p