\chapter{Sparse Matrices (\module{cvxopt.base})}\label{chap:spmatrix}

In this chapter we discuss the \spmtrx\ object defined in 
\module{cvxopt.base}.

\section{Creating Sparse Matrices} \label{s-creating-spmatrix}
A general \spmtrx\ object can be thought of as a \emph{triplet 
description} of a sparse matrix, \ie, a list of entries of the matrix, 
with for each entry the value, row index, and column index.  
Entries that are not included in the list are assumed to be zero.  
For example, the sparse matrix
\BEQ \label{e-sparse-A}
 A = \left[ \begin{array}{rrrrr}
  0 & 2 & 0 & 0 & 3 \\
  2 & 0 & 0 & 0 & 0 \\
 -1 & -2 & 0 & 4 & 0 \\
  0 & 0 & 1 & 0 & 0 \end{array} \right]
\EEQ
has the triplet description 
\[
(2,1,0), \qquad (-1,2,0), \qquad (2,0,1), \qquad (-2,2,1), \qquad
(1,3,2), \qquad (4,2,3), \qquad (3,0,4).
\]
The list may include entries with a zero value, so triplet
descriptions are not necessarily unique.
The list
\[
(2,1,0), \qquad (-1,2,0), \qquad (0,3,0), \qquad (2,0,1), \qquad 
 (-2,2,1), \qquad (1,3,2), \qquad (4,2,3), \qquad (3,0,4)
\]
is another triplet description of the same matrix.

An \spmtrx\ object corresponds to a particular triplet 
description of a sparse matrix.  We will refer to the entries in
the triplet description as the \emph{nonzero entries} of the object, 
even though they may have a numerical value zero.

Two functions are provided to create sparse matrices. 
The first, \function{spmatrix()}, constructs a sparse matrix from 
a triplet description. 
\begin{funcdesc}{spmatrix}{x, I, J\optional{, size\optional{, tc}}}

\var{I} and \var{J} are sequences of integers (lists, tuples, 
\module{array} arrays, xrange objects, \ldots) or integer matrices 
(\mtrx\ objects with typecode \itc), containing the row and column 
indices of the nonzero entries.  
The lengths of \var{I} and \var{J} must be  equal.  If they 
are matrices, they are treated as lists of indices stored in 
column-major order, \ie, as lists \code{list(\var{I})}, respectively, 
\code{list(\var{J})}. 

\var{size} is a tuple of nonnegative integers with the row and column 
dimensions of the matrix.
The \var{size} argument is only needed when creating a matrix with 
a zero last row or last column.  If \var{size} is not specified, it 
is determined from \var{I} and \var{J}:
the default value for \code{\var{size}[0]} is max(\var{I})+1 
if \var{I} is nonempty and zero otherwise.  
The default value for \code{\var{size}[1]} is 
max(\var{J})+1 if \var{J} is nonempty and zero otherwise.

\var{tc} is the typecode, \dtc\ or \ztc, for double and complex 
matrices, respectively.   Integer sparse matrices are not implemented.

\var{x} can be a number, a sequence of numbers, or a dense matrix.  
This argument specifies the numerical values of the nonzero entries.
\BIT
\item If \var{x} is a number (Python \intgr, \flt\ or \cmplx), 
a matrix is created with the sparsity pattern defined by \var{I} and 
\var{J}, and nonzero entries initialized to the value of \var{x}.  
The default value of \var{tc} is \dtc\ if \var{x} is \intgr\ or \flt,
and \ztc\ if \var{x} is \cmplx.  

The following code creates a 4 by 4 sparse identity matrix.
\begin{verbatim}
>>> from cvxopt.base import spmatrix
>>> A = spmatrix(1.0, range(4), range(4))
>>> print A  
[ 1.00e+00     0         0         0    ]
[    0      1.00e+00     0         0    ]
[    0         0      1.00e+00     0    ]
[    0         0         0      1.00e+00]
\end{verbatim}

