Sparse Matrices in IronPython QuickStart Sample

Illustrates using sparse vectors and matrices using the classes in the Numerics.NET.LinearAlgebra.Sparse namespace in IronPython.

View this sample in: C# Visual Basic F#

```Python
import numerics

from System import Array

from Extreme.Mathematics import *
# The sparse vector and matrix classes reside in the 
# Extreme.Mathematics.LinearAlgebra namespace.
from Extreme.Mathematics.LinearAlgebra import *
    
# Illustrates using sparse vectors and matrices using the classes
# in the Extreme.Mathematics.LinearAlgebra.Sparse namespace 
# of Numerics.NET.

#
# Sparse vectors
#

# The SparseVector class has three constructors. The
# first simply takes the length of the vector. All components
# are initially zero.
v1 = Vector.CreateSparse(1000000)

# The second constructor lets you specify how many components
# are expected to be nonzero. This 'fill factor' is a number
# between 0 and 1.
v2 = Vector.CreateSparse(1000000, 1e-4)

# The second constructor lets you specify how many components
# are expected to be nonzero. This 'fill factor' is a number
# between 0 and 1.
v3 = Vector.CreateSparse(1000000, 100)

# The fourth constructor lets you specify the indexes of the nonzero
# components and their values as arrays:
indexes = Array[int]([ 1, 10, 100, 1000, 10000 ])
values = Array[float]([ 1.0, 10.0, 100.0, 1000.0, 10000.0 ])
v4 = Vector.CreateSparse(1000000, indexes, values)

# Components can be accessed individually:
v1[1000] = 2.0
print "v1[1000] =", v1[1000]

# The NonzeroCount returns how many components are non zero:
print "v1 has", v1.NonzeroCount, "nonzeros"
print "v4 has", v4.NonzeroCount, "nonzeros"

# The NonzeroComponents property returns a collection of 
# IndexValuePair structures that you can use to iterate
# over the components of the vector:
print "Nonzero components of v4:"
for pair in v4.NonzeroComponents:
    print "Component {0} = {1}".format(pair.Index, pair.Value)

# All other vector methods and properties are also available, # Their implementations take advantage of sparsity.
print "Norm(v4) =", v4.Norm()
print "Sum(v4) =", v4.GetSum()
            
# Note that some operations convert a sparse vector to a
# DenseVector, causing memory to be allocated for all
# components.
            
#
# Sparse Matrices
#

# All sparse matrix classes inherit from SparseMatrix. This is an abstract class.
# There currently is only one implementation class:
# SparseCompressedColumnMatrix. 

# Sparse matrices are created by calling the CreateSparse factory
# method on the Matrix class. It has 4 overloads:

# The first overload takes the number of rows and columns as arguments:
m1 = Matrix.CreateSparse(100000, 100000)

# The second overload adds a fill factor:
m2 = Matrix.CreateSparse(100000, 100000, 1e-5)

# The third overload uses the actual number of nonzero components rather than 
# the fraction:
m3 = Matrix.CreateSparse(10000, 10000, 20000)

# The fourth overload lets you specify the locations and values of the
# nonzero components:
rows = Array[int]([ 1, 11, 111, 1111 ])
columns = Array[int]([ 2, 22, 222, 2222 ])
matrixValues = Array[float]([  3.0, 33.0, 333.0, 3333.0 ])
m4 = Matrix.CreateSparse(10000, 10000, rows, columns, matrixValues)

# You can access components as before...
print "m4[111, 222] =", m4[111, 222]
m4[99, 22] = 99.0

# A series of Insert methods lets you build a sparse matrix from scratch:
# A single value:
m1.InsertEntry(25.0, 200, 500)
# Multiple values:
m1.InsertEntries(matrixValues, rows, columns)
# Multiple values all in the same column:
m1.InsertColumn(33, values, indexes)
# Multiple values all in the same row:
m1.InsertRow(55, values, indexes)

# A clique is a 2-dimensional submatrix with indexed rows and columns.
clique = Matrix([[11, 12], [21, 22]])
cliqueIndexes = Array[int]([ 5, 8 ])
m1.InsertClique(clique, cliqueIndexes, cliqueIndexes)

# You can use the NonzeroComponents collection to iterate
# over the nonzero components of the matrix. The items
# are of type RowColumnValueTriplet:
print "Nonzero components of m1:"
for triplet in m1.NonzeroComponents:
    print "m1[{0},{1}] = {2}".format(triplet.Row, triplet.Column, triplet.Value)

# ... including rows and columns.
column = m4.GetColumn(22)
print "Nonzero components in column 22 of m4:"
for pair in column.NonzeroComponents:
    print "Component {0} = {1}".format(pair.Index, pair.Value)

# Many matrix methods have been optimized to take advantage of sparsity:
print "F-norm(m1) =", m1.FrobeniusNorm()
            
# But beware: some revert to a dense algorithm and will fail on huge matrices:
try:
    inverse = m1.GetInverse()
except MemoryError as e:
    print e.message
```