Sparse - Seidel and Laplacian Adjacency Matrix

With the AdjacencyMatrixBase in place, variations of the adjacency matrix can be easily implemented.

If you've been following along since I started the matrix series, you should see that Mendz.Graphs has similar coding patterns to implement the different graph matrices.

SeidelAdjacencyMatrix

The (-1, 1, 0)-adjacency matrix illustrates the power of overriding Fill() to point to a private static SetEntries() method.

SeidelAdjacencyMatrix.cs
using System;
using System.Collections.Concurrent;

namespace Mendz.Graphs.Representations.Matrices.Sparse
{
    public class SeidelAdjacencyMatrix : AdjacencyMatrixBase<int>
    {
        public SeidelAdjacencyMatrix(Graph graph) 
            : base(graph, (z, edge) => -1, 1)
        {

        }

        public override ConcurrentDictionary<(int row, int column), int> Fill()
        {
            return Fill((matrix, x, y, value, directed) => 
                SetEntries(matrix, x, y, value, directed));
        }

        private static void SetEntries(
            ConcurrentDictionary<(int row, int column), int> matrix, 
            int x, int y, int value, bool directed)
        {
            if (x == y)
            {
                throw new InvalidOperationException("Loops are not supported.");
            }
            if (directed)
            {
                throw new InvalidOperationException("Directed edges are not supported.");
            }
            matrix.TryAdd((x, y), value);
            matrix.TryAdd((y, x), value);
        }
    }
}

Looks familiar? ;-)

LaplacianMatrix

In the same way, the Laplacian matrix, which is implemented in Mendz.Graphs as a (-1, 0, d)-adjacency matrix, shows how the overridden Fill() and private static SetEntries() work.

LaplacianMatrix.cs
using System;
using System.Collections.Concurrent;

namespace Mendz.Graphs.Representations.Matrices.Sparse
{
    public class LaplacianMatrix : AdjacencyMatrixBase<int>
    {
        public LaplacianMatrix(Graph graph)
            : base(graph, (z, edge) => -1)
        {
            
        }

        public override ConcurrentDictionary<(int row, int column), int> Fill()
        {
            return Fill((matrix, x, y, value, directed) => 
                SetEntries(matrix, x, y, value, directed));
        }

        private static void SetEntries(
            ConcurrentDictionary<(int row, int column), int> matrix, 
            int x, int y, int value, bool directed)
        {
            if (x == y)
            {
                throw new InvalidOperationException("Loops are not supported.");
            }
            if (directed)
            {
                throw new InvalidOperationException("Directed edges are not supported.");
            }
            matrix.AddOrUpdate((x, x), 1, (k, v) => v + 1);
            matrix.AddOrUpdate((y, y), 1, (k, v) => v + 1);
            matrix.TryAdd((x, y), value);
            matrix.TryAdd((y, x), value);
        }
    }
}

Reminds you of something? ;-)

Comments