\item If \var{x} is a sequence of numbers, a sparse matrix is created 
with the entries of \var{x} copied to the entries indexed by \var{I} 
and \var{J}.  The list \var{x} must have the same length as \var{I} and 
\var{J}.
The default value of \var{tc} is determined from the elements of 
\var{x}: 
\dtc\ if \var{x} contains integers and floating-point numbers or
if \var{x} is an empty list,
and \ztc\ if \var{x} contains at least one complex number.

As an example, the matrix~(\ref{e-sparse-A}) can be created as follows.
\begin{verbatim}
>>> A = spmatrix([2,-1,2,-2,1,4,3], [1,2,0,2,3,2,0], [0,0,1,1,2,3,4])
>>> print A 
[    0      2.00e+00     0         0      3.00e+00]
[ 2.00e+00     0         0         0         0    ]
[-1.00e+00 -2.00e+00     0      4.00e+00     0    ]
[    0         0      1.00e+00     0         0    ]
\end{verbatim}

\item If \var{x} is a dense matrix, a sparse matrix is created with 
all the entries of \var{x} copied, in column-major order, to the 
entries indexed by \var{I} and \var{J}.
The matrix \var{x} must have the same length as \var{I} and \var{J}.
The default value of \var{tc} is \dtc\ if \var{x} is an \itc\ or \dtc\
matrix, and \ztc\ otherwise.
\EIT

If \var{I} and \var{J} contain repeated entries, the corresponding 
values of the coefficients are added.
\end{funcdesc}

The function \function{sparse()} constructs a sparse matrix from
a block-matrix description.
   
\begin{funcdesc}{sparse}{x\optional{, tc}}
\var{tc} is the typecode, \dtc\ or \ztc, for double and complex 
matrices, respectively.
  
\var{x} can be a \mtrx, \spmtrx, or a list of lists of matrices 
(\mtrx\ or \spmtrx\ objects) and numbers (Python \intgr, \flt\ or 
\cmplx). 
\BIT
\item If \var{x} is a \mtrx\ or \spmtrx\ object, then a sparse matrix 
of the same size and the same numerical value is created. 
Numerical zeros in \var{x} are treated as structural zeros and removed 
from the triplet description of the new sparse matrix.

\item If \var{x} is a list of lists of matrices (\mtrx\ or \spmtrx) 
and numbers (Python \intgr, \flt\ or \cmplx) then each element of 
\var{x} is interpreted as a (block-)column matrix stored in 
colum-major order, and a block-matrix is constructed by juxtaposing
the \code{len(\var{x})} block-columns
(as in \function{matrix()}, see section~\ref{s-creating-matrices}). 
Numerical zeros are removed from the triplet description of the new 
matrix.  

The following example shows how to construct a sparse block-matrix.
\begin{verbatim}
>>> from cvxopt.base import matrix, spmatrix, sparse
>>> A = matrix([[1, 2, 0], [2, 1, 2], [0, 2, 1]])
>>> B = spmatrix([], [], [], (3,3))
>>> C = spmatrix([3, 4, 5], [0, 1, 2], [0, 1, 2])
>>> D = sparse([[A, B], [B, C]])
>>> print D
[ 1.00e+00  2.00e+00     0         0         0         0    ]
[ 2.00e+00  1.00e+00  2.00e+00     0         0         0    ]
[    0      2.00e+00  1.00e+00     0         0         0    ]
[    0         0         0      3.00e+00     0         0    ]
[    0         0         0         0      4.00e+00     0    ]
[    0         0         0         0         0      5.00e+00]
\end{verbatim}

A matrix with a single block-column can be represented by a single
list.
\begin{verbatim}
>>> D = sparse([A, C])
>>> print D
[ 1.00e+00  2.00e+00     0    ]
[ 2.00e+00  1.00e+00  2.00e+00]
[    0      2.00e+00  1.00e+00]
[ 3.00e+00     0         0    ]
[    0      4.00e+00     0    ]
[    0         0      5.00e+00]
\end{verbatim}
\EIT
\end{funcdesc}


