The DOK Sparse Matrix Types

Mendz.Library.Matrices abstracted the sparse matrix via IDOKSparseMatrix and DOKSparseMatrixBase. Now it's time to create the classes DOKSparseMatrix and DOKConcurrentSparseMatrix. From these, the coordinates keyed and linear index keyed concrete classes will be created. If you've been waiting for it, note that Mendz.Graphs..Sparse matrices use CoordinatesKeyedConcurrentSparseMatrix, which is described in this article.

The DOKSparseMatrix is the default implementation that uses Dictionary<K, T>.

DOKSparseMatrix.cs
using System.Collections.Generic;

namespace Mendz.Library.Matrices
{
    public class DOKSparseMatrix<K, T> 
        : DOKSparseMatrixBase<Dictionary<K, T>, K, T>
    {
        public DOKSparseMatrix((int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode = MatrixLinearIndexMode.RowMajorOrder, 
            T defaultValue = default(T), T diagonal = default(T)) 
            : base(size, linearIndexMode, defaultValue, diagonal)
        {

        }
    }
}

The DOKConcurrentSparseMatrix is a thread-safe version that uses ConcurrentDictionary<K, T>.

DOKConcurrentSparseMatrix.cs
using System.Collections.Concurrent;

namespace Mendz.Library.Matrices
{
    public class DOKConcurrentSparseMatrix<K, T> 
        : DOKSparseMatrixBase<ConcurrentDictionary<K, T>, K, T>
    {
        public override bool IsConcurrent { get; protected set; } = true;

        public DOKConcurrentSparseMatrix((int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode = MatrixLinearIndexMode.RowMajorOrder, 
            T defaultValue = default(T), T diagonal = default(T)) 
            : base(size, linearIndexMode, defaultValue, diagonal)
        {

        }

        public override void SetEntry(K key, T value)
        {
            Matrix.AddOrUpdate(key, value, (k, v) => value);
        }
    }
}

Observe that the IsConcurrent property is set to true. Observe also that the SetEntry() method is overridden to use ConcurrentDictionary's AddOrUpdate() method.

The concrete classes are the CoordinatesKeyedSparseMatrix, CoordinatesKeyedConcurrentSparseMatrix, LinearIndexKeyedSparseMatrix and LinearIndexKeyedConcurrentSparseMatrix as listed below. Note that the linear index keyed sparse matrix requires the matrix linear index mode to be set.

namespace Mendz.Library.Matrices
{
    public class CoordinatesKeyedSparseMatrix<T> 
        : DOKSparseMatrix<(int row, int column), T>
    {
        public CoordinatesKeyedSparseMatrix((int rows, int columns) size, 
            T defaultValue = default(T), T diagonal = default(T)) 
            : base(size, MatrixLinearIndexMode.RowMajorOrder, defaultValue, diagonal)
        {

        }
    }

    public class CoordinatesKeyedConcurrentSparseMatrix<T> 
        : DOKConcurrentSparseMatrix<(int row, int column), T>
    {
        public CoordinatesKeyedConcurrentSparseMatrix((int rows, int columns) size, 
            T defaultValue = default(T), T diagonal = default(T)) 
            : base(size, MatrixLinearIndexMode.RowMajorOrder, defaultValue, diagonal)
        {

        }
    }

    public class LinearIndexKeyedSparseMatrix<T> 
        : DOKSparseMatrix<int, T>
    {
        public LinearIndexKeyedSparseMatrix((int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode, 
            T defaultValue = default(T), T diagonal = default(T)) 
            : base(size, linearIndexMode, defaultValue, diagonal)
        {

        }
    }

    public class LinearIndexKeyedConcurrentSparseMatrix<T> 
        : DOKConcurrentSparseMatrix<int, T>
    {
        public LinearIndexKeyedConcurrentSparseMatrix((int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode, 
            T defaultValue = default(T), T diagonal = default(T)) 
            : base(size, linearIndexMode, defaultValue, diagonal)
        {

        }
    }
}

These various concrete types can be created via SparseMatrixFactory. It is recommended that only the concrete classes are used in application codes. Thus, it is recommended that the SparseMatrixFactory is used to create sparse matrices from Mendz.Library.Matrices.

SparseMatrixFactory.cs
namespace Mendz.Library.Matrices
{
    public static class SparseMatrixFactory
    {
        public static IDOKSparseMatrix<(int row, int column), T> Create<T>(
            (int rows, int columns) size, bool concurrent, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            if (concurrent)
            {
                return CreateConcurrent(size, defaultValue, diagonal);
            }
            else
            {
                return Create(size, defaultValue, diagonal);
            }
        }

        public static CoordinatesKeyedSparseMatrix<T> Create<T>(
            (int rows, int columns) size, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            return new CoordinatesKeyedSparseMatrix<T>(size, defaultValue, diagonal);
        }

        public static CoordinatesKeyedConcurrentSparseMatrix<T> CreateConcurrent<T>(
            (int rows, int columns) size, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            return new CoordinatesKeyedConcurrentSparseMatrix<T>(size, 
                defaultValue, diagonal);
        }

        public static IDOKSparseMatrix<int, T> Create<T>(
            (int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode, bool concurrent, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            if (concurrent)
            {
                return CreateConcurrent(size, linearIndexMode, defaultValue, diagonal);
            }
            else
            {
                return Create(size, linearIndexMode, defaultValue, diagonal);
            }
        }

        public static LinearIndexKeyedSparseMatrix<T> Create<T>(
            (int rows, int columns) size, MatrixLinearIndexMode linearIndexMode, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            return new LinearIndexKeyedSparseMatrix<T>(size, linearIndexMode, 
                defaultValue, diagonal);
        }

        public static LinearIndexKeyedConcurrentSparseMatrix<T> CreateConcurrent<T>(
            (int rows, int columns) size, 
            MatrixLinearIndexMode linearIndexMode, 
            T defaultValue = default(T), T diagonal = default(T))
        {
            return new LinearIndexKeyedConcurrentSparseMatrix<T>(size, linearIndexMode, 
                defaultValue, diagonal);
        }
    }
}

Comments