Data structure (C language) - fast multiplication of sparse matrix

Posted by Allen4172 on Tue, 21 Jan 2020 17:49:48 +0100

Refer to data structure (C Language Edition) - Yan Weimin, WU Weimin, Tsinghua University Press

Structure definition of sparse matrix

typedef struct 
{
	int   i, j;       //Row and column subscripts of the non-zero element
	ElemType e;       //Value corresponding to non-zero element
}Triple;

typedef struct 
{
	Triple   data[MAX_SIZE];        //Nonzero element triple table
	int      rpos[MAX_RC];			//Position table of the first non-zero element in each row
	int      mu, nu, tu;            //Number of rows, columns and non-zero elements of matrix
}RTSMatrix;

Sparse matrix initialization

void Init_Matrix(RTSMatrix &M, int i)
{
	int x, y, z;
	int M_row = 0; int M_col = 0;
	M.tu = 0;
	printf("Please press row.,column,Form input of data-1 End input at\n");
	for (int i = 0; ; i++)
	{
		scanf_s("%d,%d,%d", &x, &y, &z);
		if (x == -1 || y == -1)
			break;
		M.data[i].i = x; M.data[i].j = y; M.data[i].e = z;
		M.tu++;
		if (M_row < x)
			M_row = x;
		if (M_col < y)
			M_col = y;
	}
	M.mu = M_row;
	M.nu = M_col;
	printf("\n The first%d A matrix is\n", i);
	Show_Matrix_1(M);
}

Calculate the position of the first non-zero element in each line

void  non_zero_elements(RTSMatrix &M)
{
	int num[100];								//num [] save the number of non-zero elements in each line cpot [] save the starting address of each line
	for (int i = 0; i < M.mu; i++)
		num[i] = 0;								//Initialize num
	for (int j = 0; j < M.tu; j++)
		num[M.data[j].i - 1]++;					//Count the number of non-zero elements in each row, because the matrix starts from the first row, and the data array starts from 0, so - 1
	M.rpos[0] = 0;                              //The starting point is 0.
	for (int k = 1; k < M.mu; k++)
		M.rpos[k] = M.rpos[k - 1] + num[k - 1];
}

Fast multiplication

void FastMultSMatrix(RTSMatrix A, RTSMatrix B, RTSMatrix &C)
{
	if (A.nu != B.mu)                                    //The number of columns in the front matrix should be equal to the number of rows in the back matrix
		return;
	C.mu = A.mu;                                         //The number of rows of the result matrix is the number of rows of the previous matrix
	C.nu = B.nu;										//The number of columns of the result matrix is the number of columns of the post matrix
	C.tu = 0;											//Result matrix initialization
	int ctemp[MAX_SIZE];								//accumulator
	int arow, brow, t, tp, ccol;
	non_zero_elements(A);								//Calculate the position of the first non-zero element in each row
	non_zero_elements(B);
	if (A.tu * B.tu != 0)
	{													//Multiplication matrix is not 0
		for (arow = 0; arow < A.mu; arow++)
		{												//From the first line to the last
			for (int i = 0; i <= A.nu; i++)
				ctemp[i] = 0;							//Accumulator clear 0
			C.rpos[arow] = C.tu;						//The first non-zero position is 0
			if (arow < A.mu - 1)						//Get the non 0 element number of A
				tp = A.rpos[arow + 1];
			else
				tp = A.tu;
			for (int j = A.rpos[arow]; j < tp; j++) 
			{														//For each non-zero number in A's row, take its column index and multiply it with each number in B's row
				brow = A.data[j].j;									//Take column index
				if (brow < B.mu)									//Take the non-zero number of column marked row of B
					t = B.rpos[brow];
				else
					t = B.tu;
				for (int k = B.rpos[brow - 1]; k < t; k++) 
				{													//Each non-zero element of the column standard row of B
					ccol = B.data[k].j;
					ctemp[ccol] += A.data[j].e * B.data[k].e;
				}
			}
			for (ccol = 1; ccol <= C.nu; ccol++)					//Copy the results of the accumulator to the result array in order
				if (ctemp[ccol]) 
				{
					C.tu++;
					if (C.tu > MAX_SIZE)
						return;
					C.data[C.tu - 1].i = arow + 1;
					C.data[C.tu - 1].j = ccol;
					C.data[C.tu - 1].e = ctemp[ccol];
				}
		}
	}
	printf("The result is\n");
	Show_Matrix_1(C);
}

Output sparse matrix in matrix form

void Show_Matrix_1(RTSMatrix T) {
	int data[100] = { 0 };
	for (int i = 0; i < T.tu; i++)		//Store non-0 yuan in the specified location, and the rest are 0
		data[(T.data[i].i - 1) * T.nu + T.data[i].j - 1] = T.data[i].e;

	for (int j = 0; j < T.mu * T.nu; j++) {
		printf("%5d", data[j]);
		if ((j + 1) % T.nu == 0)
			printf("\n");
	}
	printf("\n");
}

Output sparse matrix in the form of three tuples

void Show_Matrix_2(RTSMatrix T)
{
	printf("\n Three yuan table for\n");
	for (int t = 0; t < T.tu; t++)
		printf("%4d %4d %4d\n", T.data[t].i, T.data[t].j, T.data[t].e);
	printf("\n");
}

Test set