The function \function{spdiag()} constructs a block-diagonal
sparse matrix from a list of matrices.
   
\begin{funcdesc}{spdiag}{x}
\var{x} is a matrix with a single row or column, or a list of square
dense or sparse matrices or scalars.  
If \var{x} is matrix, a sparse diagonal matrix is returned with 
the entries of \var{x} on its diagonal.
If \var{x} is list, a sparse block-diagonal matrix is returned with
the element in the list as its diagonal blocks.
  
The following example shows how to construct a sparse block-diagonal matrix.
\begin{verbatim}
>>> from cvxopt.base import matrix, spmatrix, spdiag
>>> A = 3.0
>>> B = matrix([[1,-2],[-2,1]])
>>> C = spmatrix([1,1,1,1,1],[0,1,2,0,0,],[0,0,0,1,2])
>>> D = spdiag([A, B, C])
>>> print D
[ 3.00e+00     0         0         0         0         0    ]
[    0      1.00e+00 -2.00e+00     0         0         0    ]
[    0     -2.00e+00  1.00e+00     0         0         0    ]
[    0         0         0      1.00e+00  1.00e+00  1.00e+00]
[    0         0         0      1.00e+00     0         0    ]
[    0         0         0      1.00e+00     0         0    ]
\end{verbatim}
\end{funcdesc}

\section{Attributes and Methods}
The following attributes and methods are defined for \spmtrx\ objects.

\begin{memberdesc}{V}
A single-column dense matrix containing the numerical values of the 
nonzero entries in column-major order.  Making an assignment to 
the attribute is an efficient way of changing the values of the sparse 
matrix, without changing the sparsity pattern.

When the attribute \member{V} is read, a \emph{copy} of \member{V} is 
returned, as a new dense matrix. 
(This implies, for example, that an indexed assignment 
\samp{A.V[I] = B} does not work, or at least 
cannot be used to modify \var{A}.  Instead the attribute \code{V}\ 
will be read and returned as a new matrix; then the elements of this 
new matrix are modified.)
\end{memberdesc} 

\begin{memberdesc}{I}
A single-column integer matrix with the row indices of the entries in
\code{V}.  A read-only attribute.
\end{memberdesc} 

\begin{memberdesc}{J}
A single-column integer matrix with the column indices of the entries
in \code{V}.  A read-only attribute.
\end{memberdesc} 

\begin{memberdesc}{size}
A tuple with the dimensions of the matrix.  A read-only attribute.
\end{memberdesc} 

\begin{memberdesc}{CCS}
A triplet (colptr, rowind, values) with the compressed-column-storage 
representation of the matrix.  A read-only attribute.  This attribute
can be used to export sparse matrices to other packages such as MOSEK.
\end{memberdesc} 


\begin{methoddesc}{trans}
Returns the transpose of a sparse matrix as a new sparse matrix.
One can also use \code{A.T} instead of \code{A.trans()}.
\end{methoddesc}

\begin{methoddesc}{ctrans}
Returns the complex conjugate transpose of a sparse matrix as a 
new sparse matrix.
One can also use \code{A.H} instead of \code{A.ctrans()}. 
\end{methoddesc}

In the following example we take the elementwise square root of 
the matrix
\BEQ \label{e-spA-example}
 A = \left[ \begin{array}{rrrrr}
  0 & 2 & 0 & 0 & 3 \\
  2 & 0 & 0 & 0 & 0 \\
  1 & 2 & 0 & 4 & 0 \\
  0 & 0 & 1 & 0 & 0 \end{array} \right]
\EEQ
\begin{verbatim}
>>> from cvxopt.base import sqrt
>>> A = spmatrix([2,1,2,2,1,3,4], [1,2,0,2,3,0,2], [0,0,1,1,2,3,3]) 
>>> B = spmatrix(sqrt(A.V), A.I, A.J)
>>> print B
[    0      1.41e+00     0      1.73e+00]
[ 1.41e+00     0         0         0    ]
[ 1.00e+00  1.41e+00     0      2.00e+00]
[    0         0      1.00e+00     0    ]
\end{verbatim}

