矩阵压缩格式转换:COO转换CSC(C++)

news/2024/10/30 13:12:29/

目录

一、基本理论

1.1 COO格式

1.2 CSR格式

1.3 CSC格式

二、代码实现

三、测试


一、基本理论

        稀疏矩阵(Sparse Matrix)是大部分元素为零的矩阵,与之相对应的是稠密矩阵(Dense Matrix)。科学领域、工程计算、图形处理、机器学习等领域的大多数数据以稀疏矩阵的形式呈现。由于稀疏矩阵中含有大量的零元素,在矩阵计算过程中许多元素的迭代计算属于无效运算,为了减少不必要的运算,需要对稀疏矩阵进行处理,减少CPU和内存的无效消耗。最为有效、使用最广的方法是矩阵压缩,即稀疏矩阵存储时仅存储非0的数值以节约内存,计算时仅计算非0的部分以减少CPU消耗。

        常见的稀疏矩阵存储格式有:COO、CSR、CSC。

        以4x5的稀疏矩阵A为例:

A=\begin{bmatrix} 1 & 4 & 0 & 0 & 0\\ 0& 2 & 3 & 0 & 0\\ 5& 0 & 0 & 7 & 8\\ 0& 0 & 9 & 0 & 6 \end{bmatrix}

1.1 COO格式

        COO格式最为简单,与二维直角坐标系中某个点g=f(x,y)的表示形式相似,由行索引矩阵列索引矩阵非零数值矩阵组成,矩阵A对应的COO格式为:

COO\left\{\begin{matrix} data=[1\;\;4\;\;2\;\;3\;\;5\;\;7\;\;8\;\;9\;\;6]\\ row=[0\;\;0\;\;1\;\;1\;\;2\;\;2\;\;2\;\;3\;\;3]\\ col=[0\;\;1\;\;1\;\;2\;\;0\;\;3\;\;4\;\;2\;\;4] \end{matrix}\right.

1.2 CSR格式

        CSR(Compressed Sparse Row)格式由行指针矩阵列索引矩阵非零数值矩阵组成,矩阵A对应的CSR格式为:

CSR\left\{\begin{matrix} data=[1\;\;4\;\;2\;\;3\;\;5\;\;7\;\;8\;\;9\;\;6]\\ ptr=[0\;\;2\;\;4\;\;7\;\;9]\\ col=[0\;\;1\;\;1\;\;2\;\;0\;\;3\;\;4\;\;2\;\;4] \end{matrix}\right.

具体含义:非零数值矩阵和COO格式中的一致。假设有m行,行指针矩阵有m+1个元素,行指针矩阵中前m个元素为每一行的第一个非零数在数据矩阵中的角标,

        第一行的第一个非零元素为1,在数据矩阵中为第0个元素;

        第二行的第一个非零元素为2,在数据矩阵中为第2个元素;

        第三行的第一个非零元素为5,在数据矩阵中为第4个元素;

        第四行的第一个非零元素为9,在数据矩阵中为第7个元素。

在行指针矩阵中,最后一个元素的值统一为整个矩阵中非零元素的总值,即为m。

1.3 CSC格式

        CSC(Compressed Sparse Column)格式与CSR格式类似,只是CSC是列压缩,CSR为行压缩,由行索引矩阵列指针矩阵非零数值矩阵组成,矩阵A对应的CSC格式为:

CSC\left\{\begin{matrix} data=[1\;\;5\;\;4\;\;2\;\;3\;\;9\;\;7\;\;8\;\;6]\\row=[0\;\;2\;\;0\;\;1\;\;1\;\;3\;\;2\;\;2\;\;3] \\ ptr=[0\;\;2\;\;4\;\;6\;\;7\;\;9]\end{matrix}\right.

具体含义:非零数值矩阵和COO格式中的一致。假设有n列,列指针矩阵有n+1个元素,列指针矩阵中前n个元素为每一列的第一个非零数在数据矩阵中的角标,

        第一列的第一个非零元素为1,在数据矩阵中为第0个元素;

        第二列的第一个非零元素为4,在数据矩阵中为第2个元素;

        第三列的第一个非零元素为3,在数据矩阵中为第4个元素;

        第四列的第一个非零元素为7,在数据矩阵中为第6个元素;

        第五列的第一个非零元素为8,在数据矩阵中为第7个元素。

在行指针矩阵中,最后一个元素的值统一为整个矩阵中非零元素的总值,即为n。

二、代码实现

#include <stdlib.h>
#include <stdio.h>#pragma warning(disable:4996)int main(int argc, char *argv[])
{FILE *fp_a;FILE *fp_b;const char *filename1, *filename2, *filename3, *filename4;int i;int row_num, col_num, data_num, b_row_num, b_col_num;int *row, *col, *row1, *col1;double *data, *data1, *b;double e;//1//从原始稀疏矩阵数据文件中读取数据fp_b = fopen("Y_out_coo.txt", "r");if(fp_b == NULL){printf("Cannot open file a.\n");exit(0);}//从原始稀疏矩阵数据文件中读取矩阵的行数,列数,非零数目fscanf(fp_b, "%d %d %d", &row_num, &col_num, &data_num);printf("%d %d %d\n\n", row_num, col_num, data_num);//为读取矩阵市场的系数矩阵的行数组(row),列数组(col),数据数组开辟空间(data)row = (int*)malloc(sizeof(int)*data_num);col = (int*)malloc(sizeof(int)*data_num);data = (double*)malloc(sizeof(double)*data_num);//为稀疏矩阵csr格式的行数组(row1),列数组(col1),数据数组开辟空间(data1)row1 = (int*)malloc(sizeof(int)*data_num);col1 = (int*)malloc(sizeof(int)*(col_num+1));data1 = (double*)malloc(sizeof(double)*data_num);//从原始稀疏矩阵数据文件中读取矩阵全部的行元素,列元素,非零元数据//原始稀疏矩阵数据文件中存储的非零元素的行坐标,列坐标均从1开始for(i = 0; i < data_num; i++){fscanf(fp_b, "%d %d %lf", &row[i], &col[i], &data[i]);printf("%d %d %lf\n", row[i], col[i], data[i]);}fclose(fp_b);printf("稀疏矩阵coo格式读入完毕!\n");//输入Ax=b中b数据//从原始稀疏矩阵数据文件中读取数据fp_b = fopen("b_out_coo.txt", "r");if(fp_b == NULL){printf("Cannot open file b_out_coo\n");exit(0);}//从原始稀疏矩阵数据文件中读取矩阵的行数,列数,非零元数目fscanf(fp_b, "%d %d", &b_row_num, &b_col_num);printf("%d %d\n", b_row_num, b_col_num);//创建b数组输入b = (double*)malloc(sizeof(double)*b_row_num);for(i = 0; i < b_row_num; i++){fscanf(fp_b, "lf", &b[i]);}fclose(fp_b);printf("Ab数据读入完毕!\n");//2//矩阵coo格式转化为csc格式int j, k, count;count = 0;k = 0;for(i = 0; i <= col_num; i++)  //初始化csc格式的列数组{col1[i] = 0;}for(i = 0; i < data_num; i++)  //记录每列的数据数目{col1[col[i]]++;}for(i = 1; i <= col_num; i++)  //计算csc格式的列信息的数组,这里命名为row1{i = col1[col[j]-1]++;row1[i] = row[j] - 1;data1[i] = data[j];printf("%lf\n", data[j]);}printf("First step: csc col info has been done! \n");/**********输出文件名***********/filename1 = "Y_out_CSC_Ap.txt";filename2 = "Y_out_CSC_Ai.txt";filename3 = "Y_out_CSC_Ax.txt";filename4 = "Y_out_CSC_Ab.txt";if((fp_b = fopen(filename1, "w")) == NULL){printf("Cannot open file write!\n");exit(0);}for(i = 0; i < col_num; i++){fprintf(fp_b, "%d", col1[i]);fprintf(fp_b, ", ");}fclose(fp_b);if((fp_b = fopen(filename2, "w")) == NULL){fprintf(fp_b, "%d", row1[i]);fprintf(fp_b, ", ");}fclose(fp_b);if((fp_b = fopen(filename3, "w")) == NULL){printf("Cannot open file write\n");exit(0);}for(i = 0; i < data_num; i++){fprintf(fp_b, "%lf", data1[i]);fprintf(fp_b, ", ");}fclose(fp_b);if((fp_b = fopen(filename4, "w")) == NULL){printf("Cannot open file write\n");exit(0);}for(i = 0; i < b_row_num; i++){fprintf(fp_b, "%.10lf", b[i]);fprintf(fp_b, ", ");}fclose(fp_b);printf("Coo has been transformed to CSC!\n");//释放申请的数组空间free(row);free(col);free(data);free(row1);free(col1);free(data1);free(b);return 0;
}

三、测试

        这里以219x219的稀疏矩阵为测试对象,其中非零数值共699个,输入文件为COO格式。

编译:

运行结果:

其中,

①Y_out_CSC_Ap.txt

②Y_out_CSC_Ai.txt

③Y_out_CSC_Ax.txt

④Y_out_CSC_Ab.txt

        感谢大佬来访,向各位大佬学习!


http://www.ppmy.cn/news/1543108.html

相关文章

2024年10月29日Github流行趋势

项目名称&#xff1a;Amphion 项目维护者&#xff1a;lmxue HeCheng0625 yuantuo666 RMSnow HarryHe11 项目介绍&#xff1a;Amphion是一个用于音频、音乐和语音生成的工具包。它旨在支持可重复的研究&#xff0c;并帮助初学者在音频、音乐和语音生成研究与开发领域起步。 项目…

React-query vs. 神秘新工具:前端开发的新较量

流畅的分页体验&#xff1a;AlovaJS的分页请求策略 在现代web应用中&#xff0c;分页是一个常见的功能需求。无论是浏览商品列表、查看文章集合&#xff0c;还是管理后台的数据表格&#xff0c;用户都需要一种高效且流畅的方式来浏览大量数据。然而&#xff0c;实现一个流畅且…

点云处理中的多项式重构、平滑与法线估计

在三维点云数据处理中&#xff0c;为了使数据更接近真实物体的形状并减少噪声&#xff0c;常用一些重建和优化的技术&#xff0c;如多项式重构、平滑处理和法线估计。点云数据作为物体表面的离散表示&#xff0c;通常会因采集设备或环境的干扰带有噪声和不规则性。通过这些方法…

水经微图IOS版5.6.0发布,新增照片轨迹生成功能

随时随地&#xff0c;微图一下&#xff01; 水经微图&#xff08;以下称“微图”&#xff09;IOS版5.6.0发布&#xff0c;本次升级主要新增了照片附件的添加查看功能&#xff0c;以及上线吉林一号2023版本全国一张图。 当前版本 当前版本号为&#xff1a;5.6.0 如果你发现该…

【优先算法】双指针

✨✨欢迎大家来到Celia的博客✨✨ &#x1f389;&#x1f389;创作不易&#xff0c;请点赞关注&#xff0c;多多支持哦&#x1f389;&#x1f389; 所属专栏&#xff1a;优先算法 个人主页&#xff1a;Celias blog~ 目录 ​​​​​​移动零 复写零 快乐数 盛水最多的容器 …

驱动和芯片设计哪个难

驱动和芯片设计哪个难 芯片设计和驱动开发 芯片设计和驱动开发 都是具有挑战性的工作&#xff0c;它们各自有不同的难点和要求。 对于芯片设计&#xff0c;它是一个集高精尖于一体的复杂系统工程&#xff0c;涉及到从需求分析、前端设计、后端设计到流片的全过程。 芯片设计的…

Mask RCNN原理详解(个人学习笔记)

目录 mask RCNN1. Background2. ROIAlign3. Network Architecture4. class-specific mask mask RCNN 首先从introduction看起&#xff0c;mask RCNN是在Faster R-CNN的基础上添加了一个额外的分割分支&#xff08;该分支和Faster RCNN的分类分支及回归分支并行运行&#xff09…

nrm的使用

在安装nrm之前&#xff0c;要先完成node.js的安装。 1、nrm的介绍 ‌nrm&#xff08;npm registry manager&#xff09;是一个npm源管理器&#xff0c;允许用户在不同npm源之间快速切换。 关于npm和nvm的介绍&#xff0c;详见文章nvm的使用-CSDN博客。 解释&#xff1a;比如…