Matrix A:1 2 0
      0 2 0
      0 0 3
 Matrix B:1 0 0
      2 2 0
      0 0 3

Whole code

#include<stdio.h>
#include<stdlib.h>

#define MAX_SIZE 1000
#define MAX_RC 1000
#define ElemType int

typedef struct 
{
	int   i, j;       //Row and column subscripts of the non-zero element
	ElemType e;       //Value corresponding to non-zero element
}Triple;

typedef struct 
{
	Triple   data[MAX_SIZE];        //Nonzero element triple table
	int      rpos[MAX_RC];			//Position table of the first non-zero element in each row
	int      mu, nu, tu;            //Number of rows, columns and non-zero elements of matrix
}RTSMatrix;

void Show_Matrix_1(RTSMatrix T) {
	int data[100] = { 0 };
	for (int i = 0; i < T.tu; i++)
		data[(T.data[i].i - 1) * T.nu + T.data[i].j - 1] = T.data[i].e;

	for (int j = 0; j < T.mu * T.nu; j++) {
		printf("%5d", data[j]);
		if ((j + 1) % T.nu == 0)
			printf("\n");
	}
	printf("\n");
}

void Show_Matrix_2(RTSMatrix T)
{
	printf("\n Three yuan table for\n");
	for (int t = 0; t < T.tu; t++)
		printf("%4d %4d %4d\n", T.data[t].i, T.data[t].j, T.data[t].e);
	printf("\n");
}

void Init_Matrix(RTSMatrix &M, int i)
{
	int x, y, z;
	int M_row = 0; int M_col = 0;
	M.tu = 0;
	printf("Please press row.,column,Form input of data-1 Time end input\n");
	for (int i = 0; ; i++)
	{
		scanf_s("%d,%d,%d", &x, &y, &z);
		if (x == -1 || y == -1)
			break;
		M.data[i].i = x; M.data[i].j = y; M.data[i].e = z;
		M.tu++;
		if (M_row < x)
			M_row = x;
		if (M_col < y)
			M_col = y;
	}
	M.mu = M_row;
	M.nu = M_col;
	printf("\n The first%d A matrix is\n", i);
	Show_Matrix_1(M);
}

void  non_zero_elements(RTSMatrix &M)
{
	int num[100];								//num [] save the number of non-zero elements in each line cpot [] save the starting address of each line
	for (int i = 0; i < M.mu; i++)
		num[i] = 0;								//Initialize num
	for (int j = 0; j < M.tu; j++)
		num[M.data[j].i - 1]++;					//Count the number of non-zero elements in each row, because the matrix starts from the first row, and the data array starts from 0, so - 1
	M.rpos[0] = 0;                              //The starting point is 0.
	for (int k = 1; k < M.mu; k++)
		M.rpos[k] = M.rpos[k - 1] + num[k - 1];
}

void FastMultSMatrix(RTSMatrix A, RTSMatrix B, RTSMatrix &C)
{
	if (A.nu != B.mu)                                    //The number of columns in the front matrix should be equal to the number of rows in the back matrix
		return;
	C.mu = A.mu;                                         //The number of rows of the result matrix is the number of rows of the previous matrix
	C.nu = B.nu;										//The number of columns of the result matrix is the number of columns of the post matrix
	C.tu = 0;											//Result matrix initialization
	int ctemp[MAX_SIZE];								//accumulator
	int arow, brow, t, tp, ccol;
	non_zero_elements(A);								//Calculate the position of the first non-zero element in each row
	non_zero_elements(B);
	if (A.tu * B.tu != 0)
	{													//Multiplication matrix is not 0
		for (arow = 0; arow < A.mu; arow++)
		{												//From the first line to the last
			for (int i = 0; i <= A.nu; i++)
				ctemp[i] = 0;							//Accumulator clear 0
			C.rpos[arow] = C.tu;						//The first non-zero position is 0
			if (arow < A.mu - 1)						//Get the non-zero element of A
				tp = A.rpos[arow + 1];
			else
				tp = A.tu;
			for (int j = A.rpos[arow]; j < tp; j++) 
			{														//For each non-zero number in A's row, take its column index and multiply it with each number in B's row
				brow = A.data[j].j;									//Take column index
				if (brow < B.mu)									//Take the non-zero number of column marked row of B
					t = B.rpos[brow];
				else
					t = B.tu;
				for (int k = B.rpos[brow - 1]; k < t; k++) 
				{													//Each non-zero element of the column standard row of B
					ccol = B.data[k].j;
					ctemp[ccol] += A.data[j].e * B.data[k].e;
				}
			}
			for (ccol = 1; ccol <= C.nu; ccol++)					//Copy the results of the accumulator to the result array in order
				if (ctemp[ccol]) 
				{
					C.tu++;
					if (C.tu > MAX_SIZE)
						return;
					C.data[C.tu - 1].i = arow + 1;
					C.data[C.tu - 1].j = ccol;
					C.data[C.tu - 1].e = ctemp[ccol];
				}
		}
	}
	printf("The result is\n");
	Show_Matrix_1(C);
}

void main() {
	RTSMatrix A;
	RTSMatrix B;
	RTSMatrix C;
	Init_Matrix(A, 1);
	Init_Matrix(B, 2);
	FastMultSMatrix(A, B, C);
	system("pause");
}

Result

Published 8 original articles, praised 0, visited 86
Private letter follow

Topics: REST C