The next example below illustrates assignments to \member{V}.
\begin{verbatim}
>>> from cvxopt.base import spmatrix, matrix
>>> A = spmatrix(range(5), [0,1,1,2,2], [0,0,1,1,2])
>>> print A
[ 0.00e+00     0         0    ]
[ 1.00e+00  2.00e+00     0    ]
[    0      3.00e+00  4.00e+00]
>>> B = spmatrix(A.V, A.J, A.I, (4,4))  # transpose and add a zero row and column
>>> print B
[ 0.00e+00  1.00e+00     0         0    ]
[    0      2.00e+00  3.00e+00     0    ]
[    0         0      4.00e+00     0    ]
[    0         0         0         0    ]
>>> print matrix(B)
[ 0.00e+00  1.00e+00  0.00e+00  0.00e+00]
[ 0.00e+00  2.00e+00  3.00e+00  0.00e+00]
[ 0.00e+00  0.00e+00  4.00e+00  0.00e+00]
[ 0.00e+00  0.00e+00  0.00e+00  0.00e+00]
>>> B.V = matrix([1., 7., 8., 6., 4.])   # assign new values to nonzero entries
>>> print B
[ 1.00e+00  7.00e+00     0         0    ]
[    0      8.00e+00  6.00e+00     0    ]
[    0         0      4.00e+00     0    ]
[    0         0         0         0    ]
>>> B.V += 1.0   # add 1 to the nonzero entries
>>> print B
[ 2.00e+00  8.00e+00     0         0    ]
[    0      9.00e+00  7.00e+00     0    ]
[    0         0      5.00e+00     0    ]
[    0         0         0         0    ]
\end{verbatim}

The \member{V}, \member{I} and \member{J}  attributes can be used for 
reading sparse matrices from or writing them to binary files.  
Suppose we want to write the matrix \var{A} defined above to a binary 
file.
\begin{verbatim}
>>> f = open('test.bin','w')
>>> A.V.tofile(f)  
>>> A.I.tofile(f) 
>>> A.J.tofile(f)
>>> f.close()
\end{verbatim}
A sparse matrix can be created from this file as follows.
\begin{verbatim}
>>> f = open('test.bin','r')
>>> V = matrix(0.0, (5,1));  V.fromfile(f)  
>>> I = matrix(0, (5,1));  I.fromfile(f)  
>>> J = matrix(0, (5,1));  J.fromfile(f)  
>>> B = spmatrix(V, I, J)
>>> print B
[ 0.00e+00     0         0    ]
[ 1.00e+00  2.00e+00     0    ]
[    0      3.00e+00  4.00e+00]
\end{verbatim}

Note that the  \module{pickle} module provides a convenient alternative 
to this method.

\section{Arithmetic Operations} \label{s-spmatrix-arith}
Most of the operations defined for dense \dtc\ and \ztc\ matrices
(section~\ref{s-arithmetic}) are also defined for sparse matrices.
In the following table, \var{A} is a sparse matrix,
\var{B} is sparse or dense, and \var{c} is a scalar, defined as a
Python number or a 1 by 1 dense matrix.

\begin{center}
\begin{tabular}{l|l} \hline
 Unary plus/minus & \code{+\var{A}}, \code{-\var{A}} \\ \hline
 Addition & \code{\var{A}+\var{B}}, \code{\var{B}+\var{A}}, 
   \code{\var{A}+\var{c}}, \code{\var{c}+\var{A}}\\ \hline
 Subtraction & \code{\var{A}-\var{B}}, \code{\var{B}-\var{A}}, 
    \code{\var{A}-\var{c}}, \code{\var{c}-\var{A}}\\ \hline
 Matrix multiplication & \code{\var{A}*\var{B}}, 
  \code{\var{B}*\var{A}} \\ \hline
 Scalar multiplication and division & \code{\var{c}*\var{A}}, 
   \code{\var{A}*\var{c}}, \code{\var{A}/\var{c}} \\\hline
 \end{tabular}
\end{center}

If \var{B} is a dense matrix, then the result of 
\code{\var{A}+\var{B}}, \code{\var{B}+\var{A}}, \code{\var{A}-\var{B}}, 
\code{\var{B}-\var{A}} is a dense  matrix.
The typecode of the result is \dtc\ if \var{A} has typecode \dtc\ and 
\var{B} has typecode \itc\ or \dtc,
and it is \ztc\ if \var{A} and/or \var{B} have typecode \ztc.

If \var{B} is a sparse matrix, then the result of
\code{\var{A}+\var{B}}, \code{\var{B}+\var{A}}, 
\code{\var{A}-\var{B}}, \code{\var{B}-\var{A}} is a sparse 
matrix.  The typecode of the result is \dtc\ if \var{A} and \var{B}
have typecode \dtc,  and \ztc\ otherwise.

If \var{c} in \code{\var{A}+\var{c}}, \code{\var{A}-\var{c}}, 
\code{\var{c}+\var{A}}, \code{\var{c}-\var{A}} is a number,
then it is interpreted as a dense matrix with the same size as 
\var{A}, typecode given by the type of \var{c}, and all entries equal 
to \var{c}. 
If \var{c} is a 1 by 1 dense matrix and the size of \var{A} is not 1 
by 1, then \var{c}
is interpreted as a dense matrix of the same size as \var{A},
typecode given by the typecode of \var{c}, and all entries equal to 
\code{\var{c}[0]}.

The result of a matrix-matrix product \code{\var{A}*\var{B}} or 
\code{\var{B}*\var{A}} is a dense matrix if \var{B} is dense, and sparse
if \var{B} is sparse.   The matrix-matrix product is not allowed if 
\var{B} is a dense \itc\ matrix.  

If \var{c} is a number (Python \intgr\, \flt\ or \cmplx), then the 
operations \code{\var{c}*\var{A}} and \code{\var{A}*\var{c}} define 
scalar multiplication and return a sparse matrix.

If \var{c} is a 1 by 1 dense matrix, then, if possible, the products 
\code{\var{c}*\var{A}} and \code{\var{A}*\var{c}} are interpreted as 
matrix-matrix products and a dense matrix is returned.  
If the product cannot be interpreted as a matrix-matrix product
(either because the dimensions of \var{A} are incompatible or because
\var{c} has typecode \itc), then the product is interpreted as the 
scalar multiplication with \code{\var{c}[0]} and a sparse matrix is 
returned.

The division \code{\var{A}/\var{c}} is interpreted as scalar 
multiplication with \code{1.0/\var{c}} if \var{c} is a number, 
or with  \code{1.0/\var{c}[0]} if \var{c} is a 1 by 1 dense matrix.

The following in-place operations are defined for a sparse matrix 
\var{A} if they do not change the dimensions or type of \var{A}.
\begin{center}
  \begin{tabular}{l|l} \hline
  In-place addition & \code{\var{A}+=\var{B}}, 
    \code{\var{A}+=\var{c}} \\ \hline   
  In-place subtraction & \code{\var{A}-=\var{B}}, 
    \code{\var{A}-=\var{c}} \\ \hline   
  In-place scalar multiplication and division & 
    \code{\var{A}*=\var{c}}, \code{\var{A}/=\var{c}}  \\ \hline
  \end{tabular}
\end{center}

For example, \samp{\var{A} += 1.0} is not allowed because the 
operation \samp{\var{A} = \var{A} + 1.0} results in a dense matrix, 
so it cannot be assigned to \var{A} without changing its type.

In-place matrix-matrix products are not allowed.  (Except when
\var{c} is a 1 by 1 dense matrix, in which case \code{\var{A}*=\var{c}} 
is interpreted as a scalar product \code{\var{A}*=\var{c}[0]}.)

As for dense operations, the in-place sparse operations do not return
a new matrix but modify the existing object \var{A}.
The restrictions on in-place operations follow the principle that once 
a sparse matrix is created, its size and type cannot be modified.  
The only attributes that can be modified are the sparsity pattern and 
the numerical values of the nonzero elements.
These attributes can be modified by in-place operations or by indexed 
assignments.



\section{Indexing and Slicing} 
Sparse matrices can be indexed the same way as dense matrices 
(see section~\ref{s-indexing} ).  

\begin{verbatim}
>>> from cvxopt.base import spmatrix
>>> A = spmatrix([0,2,-1,2,-2,1], [0,1,2,0,2,1], [0,0,0,1,1,2]) 
>>> print A[:,[0,1]]
[ 0.00e+00  2.00e+00]
[ 2.00e+00     0    ]
[-1.00e+00 -2.00e+00]
>>> B = spmatrix([0,2*1j,0,-2], [1,2,1,2], [0,0,1,1,])
>>> print B[-2:,-2:]
[ 0.00e+00-j0.00e+00  0.00e+00-j0.00e+00]
[ 0.00e+00+j2.00e+00 -2.00e+00-j0.00e+00]
\end{verbatim}

An indexed sparse matrix \code{\var{A}[\var{I}]} or 
\code{\var{A}[\var{I},\var{J}]} can also be the target of an 
assignment.  The righthand side of the assignment can be a scalar
(a Python \intgr, \flt, or \cmplx,  or a 1 by 1 dense matrix),
a sequence of numbers, or a sparse or dense matrix of 
compatible dimensions. 
If the righthand side is a scalar, it is treated as a dense matrix of 
the same size as the lefthand side and with all its entries equal to 
the scalar. 
If the righthand side is a sequence of numbers, they are treated as
the elements of a dense matrix in column-major order. 

We continue the example above.
\begin{verbatim}
>>> C = spmatrix([10,-20,30], [0,2,1], [0,0,1])
>>> A[:,0] = C[:,0]
>>> print A
[ 1.00e+01  2.00e+00     0    ]
[    0         0      1.00e+00]
[-2.00e+01 -2.00e+00     0    ]
>>> D = matrix(range(6), (3,2))
>>> A[:,0] = D[:,0]
>>> print A
[ 0.00e+00  2.00e+00     0    ]
[ 1.00e+00     0      1.00e+00]
[ 2.00e+00 -2.00e+00     0    ]
>>> A[:,0] = 1
>>> print A
[ 1.00e+00  2.00e+00     0    ]
[ 1.00e+00     0      1.00e+00]
[ 1.00e+00 -2.00e+00     0    ]
>>> A[:,0] = 0
>>> print A
[ 0.00e+00  2.00e+00     0    ]
[ 0.00e+00     0      1.00e+00]
[ 0.00e+00 -2.00e+00     0    ]
\end{verbatim}


\section{Built-In Functions}

The functions described in the table of section~\ref{s-builtinfuncs} 
also work with sparse matrix arguments.  The difference is that for a 
sparse matrix only the nonzero entries are considered. 

\begin{funcdesc}{len}{x}
If \var{x} is a \spmtrx, returns the number of nonzero entries in
\var{x}.
\end{funcdesc}

\begin{funcdesc}{bool}{\optional{x}}
If \var{x} is a \spmtrx, returns \False\ if \var{x} has at least one 
nonzero entry; \False\ otherwise.
\end{funcdesc}

\begin{funcdesc}{max}{x}
If \var{x} is a \spmtrx, returns the maximum nonzero entry of \var{x}.
\end{funcdesc}

\begin{funcdesc}{min}{x}
If \var{x} is a \spmtrx, returns the minimum nonzero entry of \var{x}.
\end{funcdesc}

\begin{funcdesc}{abs}{x}
If \var{x} is a \spmtrx, returns a sparse matrix with the absolute
value of the elements of \var{x} and the same sparsity pattern.
\end{funcdesc}

\begin{funcdesc}{sum}{x\optional{, start=0.0}}
If \var{x} is a \spmtrx, returns the sum of \var{start} and the 
elements of \var{x}.
\end{funcdesc}

The functions \function{list()}, \function{tuple()}, \function{zip()}, 
\function{map()}, \function{filter()} also take sparse matrix arguments.
They work as for dense matrices, again with the difference that only 
the nonzero entries are considered.

In the following example we square the entries of the 
matrix~(\ref{e-spA-example}). 

\begin{verbatim}
>>> A = spmatrix([2,1,2,2,1,3,4], [1,2,0,2,3,0,2], [0,0,1,1,2,3,3]) 
>>> B = spmatrix(map(lambda x: x**2, A), A.I, A.J)
>>> print B
[    0      4.00e+00     0      9.00e+00]
[ 4.00e+00     0         0         0    ]
[ 1.00e+00  4.00e+00     0      1.60e+01]
[    0         0      1.00e+00     0    ]
\end{verbatim}

The expression \samp{\var{x} in \var{A}} returns \True\  if a nonzero
entry of \var{A} is equal to \var{x} and \False\ otherwise.


\section{Sparse BLAS Functions}
The \module{cvxopt.base} module includes a few arithmetic functions 
that extend functions from \module{cvxopt.blas} to sparse matrices.
These functions are faster than the corresponding operations 
implemented using the overloaded arithmetic described 
in~section~\ref{s-spmatrix-arith}.
They also work in-place, \ie, they modify their arguments without 
creating new objects.


\begin{funcdesc}{gemv}{A, x, y\optional{, trans='N'\optional{, 
  alpha=1.0\optional{, beta=0.0}}}}
Matrix-vector product with a general dense or sparse matrix:
\[ 
y := \alpha Ax + \beta y \quad (\mathrm{trans} = \mathrm{'N'}),
  \qquad 
y := \alpha A^T x + \beta y \quad (\mathrm{trans} = \mathrm{'T'}), 
  \qquad
y := \alpha A^H x + \beta y \quad (\mathrm{trans} = \mathrm{'C'}). 
\]
If \var{A} is a dense matrix, this is identical to 
\function{blas.gemv()}.  If \var{A} is sparse, the result is the same 
as when \function{blas.gemv()} is called with \code{matrix(A)} as 
argument, however, without explicitly converting \var{A} to dense.
\end{funcdesc}

\begin{funcdesc}{symv}{A, x, y\optional{, uplo='L'\optional{, 
alpha=1.0\optional{, beta=0.0}}}} 
Matrix-vector product with a dense or sparse real symmetric matrix:
\[
   y := \alpha A x + \beta y.
\]
If \var{A} is a dense matrix, this is identical to 
\function{blas.symv()}.  If \var{A} is sparse, the result is the same 
as when \function{blas.symv()} is called with \code{matrix(A)} as 
argument, however, without explicitly converting \var{A} to dense.
\end{funcdesc}

\begin{funcdesc}{gemm}{A, B, C\optional{, transA='N'\optional{, 
transB='N'\optional{, alpha=1.0\optional{, beta=0.0\optional{, 
partial=False}}}}}}
Matrix-matrix product of two general sparse or dense matrices:
\[
  C := \alpha \op(A) \op(B) + \beta C 
\]
where
\[
\op(A) =  \left\{ \begin{array}{ll}
 A & \mathrm{transA} = \mathrm{'N'} \\
 A^T & \mathrm{transA} = \mathrm{'T'} \\
 A^H & \mathrm{transA} = \mathrm{'C'} \end{array} \right.
\qquad
\op(B) =  \left\{ \begin{array}{ll}
 B & \mathrm{transB} = \mathrm{'N'} \\
 B^T & \mathrm{transB} = \mathrm{'T'} \\
 B^H & \mathrm{transB} = \mathrm{'C'}. \end{array} \right.
\]
If \var{A}, \var{B} and \var{C} are dense matrices, this is 
identical to \function{blas.gemm()}, described in section~\ref{s-blas3},
and the argument \var{partial} is ignored.

If \var{A} and/or \var{B} are sparse and \var{C} is dense, the result
is the same as when \function{blas.gemm()} is called with
\code{matrix(A)} and \code{matrix(B)} as arguments, without explicitly 
converting  \var{A} and \var{B} to dense.
The argument \var{partial} is ignored.

If \var{C} is a sparse matrix, the matrix-matrix product in the
definition of \function{blas.gemm()} is computed, but as a sparse 
matrix.  
If \var{partial} is \False, the result is stored in \var{C}, 
and the sparsity pattern of \var{C} is  modified if necessary.
If \var{partial} is \True, the operation only updates the nonzero
elements in \var{C}, even if the sparsity pattern of \var{C} differs
from that of the matrix product.  
\end{funcdesc}

\begin{funcdesc}{syrk}{A, C\optional{, uplo='L'\optional{, 
trans='N'\optional{, alpha=1.0\optional{, beta=0.0\optional{, 
partial=False}}}}}}
Rank-\tm{k} update of a sparse or dense real or complex symmetric
matrix:
\[
 C := \alpha AA^T + \beta C \quad (\mathrm{trans} = \mathrm{'N'}), 
 \qquad 
 C := \alpha A^TA + \beta C \quad (\mathrm{trans} = \mathrm{'T'}), 
\]
If \var{A} and \var{C} are dense, this is identical to 
\function{blas.syrk()}, described in section~\ref{s-blas3},
and the argument \var{partial} is ignored.

If \var{A} is sparse and \var{C} is dense, the result is the same as 
when \function{blas.syrk()} is called with \code{matrix(A)} as 
argument, without explicitly converting  \var{A} to dense.  
The argument \var{partial} is ignored.

If \var{C} is sparse, the product in the definition of 
\function{blas.syrk()} is computed, but as a sparse matrix.  
If \var{partial} is \False, the result is stored in \var{C}, 
and the sparsity pattern of \var{C} is  modified if necessary.
If \var{partial} is \True, the operation only updates the nonzero
elements in \var{C}, even if the sparsity pattern of \var{C} differs
from that of the matrix product.  
\end{funcdesc}

In the following example, we first compute 
\[
C =  A^TB, \qquad
A = \left[ \begin{array}{ccc}
0 & 1 & 0 \\ 1 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \end{array}\right],
\qquad
B = \left[ \begin{array}{ccc}
   0 & -1 & 0 \\ 2 & 0 & 2 \\ 0 & 3 & 0 \\ 2 & 0 & 0 
   \end{array}\right].
\]
\begin{verbatim}
>>> from cvxopt.base import spmatrix, gemm
>>> A = spmatrix(1, [1,3,0,2,1], [0,0,1,1,2])
>>> B = spmatrix([2,2,-1,3,2], [1,3,0,2,1], [0,0,1,1,2])
>>> C = spmatrix([], [], [], size=(3,3))
>>> gemm(A, B, C, transA='T')
>>> print C
[ 4.00e+00     0      2.00e+00]
[    0      2.00e+00     0    ]
[ 2.00e+00     0      2.00e+00]
\end{verbatim}
Now suppose we want to replace \var{C}  with
\[
C = A^TD, \qquad 
D = \left[ \begin{array}{ccc}
   0 & 1 & 0 \\ 3 & 0 & -2 \\ 0 & 1 & 0 \\ 4 & 0 & 0 
   \end{array}\right].
\]
The new matrix has the same sparsity pattern as \var{C}, so we can 
use \function{gemm()} with the \code{partial=True} option.
This saves time in large sparse matrix multiplications when the 
sparsity pattern of the result is known beforehand.
\begin{verbatim}
>>> D = spmatrix([3,4,1,1,-2], [1,3,0,2,1], [0,0,1,1,2])
>>> gemm(A, D, C, transA='T', partial=True)
>>> print C
[ 7.00e+00     0     -2.00e+00]
[    0      2.00e+00     0    ]
[ 3.00e+00     0     -2.00e+00]
\end{verbatim}
