稀疏矩阵乘法的运算
scipy稀疏矩阵按行乘
scipy稀疏矩阵按行乘
稀疏矩阵按行乘是指使用Scipy库中的稀疏矩阵功能进行矩阵乘法运算时按行
进行操作。
在实际应用中,稀疏矩阵往往是非常大的矩阵,因此对于大规模稀疏矩阵的操作效率是非常重要的。
Scipy库提供了一系列的函数和方法来处理稀疏矩阵,其中包括按行乘法操作。
在Scipy库中,稀疏矩阵主要有三种类型:COO格式、CSR格式和CSC格式。
这些格式都有各自的优势和适用场景。
在进行稀疏矩阵按行乘的操作时,通常会选择CSR格式的稀疏矩阵,因为CSR格式在按行进行乘法操作时效率更高。
稀疏矩阵按行乘的操作可以通过矩阵乘法运算来实现。
对于两个稀疏矩阵A和B,可以使用稀疏矩阵乘法的方式来实现按行乘的操作。
具体步骤如下:
1. 将稀疏矩阵A和B转换为CSR格式。
2. 遍历稀疏矩阵A的每一行,将该行乘以稀疏矩阵B的对应列,得到乘积矩
阵的对应行。
3. 将乘积矩阵的对应行存储起来,最终得到稀疏矩阵按行乘的结果。
在实际应用中,稀疏矩阵按行乘的操作可以用于矩阵乘法运算、矩阵向量乘法
等问题的求解。
通过Scipy库提供的稀疏矩阵功能,可以高效地处理大规模稀疏矩
阵的按行乘操作,提高计算效率和节约存储空间。
总的来说,稀疏矩阵按行乘是一种重要的矩阵操作,通过Scipy库提供的稀疏
矩阵功能,可以方便高效地实现这种操作,应用于各种科学计算和工程问题的求解中。
Scipy的稀疏矩阵功能在处理稀疏矩阵的矩阵乘法等操作中具有很大的优势,
是矩阵运算的重要工具之一。
稀疏矩阵乘法 并行
稀疏矩阵乘法并行全文共四篇示例,供读者参考第一篇示例:稀疏矩阵乘法是一种重要的数值计算问题,它在很多领域都有着广泛的应用,比如图像处理、机器学习等。
由于稀疏矩阵的特性是大部分元素都是0,只有少量非零元素,所以传统的矩阵乘法算法在处理稀疏矩阵时会浪费大量的计算资源。
为了解决这个问题,人们提出了一种并行计算的方法,即利用多个处理器同时计算矩阵乘法,从而提高计算效率。
在并行计算中,稀疏矩阵乘法也有着自己的特点和挑战。
稀疏矩阵的非零元素分布在整个矩阵中,处理起来比较困难。
矩阵乘法的计算量随着非零元素的增加而增加,所以需要合理地分配计算资源和任务。
稀疏矩阵乘法的并行计算需要考虑通信开销和负载均衡,以充分利用多个处理器的计算能力。
为了解决上述问题,人们提出了一些并行的稀疏矩阵乘法算法。
其中比较有代表性的是基于CSR(Compressed Sparse Row)格式的算法。
CSR格式是一种压缩存储稀疏矩阵的方法,它将矩阵分成三部分:非零元素数组、列索引数组和行偏移数组。
基于CSR格式的算法在并行计算中能够有效地减少通信开销,提高计算效率。
还有一些其他的并行稀疏矩阵乘法算法,比如基于COO (Coordinate)格式、基于Ecoo(Ellpack-Chebyshev)格式等。
这些算法都有着自己的特点和适用场景,可以根据具体的问题选择合适的算法。
在并行计算中,负载均衡是一个非常重要的问题。
负载不均衡会导致一些处理器的计算资源被浪费,影响整体的计算效率。
为了解决负载均衡问题,人们提出了一些方法,比如动态任务分配、静态任务划分、自适应任务调度等。
这些方法能够根据任务的计算量和数据分布特点,合理地分配任务,从而提高计算效率。
除了负载均衡,通信开销也是一个需要考虑的重要问题。
在并行计算中,处理器之间需要进行通信,传递计算结果和数据,这会导致一定的开销。
为了减小通信开销,人们提出了一些方法,比如数据压缩、异步通信、消息合并等。
基于mpi实现稀疏矩阵的乘法
基于MPI实现稀疏矩阵的乘法1. 引言稀疏矩阵是指大部分元素为零的矩阵,与之相对应的是稠密矩阵,其中大部分元素非零。
由于稀疏矩阵中有大量的零元素,传统的矩阵乘法算法在计算稀疏矩阵乘法时效率较低。
为了提高计算效率,我们可以利用并行计算的思想,使用MPI (Message Passing Interface)来实现稀疏矩阵的乘法。
MPI是一种用于编写并行程序的标准通信库,它定义了一组函数和语义,用于在多个进程之间进行通信和同步操作。
通过将任务划分为多个进程,每个进程负责处理一部分数据,并通过消息传递进行通信和协调,可以实现并行计算。
本文将介绍如何使用MPI实现稀疏矩阵的乘法算法。
首先我们会介绍稀疏矩阵的表示方法和存储格式,然后详细说明基于MPI的稀疏矩阵乘法算法的实现过程。
2. 稀疏矩阵的表示和存储格式稀疏矩阵有多种表示方法,常用的有三元组表示法、行压缩存储(CSR)和列压缩存储(CSC)。
三元组表示法将稀疏矩阵中非零元素的行、列和值分别存储在三个数组中。
这种表示方法简单直观,但对于大型稀疏矩阵来说,空间效率较低。
行压缩存储(CSR)是一种常用的稀疏矩阵存储格式。
在CSR格式中,我们将稀疏矩阵拆分为三个数组:值数组(values)、列指针数组(col_indices)和行偏移量数组(row_offsets)。
其中,值数组存储非零元素的值,列指针数组存储非零元素所在的列索引,行偏移量数组记录每一行第一个非零元素在值数组和列指针数组中的索引。
通过这种方式,我们可以快速访问稀疏矩阵中的非零元素。
列压缩存储(CSC)与CSR类似,只是将列指针数组变为行指针数组,将行偏移量数组变为列偏移量数组。
CSC格式适合于按列访问稀疏矩阵。
在本文中,我们将使用CSR格式来表示稀疏矩阵,并基于该格式实现稀疏矩阵的乘法算法。
3. 基于MPI的稀疏矩阵乘法算法基于MPI的稀疏矩阵乘法算法可以分为以下几个步骤:1.初始化MPI环境:在开始进行并行计算之前,需要初始化MPI环境,获取进程数量和进程编号等信息。
?LeetCode刷题实战311:稀疏矩阵的乘法
LeetCode刷题实战311:稀疏矩阵的乘法算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。
所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选!今天和大家聊的问题叫做稀疏矩阵的乘法,我们先来看题面:/problems/sparse-matrix-multiplication/Given two sparse matrices A and B, return the result of AB.You may assume that A's column number is equal to B's row number.给你两个稀疏矩阵 A 和 B,请你返回 AB 的结果。
你可以默认 A 的列数等于 B 的行数。
示例解题由于是稀疏数组可以只计算非零数字。
将A矩阵转存为hashmap,然后对每一个非零数遍历B的列数来更新它在ans矩阵里可以被用到的位置。
class Solution {public:vector<vector<int>> multiply(vector<vector<int>>& A, vector<vector<int>>& B) {int n = A.size(), m = A[0].size(), k = B[0].size();vector<vector<int>> res(n, vector<int>(k, 0));unordered_map<int, int> am;for (int i = 0; i < n; i ++)for (int j = 0; j < m; j ++){if (!A[i][j]) continue;int idx = i * m + j;am[idx] = A[i][j];}for (auto aij : am){int va = aij.second, aidx = aij.first, ai = aidx / m, aj = aidx % m;for (int j = 0; j < k; j ++){res[ai][j] += va * B[aj][j];}}return res;}};好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力。
稀疏矩阵的运算
稀疏矩阵的运算稀疏矩阵的运算稀疏矩阵,顾名思义,就是矩阵中空值(0)的比例很大,而实际值(非0)的比例很小的矩阵。
它最大的特点就是,当矩阵的规模增大时,仍然可以保持较低的计算量。
在运算时,因为稀疏矩阵中的0值没有意义,所以对其做运算也没有意义。
所以,在运算中需要把稀疏矩阵转换成一维数组,即只保留其有意义的值。
下面介绍几种常用的稀疏矩阵运算技术。
1.索引表(Indextable)这是一种最简单的稀疏矩阵运算技术,在使用索引表时,需要用一个额外的一维数组来保存有意义的值的位置,而把矩阵本身变成一维数组,进行运算。
例如矩阵A:1 0 0 0 00 0 0 4 00 0 0 0 00 3 0 0 00 0 7 0 0这样的矩阵,可以使用一个一维数组来保存其有意义的值及其位置,例如:[1,(0,0); 4,(1,3); 3,(3,1); 7,(2,2)]这样,我们就可以用简单的一维数组代替复杂的二维矩阵,从而加快稀疏矩阵的运算。
2.矩阵向量乘法(Matrix-Vector Multiplication)这是一种最常用的稀疏矩阵运算技术,把一个大的稀疏矩阵A和一个向量(一维数组)V作乘法,得到一个新的向量C,即:C = A * V对于上面的实例,可以用以下方式求出C:C[0] = 1 * V[0] + 0 * V[1] + 0 * V[2] + 0 * V[3] + 0 * V[4] C[1] = 0 * V[0] + 0 * V[1] + 0 * V[2] + 4 * V[3] + 0 * V[4] C[2] = 0 * V[0] + 0 * V[1] + 0 * V[2] + 0 * V[3] + 7 * V[4] C[3] = 0 * V[0] + 3 * V[1] + 0 * V[2] + 0 * V[3] + 0 * V[4] 3.矩阵乘法(Matrix Multiplication)矩阵乘法也是一种常用的稀疏矩阵运算技术,把两个大的稀疏矩阵A和B相乘,得到一个新的稀疏矩阵C,即:C = A * B以上就是稀疏矩阵运算的一些常用技术,稀疏矩阵也可以用于解决很多复杂的运算问题,例如机器学习和深度学习等。
稀疏矩阵乘法
稀疏矩阵乘法给定两个 A 和 B,返回AB的结果。
您可以假设A的列数等于B的⾏数。
本参考程序来⾃九章算法,由 @Roger 提供。
题⽬解法:时间复杂度分析:假设矩阵A,B均为 n x n 的矩阵,矩阵A的稀疏系数为a,矩阵B的稀疏系数为b,a,b∈[0, 1],矩阵越稀疏,系数越⼩。
⽅法⼀:暴⼒,不考虑稀疏性Time (n^2 * (1 + n)) = O(n^2 + n^3)Space O(1)⽅法⼆:改进,仅考虑A的稀疏性Time O(n^2 * (1 + a * n) = O(n^2 + a * n^3)Space O(1)⽅法三(最优):进⼀步改进,考虑A与B的稀疏性Time O(n^2 * (1 + a * b * n)) = O(n^2 + a * b * n^3)Space O(b * n^2)⽅法四:另外⼀种思路,将矩阵A, B⾮0元素的坐标抽出,对⾮0元素进⾏运算和结果累加Time O(2 * n^2 + a * b * n^4) = O(n^2 + a * b * n^4)Space O(a * n^2 + b * n^2)解读:矩阵乘法的两种形式,假设 A(n, t) * B(t, m) = C(n, m)// 形式⼀:外层两个循环遍历C (常规解法)for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {for (int k = 0; k < t; k++) {C[i][j] += A[i][k] * B[k][j];}}}// 或者写成下⾯这样⼦for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int sum = 0;for (int k = 0; k < t; k++) {sum += A[i][k] * B[k][j];}C[i][j] = sum;}}// 形式⼆:外层两个循环遍历Afor (int i = 0; i < n; i++) {for (int k = 0; k < t; k++) {for (int j = 0; j < m; j++) {C[i][j] += A[i][k] * B[k][j];}}}两种⽅法的区别代码上的区别(表象):调换了第⼆三层循环的顺序核⼼区别(内在):形式⼀以C为核⼼进⾏遍历,每个C[i][j]只会被计算⼀次,就是最终答案。
拓展阅读3——稀疏矩阵的相乘
稀疏矩阵的相乘*两个矩阵相乘的经典算法是大家所熟悉的,设Q=M×N其中,M 是m 1×n 1矩阵,N 是m 2×n 2矩阵。
当n 1=m 2时有:for (i=1;i<=m1;++i )for(j=1;j<=n2;++j){Q[i][j]=0;for(k=1;k<=n1;++k)Q[i][j]+=M[i][k]×N[k][j];}此算法的时间复杂度是O(m 1×n 1×n 2)。
当矩阵变成稀疏矩阵,并且用三元组表作存储结构时,上面这个算法就不能用了,下面我们讨论稀疏矩阵三元组表的相乘算法。
已知稀疏矩阵A(m 1× n 1)和B(m 2× n 2),求乘积C(m 1× n 2)。
稀疏矩阵A 、B 、C 及它们对应的三元组表A.data 、B.data 、C.data 如图1所示。
A=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡000203008005 B=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡-01500720 C=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-40150108 115148233312ij v 114523712221-v j i 42315221021811-v j i 图1 稀疏矩阵相乘图例由矩阵乘法规则知:C (i ,j )=A(i,1)×B(1,j)+A(i,2)×B(2,j)+…+A(i,n)×B(n,j)=)11(),(),(2,11n j m i j k B k i A n k ≤≤≤≤⨯∑=矩阵用二维数组表示时,在经典算法中,不论A(i,k)与B(k,j)的值是否为零,都要进行一次乘法运算,而在三元组表示的稀疏矩阵相乘时,只需从A.data 和B.data 中找到A.data 中列值与B.data 中行值相等的各对元素相乘并将结果累加即可。
为此需要在B.data 中找到矩阵B 第k 行中所有非零元素,跟矩阵转置改进算法相同的原理,我们引入num 和rpot 两个向量。
稀疏矩阵乘法的时间复杂度
稀疏矩阵乘法的时间复杂度稀疏矩阵乘法的时间复杂度,这话一说出来,可能有些朋友会皱眉头,觉得这又是个高深的数学问题。
但实际上,咱们今天就来聊聊这个看似复杂的事情,轻松点、幽默点,让大家都能明白。
咱们得搞清楚什么是稀疏矩阵。
简单来说,就是矩阵里有很多的零。
想象一下,你在看一张桌子,上面摆着很多碗,只有几个碗里有东西,其他的都是空的。
这样的矩阵就叫稀疏矩阵。
其实在很多实际应用中,稀疏矩阵的出现是非常常见的,特别是在图像处理、机器学习和数据科学中,真是频繁得让人惊叹。
咱们就要说说稀疏矩阵乘法。
说白了,就是把两个稀疏矩阵相乘。
这个过程其实可以看作是把两个“空碗”组合成一个新碗,看看能不能得到一些“有料”的东西。
由于很多位置上都是零,所以在计算的时候,咱们可以聪明点,干脆不去计算那些零的位置,省得浪费时间和精力,简直就是把“事半功倍”发挥到了极致。
这一招可不是什么秘笈,很多程序员和数学家都用得特别溜。
不过,时间复杂度是个什么鬼呢?简单来说,它就是描述算法运行时间的一个指标。
想象一下,咱们去市场买菜,时间复杂度就像是你去菜市场的路程,如果你走的路特别绕,那肯定花的时间就长;如果你选了一条最近的路,当然就能更快到达。
对于稀疏矩阵乘法来说,时间复杂度跟矩阵的稀疏程度和大小有很大关系。
一般来说,如果你有一个稀疏矩阵A和B,那么它们相乘的复杂度大致是O(NzA + NzB),Nz代表非零元素的数量。
别被这些符号吓到,通俗点说,就是看你非零元素有多少,越多计算的时间就越长。
再说个形象的例子。
想象你在一个派对上,跟一群朋友聊得火热,结果你发现只有几个人是你特别想交流的。
如果你一个一个去找他们,肯定费时费力。
但是如果你能知道他们在哪,直接冲过去,效率简直翻倍。
稀疏矩阵乘法就像这样,只找非零的元素,省去那些冗余的时间,简直太聪明了。
再来聊聊实际应用。
稀疏矩阵在机器学习中可是大显身手。
比如在推荐系统里,用户和物品的评分矩阵常常都是稀疏的,绝大多数用户根本没给某些物品打过分。
基于mapreduce的稀疏矩阵乘法算法
基于mapreduce的稀疏矩阵乘法算法组长:吴建堃组员:白野朵宝宝目录一、课题研究目的二、稀疏矩阵介绍(一)稀疏矩阵乘法介绍(三元组) (2)(二) Mapreduce介绍 (4)(三)实验环境配置 (7)(四)创建代码(来自网络的代码) (10)(五)组员总结 (16)一、课题研究目的。
矩阵乘法运算是一种基本运算。
而扩大矩阵乘法的运算规模并降低其运算时间,将有利于满足机器学习算法处理大规模数据的要求。
将MapReduce并行框架用于分块矩阵乘法,实现一种用于大规模矩阵乘法运算的方法。
理论分析和实验结果表明该方法在处理大规模矩阵乘法上具有极大的潜能,并且随着计算节点的增加从而获得较好的加速比。
二、稀疏矩阵介绍。
人们无法给出稀疏矩阵的确切定义,一般都只是凭个人的直觉来理解这个概念,即矩阵中非零元素的个数远远小于矩阵元素的总数,并且非零元素没有分布规律。
对于那些零元素数目远远多于非零元素数目,并且非零元素的分布没有规律的矩阵称为稀疏矩阵(六)稀疏矩阵乘法介绍(三元组)当矩阵M、N是稀疏矩阵时,我们可以采用三元组表的表示形式来实现矩阵的乘。
采用三元组表的方法来实现时,因为三元组只对矩阵的非零元素做存储所以可以采用固定三元组表a中的元素(i,k,Mik)(1≤i≤m1,1≤k≤n1),在三元组表b中找所有行号为k的的对应元素(k,j, Nkj)(1≤k≤m2,1≤j≤n2)进行相乘、累加,从而得到Q[i][j],即以三元组表a中的元素为基准,依次求出其与三元组表b的有效乘积。
算法中附设两个向量num[]、first[],其中num[row]表示三元组表b中第row 行非零元素个数(1≤row≤m2), first[row]表示三元组表b中第row行第一个非零元素所在的位置。
显然,first[row+1]-1指向三元组表b中第row行最后一个非零元素的位置。
first[1]=1;first[row]=first[row-1]+num[row-1], 2≤row≤m2+1。
用三元组表示稀疏矩阵的乘法
该结点除了( row , col , value )以外,还要有以下两个链域:
right: down: 用于链接同一列中的下一个非零元素。
row Down
col
Value right
第十二讲
1 1 3
1 4 5
2 2 -1
3 1 3
图5.23 十字链表的结构
第十二讲
十字链表的结构类型说明如下:
typedef struct OLNode
第十二讲
用三元组表实现稀疏矩阵的乘法运算
第十二讲
两个矩阵相乘也是矩阵的一种常用的运算。设矩阵 M 是
m1×n1 矩阵, N 是 m2×n2 矩阵;若可以相乘,则必须满足矩
阵 M 的列数 n1 与矩阵 N 的行数 m2 相等,才能得到结果矩阵 Q=M×N(一个m1×n2的矩阵)。
数学中矩阵Q中的元素的计算方法如下:
矩阵不仅节约了空间,而且使得矩阵某些运算的运算时间比经
典算法还少。但是在进行矩阵加法、减法和乘法等运算时,有 时矩阵中的非零元素的位置和个数会发生很大的变化。如
A=A+B, 将矩阵B加到矩阵A上,此时若还用三元组表表示法,
势必会为了保持三元组表“以行序为主序”而大量移动元素。
第十二讲
在十字链表中,矩阵的每一个非零元素用一个结点表示,
0 1 N 2 0
2 0 4 0
0 Q 1 0
6 0 4
图5.17 Q=M×N
第十二讲
图5.18 矩阵M、N、Q的三元组表
第十二讲
经典算法中,不论 M [ i ][ k ]、 N [ k ][ j ]是否为零,
for(k=1; k<=n1; k++)
稀疏矩阵向量乘
稀疏矩阵向量乘1.引言1.1 概述稀疏矩阵向量乘是指针对稀疏矩阵和向量进行相乘的一种运算方法。
稀疏矩阵是指其中大部分元素都为0的矩阵,而向量是由一列数值组成的有序集合。
相比于密集矩阵和向量,稀疏矩阵和向量在存储和计算上具有更高的效率。
在现实生活和科学工程领域中,很多数据都呈现出稀疏的特性,比如文本分析中的词频矩阵、网络分析中的邻接矩阵等。
因此,稀疏矩阵向量乘的算法研究和优化具有重要的意义。
本文将首先对稀疏矩阵的定义与特点进行介绍,包括稀疏矩阵的存储方式和稀疏性的度量方法。
然后,我们将详细探讨稀疏矩阵向量乘的算法,包括传统的普通稀疏矩阵向量乘算法以及近年来涌现的一些优化算法。
通过对比实验和性能分析,我们将评估这些算法的优缺点,并探讨它们的适用场景。
在结论部分,我们将探讨稀疏矩阵向量乘的应用领域,包括机器学习、计算机图形学以及科学工程等领域。
同时,我们也将总结本文的主要内容,并展望未来在稀疏矩阵向量乘算法优化方面的研究方向。
通过本文的研究,读者将更深入地了解稀疏矩阵向量乘的算法和应用,并对如何选择合适的算法进行稀疏矩阵向量乘有一定的指导意义。
最终,我们希望本文能够为稀疏矩阵向量乘算法的研究和应用提供一些有益的参考。
1.2文章结构1.2 文章结构本文主要分为引言、正文和结论三个部分。
在引言部分,我们首先对本文的研究对象进行概述,即稀疏矩阵向量乘。
稀疏矩阵是一种特殊的矩阵,其大部分元素为0,只有少数非零元素。
稀疏矩阵向量乘是指将稀疏矩阵与向量相乘的操作。
接着,我们将介绍文章的结构,为读者提供一个整体的预览。
最后,我们说明本文的目的,即探讨稀疏矩阵向量乘的算法和应用。
在正文部分,我们将首先介绍稀疏矩阵的定义与特点。
我们将解释稀疏矩阵的特点,如大部分元素为0、稀疏矩阵的存储方式等。
然后,我们将详细介绍稀疏矩阵向量乘的算法。
我们将介绍常见的算法,如CSR格式、COO格式等,并对这些算法进行比较和分析,寻找最高效的方法。
稀疏矩阵乘法运算
稀疏矩阵的乘法运算程序代码:#include<iostream.h>#include<fstream.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define Ture 1#define Overflow -1typedef struct OLnode{int i,j;int e;struct OLnode *right,*down;}OLnode,*Olink;typedef struct{Olink *rhead,*chead;int mu,nu,tu;}Crosslist;//在十字链表M.rhead[row]中插入一个t结点void insert_row(Crosslist &M,OLnode *t,int row){OLnode *p;int col=t->j;if(M.rhead[row]==NULL||M.rhead[row]->j>col){t->right=M.rhead[row];M.rhead[row]=t;}else{for(p=M.rhead[row];p->right&&p->right->j<col;p=p->right);//寻找在行表中的插入位置t->right=p->right;p->right=t;}}//在十字链表M.chead[col]中插入一个结点tvoid insert_col(Crosslist &M,OLnode *t,int col){OLnode *p;int row=t->i;if(M.chead[col]==NULL||M.chead[col]->i>row){t->down=M.chead[col];M.chead[col]=t;}else{for(p=M.chead[col];p->down&&p->down->i<row;p=p->down);//寻找在列表中的插入位置t->down=p->down;p->down=t;}}//创建十字链表并存入数据void input(Crosslist &M){int m,n,t;cout<<"请输入矩阵的行和列的个数及非零元个数";cin>>m>>n>>t;if(t>m*n) exit(Overflow);M.mu=m;M.nu=n;M.tu=t;int row,col,e;OLnode *q;M.rhead=(Olink *)malloc((m+1)*sizeof(Olink));M.chead=(Olink *)malloc((n+1)*sizeof(Olink));if(!M.rhead) exit(Overflow);if(!M.chead) exit(Overflow);for(int i=0;i<=m+1;i++)M.rhead[i]=NULL;for(int j=0;j<=n;j++)M.chead[j]=NULL;cout<<"请输入矩阵"<<endl;int k=1;for(cin>>row>>col>>e;row!=0&&k<=t;cin>>row>>col>>e,k++) {q=(OLnode *) malloc(sizeof(OLnode));if(!t) exit(Overflow);q->e=e; //生成结点q->i=row;q->j=col;insert_row(M,q,row); //完成行插入insert_col(M,q,col); //完成列插入}}//矩阵M与矩阵N的乘法运算void chengfa(Crosslist M,Crosslist N,Crosslist &Q){if(M.nu!=N.mu) exit(Overflow);Q.mu=M.mu;Q.nu=N.nu;Q.tu=0;OLnode *p,*q,*t;Olink temp;int e,col;Q.rhead=(Olink *)malloc((Q.mu+1)*sizeof(Olink));Q.chead=(Olink *)malloc((Q.nu+1)*sizeof(Olink));if(!Q.rhead) exit(Overflow);if(!Q.chead) exit(Overflow);temp=(Olink)malloc((Q.nu+1)*sizeof(OLnode));for(int i=0;i<=Q.mu+1;i++)Q.rhead[i]=NULL;for(int j=0;j<=Q.nu;j++)Q.chead[j]=NULL;for(int row=1;row<=Q.mu;row++){for(int k=1;k<=Q.nu;k++)temp[k].e=0;for(p=M.rhead[row];p!=NULL;p=p->right){int row2=p->j;for(q=N.rhead[row2];q;q=q->right)//将每一行的各列乘积存入temp中 {col=q->j;temp[col].e+=p->e*q->e;temp[col].i=row;temp[col].j=col;}}for(col=1;col<=Q.nu;col++)//将temp中的数据赋值给t,将t插入Q中 {if(temp[col].e!=0){t=(Olink)malloc(sizeof(OLnode));t->e=temp[col].e;t->i=temp[col].i;t->j=temp[col].j;insert_row(Q,t,row);insert_col(Q,t,col);}}}}void output(Crosslist M) //输出矩阵M{OLnode *pp;for(int i=1;i<=M.mu;i++){pp=M.rhead[i];for(int j=1;j<=M.nu;j++){if(pp&&pp->j==j){int e=pp->e;cout<<pp->e<<" ";pp=pp->right;}elsecout<<0<<" ";}cout<<endl;}}void main(){Crosslist M,N,Q;input(M);input(N);cout<<"矩阵M:"<<endl;output(M);cout<<"矩阵N:"<<endl;output(N);chengfa(M,N,Q);cout<<"矩阵M、N的乘积为:"<<endl; output(Q);}运行结果:。
基于mpi实现稀疏矩阵的乘法
基于mpi实现稀疏矩阵的乘法要基于MPI实现稀疏矩阵的乘法,首先需要将稀疏矩阵存储在内存中的数据结构转换成适合在MPI上进行并行计算的数据结构。
稀疏矩阵通常采用压缩稀疏行(Compressed Sparse Row,CSR)格式进行存储。
在CSR格式中,矩阵被分为三个数组:val、col_ind和row_ptr。
val数组存储所有非零元素的值,col_ind数组存储对应非零元素的列索引,而row_ptr数组存储每一行的起始位置在val和col_ind数组中的索引。
在基于MPI的并行计算中,每个MPI进程将会处理部分矩阵的行。
因此,需要将稀疏矩阵按照行进行划分,并将行划分的结果分配给每个MPI进程。
下面是一个基于MPI的稀疏矩阵乘法的伪代码:```#include <mpi.h>MPI_Init(NULL, NULL);int rank, size;MPI_Comm_rank(MPI_COMM_WORLD, &rank);MPI_Comm_size(MPI_COMM_WORLD, &size);// 假设稀疏矩阵A和向量x的CSR格式为val、col_ind和row_ptr// 假设矩阵A的行数为M,列数为N,向量x的长度为N double* val_A;int* col_ind_A;int* row_ptr_A;int M, N;// 由主进程读取稀疏矩阵A和向量x,并分发给其他进程if (rank == 0) {// 从文件或其他地方读取稀疏矩阵A和向量x的值,并存储在val_A、col_ind_A和row_ptr_A等变量中// 设置矩阵A的行数M和列数N// 将稀疏矩阵A和向量x的数据按行划分,并发送给其他进程for (int i = 1; i < size; i++) {// 计算每个MPI进程处理的行数和起始行索引int rows = ...; // 每个进程处理的行数int start_row = ...; // 每个进程处理的起始行索引// 发送稀疏矩阵A的值、列索引和行指针数组给其他进程 // 发送向量x的值给其他进程MPI_Send(val_A + start_row, rows * N, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);MPI_Send(col_ind_A + start_row, rows * N, MPI_INT, i, 0, MPI_COMM_WORLD);MPI_Send(row_ptr_A + start_row, rows + 1, MPI_INT, i, 0, MPI_COMM_WORLD);MPI_Send(x, N, MPI_DOUBLE, i, 0,MPI_COMM_WORLD);}} else {// 接收稀疏矩阵A和向量x的数据MPI_Recv(val_A, <每个进程处理的行数> * N,MPI_DOUBLE, 0, 0, MPI_COMM_WORLD,MPI_STATUS_IGNORE);MPI_Recv(col_ind_A, <每个进程处理的行数> * N, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);MPI_Recv(row_ptr_A, <每个进程处理的行数> + 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);MPI_Recv(x, N, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);}// 在每个进程上计算稀疏矩阵乘法的结果// 假设结果向量y的长度为Mdouble* y = new double[<每个进程处理的行数>];for (int i = 0; i < <每个进程处理的行数>; i++) {double sum = 0.0;for (int j = row_ptr_A[i]; j < row_ptr_A[i + 1]; j++) {sum += val_A[j] * x[col_ind_A[j]];}y[i] = sum;}// 将每个进程上的计算结果发送给主进程if (rank == 0) {// 接收其他进程的计算结果for (int i = 1; i < size; i++) {double* recv_buf = new double[<每个进程处理的行数>]; MPI_Recv(recv_buf, <每个进程处理的行数>,MPI_DOUBLE, i, 0, MPI_COMM_WORLD,MPI_STATUS_IGNORE);// 将每个进程的计算结果合并到结果向量y中for (int j = 0; j < <每个进程处理的行数>; j++) {y[<每个进程的处理起始行索引> + j] = recv_buf[j];}delete[] recv_buf;}} else {// 发送计算结果给主进程MPI_Send(y, <每个进程处理的行数>, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);}// 主进程输出结果向量yif (rank == 0) {for (int i = 0; i < M; i++) {std::cout << y[i] << " ";}std::cout << std::endl;}// 释放内存delete[] val_A;delete[] col_ind_A;delete[] row_ptr_A;delete[] x;delete[] y;MPI_Finalize();```请注意,上述代码中的一些变量和计算的具体实现可能需要根据你的具体需求进行调整。
稀疏矩阵的存储和乘法操作
稀疏矩阵的存储和乘法操作⼀稀疏矩阵的存储1.三元组顺序表三元组表⽰法就是在存储⾮零元的同时,存储该元素所对应的⾏下标和列下标。
稀疏矩阵中的每⼀个⾮零元素由⼀个三元组(i,j,a ij)唯⼀确定。
矩阵中所有⾮零元素存放在由三元组组成的顺序表中(通常⽤数组)。
所以三元组的逻辑结构如下://————稀疏矩阵的三元组表⽰法————//#define MAX_SIZE 1500 //表⽰稀疏矩阵的⾮零元素的最⼤个数class Triple{int i,j;//表⽰⾮零元素的⾏下表和列下标int val;//⾮零元素的值,此处以int类型为例};class TSMatrix{Triple data[MAX_SIZE];int row_num,col_num,cnt;//稀疏矩阵的⾏数、列数以及⾮零元素的个数};注意,此处的⾮零元素的三元组是以⾏序为主序顺序排列的。
2.⾏逻辑链接顺序表⾏逻辑链接顺序表的实质就是在三元组顺序表的基础上加了⼀个数组,这个数组⽤于存储稀疏矩阵中每⾏的第⼀个⾮零元素的在三元组顺序表中的位置(此处⼀定要理解对,是在三元组顺序表中的位置)。
所以其逻辑结构如下://————稀疏矩阵的⾏逻辑链接表⽰法————//#define MAX_SIZE 1500 //表⽰稀疏矩阵的⾮零元素的最⼤个数#define MAX_ROW 1500 //表⽰稀疏矩阵的⾏数的最⼤个数class Triple{int i,j;//表⽰⾮零元素的⾏下表和列下标int val;//⾮零元素的值,此处以int类型为例};class RLSMatrix{Triple data[MAX_SIZE]; //⾮零元三元组表int rpos[MAX_ROW];//每⾏第⼀个⾮零元素的位置int row_num,col_num,cnt;//稀疏矩阵的⾏数、列数以及⾮零元素的个数};3.⼗字链表当稀疏矩阵的⾮零元个数和位置在操作过程中变化较⼤时,就不易采⽤顺序存储结构来表⽰三元组的线性表。
稀疏矩阵相乘
稀疏矩阵相乘1问题描述稀疏矩阵的三元组及十字链表表示(1)稀疏矩阵及其三元组表示 稀疏矩阵(2)稀疏矩阵的十字链表表示基本要求(1)以“带行逻辑链接信息”的三元组表示稀疏矩阵; (2)输入矩阵用三元组顺序输入; (2)稀疏矩阵采用十字链表表示;(3)实现两个矩阵相乘的运算,而运算结果的矩阵则以通常的阵列形式列出。
2设计思路行(row) 列(col) 值(value)[0] 0 3 22 [1] 0 6 15 [2] 1 1 11 [3] 1 5 17 [4] 2 3 -6 [5] 3 5 39 [6] 4 0 39 [7]52280000280000000091039000000006000017000110150022000⎪⎪⎪⎪⎪⎪⎪⎪⎭⎫⎝⎛-存储结构设计三元组表示稀疏矩阵只存储矩阵中极少的非零元素,采用<row,col,value>来唯一地确定每一个非零元素,其中row、col、value分别表示非零元素在矩阵中的的行下标、列下表和值。
各数组元素的三元组按在原矩阵中的位置以行优先的顺序依次存放。
struct triple{ //三元组结构定义int row, col; //非零元素行号,列号Float value; //非零元素的值triple& operator=(triple &x){row=;col=;value=;}};十字链表表示稀疏矩阵struct element{ int row,col;float value;};class Matrix;class node{ // 矩阵节点类的定义friend class Matrix;public:node():head(true){ right=down=this;} //建立附加头结点node(element *t) // 建立非零元素结点{=t->col;=t->row;=t->value;right=down=this;head=false;}node*down,*right;//行列链表指针bool head;union{ element triple;node*next;}; //无名联合};class Matrix{//稀疏矩阵的类定义friend istream&operator>>(istream&,Matrix&);friend ostream&operator<<(ostream&,Matrix&);private:int Row,Col,Terms,temp; //矩阵的总行数,总列数,和非零元素个数和临时变量;node*headnode; //稀疏矩阵的总表头public:Matrix(int m,int n); //重载构造函数Matrix(); //对矩阵进行构造Matrix(Matrix& T); //复制构造函数~Matrix(){makeEmpty();} //析构函数void Init(int m,int n); //初始化函数,又来初始化无参构造函数构造的矩阵void makeEmpty(); //清空矩阵void Insert(int m,int n,float p); //插入矩阵元素node *Locate(int i); //定位附加头结点Matrix Mul(Matrix b); //两个矩阵相乘Matrix &operator=(Matrix &T); //重载赋值号};在稀疏矩阵的十字链表表示中,矩阵的的每一行设置为一个带附加头结点的循环行链表,每一列也设置为一个带附加头结点的循环列链表。
稀疏矩阵乘法 并行
稀疏矩阵乘法并行
稀疏矩阵乘法是指两个稀疏矩阵相乘的运算。
稀疏矩阵是指大部分元素为零的矩阵。
由于稀疏矩阵的特殊性质,传统的矩阵乘法算法在稀疏矩阵上执行效率较低,因此并行计算可以提高稀疏矩阵乘法的运算速度和效率。
首先,我们可以从并行计算的角度来考虑稀疏矩阵乘法。
在并行计算中,可以将稀疏矩阵分割成多个子矩阵,然后在多个处理单元上同时进行计算,最后将结果合并得到最终的乘积矩阵。
这样可以充分利用并行计算的优势,加快稀疏矩阵乘法的运算速度。
其次,从算法优化的角度来看,针对稀疏矩阵的特点,可以采用一些特殊的算法来进行并行计算。
例如,可以使用CSR (Compressed Sparse Row)格式或者CSC(Compressed Sparse Column)格式来存储稀疏矩阵,并设计针对这些格式的并行算法来进行稀疏矩阵乘法的计算,以提高计算效率。
另外,还可以考虑使用GPU进行并行计算。
由于GPU具有大量的并行计算单元,适合处理大规模数据的特点,可以利用GPU的并行计算能力来加速稀疏矩阵乘法的运算。
此外,针对稀疏矩阵乘法的特点,还可以结合多线程并行计算,利用多核处理器的优势,实现稀疏矩阵乘法的并行计算。
总的来说,稀疏矩阵乘法的并行计算可以从多个角度进行优化,包括算法设计、数据格式选择以及硬件加速等方面,以提高稀疏矩
阵乘法的运算速度和效率。
通过并行计算,可以更好地利用计算资源,加快稀疏矩阵乘法的计算速度,提高计算效率。
稀疏矩阵乘法算法
稀疏矩阵乘法算法
稀疏矩阵乘法算法是一种优化矩阵乘法运算的方法,适用于稀疏矩阵的乘法运算。
稀疏矩阵指的是矩阵中大部分元素都是0的矩阵。
传统的矩阵乘法算法在处理稀疏矩阵时效率较低,因为它需要计算每一个元素的乘积,即使其中一项为0。
稀疏矩阵乘法算法则只计算非零元素的乘积,从而避免了大量无效的计算。
稀疏矩阵乘法算法的实现方法有多种,其中比较常用的是压缩稀疏矩阵的存储方法。
这种方法将稀疏矩阵中的非零元素存储在一个数组中,并记录每一行中的非零元素的位置和数量,从而减少了存储空间。
在计算乘积时,只需要遍历非零元素的位置进行计算即可。
稀疏矩阵乘法算法的时间复杂度与稀疏矩阵的非零元素个数有关,一般情况下比传统矩阵乘法算法更快。
因此,在处理稀疏矩阵的乘法运算时,稀疏矩阵乘法算法是一种优秀的选择。
- 1 -。
稀疏矩阵的加、减、乘、求逆运算
稀疏矩阵的加、减、乘、求逆运算#include <iostream>#include <iomanip>using namespace std;const int MAXSIZE = 100; //定义非零元素的最多个数const int MAXROW = 10; //定义数组行数的最大值const int SIZENUM = 10;typedef struct //定义三元组元素{int r, c; //矩阵的行号和列号int v; //矩阵元素值}Triple;typedef struct //定义普通三元组对象{Triple data[MAXSIZE+1];int rows, cols, nzeroNums; //行数、列数、非零元素个数}TSMatrix;typedef struct //定义行逻辑链接的顺序表{Triple data[MAXSIZE+2]; //非0元三元组表int rpos[MAXROW+1]; //各行第一个非零元素的位置表int rows, cols, nzeroNums; //行数、列数、非零元素个数}RLSMatrix;//输入三元组矩阵template <class T>bool InputTSMatrix(T &M, int y){cout << "输入矩阵的行数、列数和非零元素个数: ";cin >> M.rows >> M.cols >> eroNums;cout << "请输入非零元素对应的行号、列号和相应的元素值: " << endl;for (int i = 1; i <= eroNums; i++){cin >> M.data[i].r >> M.data[i].c >> M.data[i].v;}return true;}//输出矩阵,按标准格式输出template <class T>bool OutputSMatrix(T M){int i, j, k = 1;for (i = 0; i < M.rows; i++){for (j = 0; j < M.cols; j++){if ((M.data[k].r-1) == i && (M.data[k].c-1) == j){cout << setw(4) << M.data[k].v;k++;}elsecout << setw(4) << "0";}//end_jcout << endl;}//end_ireturn true;}//求稀疏矩阵的转置int TranSMatrix(){TSMatrix M, T;InputTSMatrix(M, 0);int col, p, q = 1;T.rows = M.cols;T.cols = M.rows;eroNums = eroNums;if (eroNums){for (col = 1; col <= M.cols; col++){for (p = 1; p <= eroNums; p++){if (M.data[p].c == col){T.data[q].r = M.data[p].c;T.data[q].c = M.data[p].r;T.data[q].v = M.data[p].v;++q;}}//end_col}//end_ifcout << "运用普通转置算法, 输入矩阵的转置矩阵为: " << endl;OutputSMatrix(T);return 1;}//稀疏矩阵的快速转置int FastTranMat(){TSMatrix M, T;int num[MAXROW+1]; //表示矩阵M中第col列非零元素的个数int cpot[MAXROW+1]; //表示矩阵M中第col列第一个非0元素在b.data中的位置int p, q, col, t;InputTSMatrix(M, 0); //输入稀疏矩阵T.rows = M.cols;T.cols = M.rows;eroNums = eroNums;if (eroNums){for (col = 1; col <= M.cols; col++)//M中各列元素初始化{num[col] = 0;}for (t = 1; t <= eroNums; t++){++num[M.data[t].c]; //求M中每一列非零元个数}//求第col列第一个非零元在b.data中的序号cpot[1] = 1;for (col = 2; col <= M.cols; col++){cpot[col] = cpot[col-1] + num[col-1];}for (p = 1; p <= eroNums; p++){col = M.data[p].c; //稀疏矩阵M中每个元素对应的列号q = cpot[col]; //稀疏矩阵M中第一个非零元素位置T.data[q].r = M.data[p].c;T.data[q].c = M.data[p].r;T.data[q].v = M.data[p].v;++cpot[col];}//end_ifcout << "运用快速算法,输入矩阵的转置为: " << endl;OutputSMatrix(T);return 1;}//求取稀疏矩阵每一行非零元个数bool Count(RLSMatrix &M){int row, p;int num[MAXROW+1];for (row = 1; row <= M.rows; row++){num[row] = 0; //清零}for (p = 1; p <= eroNums; p++){++num[M.data[p].r]; //统计M每一行非零元个数}M.rpos[1] = 1;//M中每一行非零元的起始位置for (row = 2; row <= M.rows; row++){M.rpos[row] = M.rpos[row-1] + num[row-1];}return true;}//两个稀疏矩阵的乘法bool MultSMatrix(){RLSMatrix M, N, Q; //构建三个带链接信息的三元组表示的数组InputTSMatrix(M, 1); //用普通三元组形式输入数组InputTSMatrix(N, 1);Count(M);Count(N);if (M.cols != N.rows){cout << "Error!";return false;}//Q的初始化Q.rows = M.rows;Q.cols = N.cols;eroNums = 0;int mrow, nrow, p, q, t, tp, qcol;int ctemp[MAXROW+1]; //辅助数组//如果Q是非零矩阵if (eroNums * eroNums){for (mrow = 1; mrow <= M.rows; mrow++){//当前行各元素累加器清零for (int x = 1; x <= N.cols; x++){ctemp[x] = 0;}//end_x//当前行的首个非零元素在三元组中的位置为此行前所有非0元素加1Q.rpos[mrow] = eroNums + 1;if (mrow < M.rows){tp = M.rpos[mrow+1];}elsetp = eroNums + 1;for (p = M.rpos[mrow]; p < tp; p++) //对当前行的每个非零元素操作{nrow = M.data[p].c; //在N中找到与M操作元素的c值相等的行值rif (nrow < N.rows){t = N.rpos[nrow+1];}elset = eroNums + 1;//对找出的行的每个非零元素进行操作for (q = N.rpos[nrow]; q < t; q++){qcol = N.data[q].c;//将乘得到的对应值放在相应元素的累加器里面ctemp[qcol] += M.data[p].v * N.data[q].v;}}//p_end_for//对已经求出的累加器中的值压缩到Q中for (qcol = 1; qcol <= Q.cols; qcol++){if (ctemp[qcol])if (++eroNums > MAXSIZE){cout << "Error!" << endl;return 0;}Q.data[eroNums].r = mrow;Q.data[eroNums].c = qcol;Q.data[eroNums].v = ctemp[qcol];}}//qcol_end_for}//arow_end_for}//end_ifcout << "两个稀疏矩阵相乘的结果为:\n";OutputSMatrix(Q);return 1;}//两个稀疏矩阵的加法int AddMatrix(){TSMatrix A, B, C;int i = 1, j = 1, k = 1; //i, j, k分别用以保存A、B、C非零元素个数int value = 0;InputTSMatrix(A, 0);InputTSMatrix(B, 0);if (A.rows != B.rows || A.cols != B.cols){cout << "两个稀疏矩阵的大小不等,不能相加!" << endl;return 0;}if (A.rows == B.rows && A.cols == B.cols){while (i <= eroNums && j <= eroNums){if (A.data[i].r == B.data[j].r){if (A.data[i].c < B.data[j].c){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;i++;else if (A.data[i].c > B.data[j].c){C.data[k].r = B.data[j].r;C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;j++;}else{value = A.data[i].v + B.data[j].v;if (value != 0){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = value;k++;}i++;j++;}}//end_ifelse if (A.data[i].r < B.data[j].r){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;i++;}else{C.data[k].r = B.data[j].r;C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;j++;}//把剩余部分元素存入C中if (i > eroNums && j <= eroNums) {for (; j <= eroNums; j++){C.data[k].c = B.data[j].c;C.data[k].v = B.data[j].v;k++;}}if (i <= eroNums && j > eroNums){for (; i <= eroNums; i++){C.data[k].r = A.data[i].r;C.data[k].c = A.data[i].c;C.data[k].v = A.data[i].v;k++;}}}//end_whileC.rows = A.rows;C.cols = A.cols;eroNums = k-1;cout << "输出两个稀疏矩阵的和: " << endl;OutputSMatrix(C);return 1;}//end_ifelsereturn 0;}//两个稀疏矩阵的减法int SubMatrix(){TSMatrix A, B, C;int m = 1, n = 1, k = 1, temp;InputTSMatrix(A, 0);InputTSMatrix(B, 0);C.rows = A.rows;C.cols = A.cols;eroNums = 0;if (A.rows == B.rows && A.cols == B.cols){while (m <= eroNums && n <= eroNums){if (A.data[m].r == B.data[n].r){{temp = A.data[m].v - B.data[n].v;if (temp != 0){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;C.data[k].v = temp;k++;}m++;n++;}else if (A.data[m].c < B.data[n].c){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;C.data[k].v = A.data[m].v;k++;m++;}else{C.data[k].r = B.data[n].r;C.data[k].c = B.data[n].c;C.data[k].v = -B.data[n].v;k++;n++;}}else if (A.data[m].r < B.data[n].r){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;;C.data[k].v = A.data[m].v;k++;m++;}else{C.data[k].r = B.data[n].r;C.data[k].c = B.data[n].c;C.data[k].v = -B.data[n].v;k++;n++;}}//end_whileif (m <= eroNums){for (; m <= eroNums; m++){C.data[k].r = A.data[m].r;C.data[k].c = A.data[m].c;C.data[k].v = A.data[m].v;k++;}}if (n <= eroNums){for (; n <= eroNums; n++){C.data[k].r = B.data[n].r;C.data[k].c = B.data[n].c;C.data[k].v = -B.data[n].v;k++;}}eroNums = k-1;cout << "两个稀疏矩阵的差为:\n";OutputSMatrix(C);return 1;} //end_ifelse{cout << "两个稀疏矩阵的大小不同,不能相减!\n";return 0;}}//得到矩阵元素M[i][j]的值int value(TSMatrix M, int i, int j){int k;for (k = 1; k <= eroNums; k++){if (M.data[k].r == i && M.data[k].c == j){return M.data[k].v;}}return 0;}//矩阵乘法的算法2int MultMat(){TSMatrix A, B, C;InputTSMatrix(A, 0);InputTSMatrix(B, 0);int i, j, k, temp = 0, p = 1;if (A.cols != B.rows){cout << "矩阵A的列数不等于矩阵B的行数不能相乘!\n";return 0;}else{for (i = 1; i <= A.rows; i++){for (j = 1; j <= B.cols; j++){temp = 0;for (k = 1; k <= A.cols; k++){temp += value(A, i, k) * value(B, k, j);}if (temp != 0){C.data[p].r = i;C.data[p].c = j;C.data[p].v = temp;p++;}}}C.rows = A.rows;C.cols = B.cols;eroNums = p-1;OutputSMatrix(C);return 1;}}//计算矩阵的行列式, 通过递归算法来实现int JsMatrix(int s[][MAXROW], int n){int i, j, k, r, total = 0;int b[SIZENUM][SIZENUM]; //b[N][N]用于存放在矩阵s[N][N]中元素s[0]的余之式if (n == 1){total = s[0][0];}else if (n == 2){total = s[0][0] * s[1][1] - s[0][1] * s[1][0];}else{for (i = 0; i < n; i++){for (j = 0; j < n-1; j++){for (k = 0; k < n-1; k++){if (k >= i){b[j][k] = s[j+1][k+1];}else{b[j][k] = s[j+1][k];}}//end_for_k}//end_for_jif (i % 2 == 0){r = s[0][i] * JsMatrix(b, n-1); //递归调用}else{r = (-1) * s[0][i] * JsMatrix(b, n-1);}total += r;}//end_for_i}//end_elsereturn total;}//求原矩阵个元素对应的余之式, 存放在b[n][n]中,定义为float型void N1Matrix(int s[][SIZENUM], float b[][SIZENUM], int n){int i, j, k, l, m, g, a[SIZENUM][SIZENUM];for (i = 0; i < n; i++){m = i;for (j = 0; j < n; j++){g = j;for (k = 0; k < n-1; k++){for (l = 0; l < n-1; l++){if (k >= m && l >= g){a[k][l] = s[k+1][l+1];}else if (k < m && l >= g){a[k][l] = s[k][l+1];}else if (k >= m && l < g){a[k][l] = s[k+1][l];}else{a[k][l] = s[k][l];}}//end_for_l}//end_for_kb[i][j] = JsMatrix(a, n-1);}//end_for_j}//end_for_i}//稀疏矩阵求逆void InverseMat(){TSMatrix M;InputTSMatrix(M, 0);int i, j, k, n = M.rows;float temp;int a[SIZENUM][SIZENUM];float b[SIZENUM][SIZENUM], c[SIZENUM][SIZENUM];for (i = 0; i < n; i++) //初始化矩阵a{for (j = 0; j < n; j++){a[i][j] = 0;}}for (i = 1; i <= eroNums; i++) //给矩阵a赋值{a[M.data[i].r-1][M.data[i].c-1] = M.data[i].v;}cout << "稀疏矩阵对应的普通矩阵为: \n";for (i = 0; i < n; i++) //打印原矩阵{for (j = 0; j < n; j++){cout << setw(4) << a[i][j] << setw(4);}cout << endl;}k = JsMatrix(a, n);cout << "矩阵的行列式值: |A| = " << k << endl;if (k == 0){cout << "行列式的值为0, 原矩阵无逆矩阵!" << endl;}else{N1Matrix(a, b, n); //调用函数,得到原矩阵各元素对应的余之式存放在数组b[n][n]中//求代数余之式cout << "普通矩阵各元素对应的代数余之式矩阵为: \n";for (i = 0; i < n; i++){for (j = 0; j < n; j++){if ((i+j)%2 != 0 && b[i][j] != 0){b[i][j] = -b[i][j];}cout << setw(4) << b[i][j] << setw(4);}cout << endl;}//end_for_i//对b[N][N]转置,此时b[n][n]存放的为原矩阵的伴随矩阵for (i = 0; i < n; i++){for (j = i+1; j < n; j++){temp = b[i][j];b[i][j] = b[j][i];b[j][i] = temp;}}cout << "伴随矩阵A*: " << endl;for (i = 0; i < n; i++) //打印伴随矩阵A*{for (j = 0; j < n; j++){cout << setw(4) << b[i][j] << setw(4);}cout << endl;}for (i = 0; i < n; i++) //求逆矩阵,此时c[n][n]中存放的是原矩阵的逆矩阵{for (j = 0; j < n; j++){c[i][j] = b[i][j]/k;}}cout << "逆矩阵(A*)/|A|: " << endl;for (i = 0; i < n; i++) //打印逆矩阵{for (j = 0; j < n; j++){cout << setw(6) << c[i][j] << setw(6);}cout << endl;}}//end_else}{char c;cout << setw(50) << "******欢迎使用稀疏矩阵的相关操作!******" << endl << endl;cout.fill('*');cout << setw(20) << '*';cout << "请选择要进行的操作";cout << setw(20) << '*' << endl;cout << setw(6) << '*' << " 1: 稀疏矩阵的普通转置算法" << endl;cout << setw(6) << '*' << " 2: 稀疏矩阵的快速转置算法" << endl;cout << setw(6) << '*' << " 3: 稀疏矩阵的乘法的快速算法" << endl;cout << setw(6) << '*' << " 4: 稀疏矩阵的乘法的经典算法" << endl;cout << setw(6) << '*' << " 5: 稀疏矩阵的加法" << endl;cout << setw(6) << '*' << " 6: 稀疏矩阵的减法" << endl;cout << setw(6) << '*' << " 7: 求稀疏矩阵的逆" << endl;cout << setw(6) << '*' << " 0: 退出程序" << endl;cout.fill(' ');c = getchar();switch(c){case '1':TranSMatrix();break;case '2':FastTranMat();break;case '3':MultSMatrix();break;case '4':MultMat();break;case '5':AddMatrix();break;case '6':SubMatrix();break;case '7':InverseMat();break;case '0':cout << "谢谢使用! 再见!" << endl;break;cout << "错误命令!" << endl << endl;break;}return 0;。
稀疏矩阵乘法
稀疏矩阵乘法
稀疏矩阵乘法是指矩阵乘法,其中一个或两个输
入矩阵都是稀疏矩阵。
稀疏矩阵是指当矩阵中大
多数元素都是零时,用较少数据表示矩阵的数据
结构。
稀疏矩阵乘法把空间和时间复杂度降低了。
一、什么是稀疏矩阵乘法?
稀疏矩阵乘法(sparse matrix multiplication),是指
当一个(或两个)输入矩阵中的大多数元素为零时,采用较少数据表示矩阵的数据结构,在一些
应用场景中,可以减少计算的方法及时间覆盖率。
它可以把空间和时间复杂度降低了。
二、稀疏矩阵乘法的特点
(1)它需要少量的额外空间,可以节省很大的内存空间,而且速度也会提高。
(2)它可以显著提高矩阵乘法的效率,使得矩阵乘法可以在稀疏矩阵计算方面大大提高,且运算时间短、耗能少。
(3)它可以增加乘积矩阵的稀疏程度,并能同时得到多个稀疏乘积结果。
三、稀疏矩阵乘法的优势
(1)稀疏矩阵乘法的运算时间较矩阵乘法短,比其它计算方法更快。
(2)稀疏矩阵乘法可以高效地利用现有存储器结构,并将所需数据传送到存储器中。
(3)它可以明显降低计算开销,并在数据库查询大量数据时有显著优势。
四、稀疏矩阵乘法的应用
(1)稀疏矩阵乘法应用于搜索引擎,复杂的数据
挖掘任务,图像处理,矩阵乘积,矩阵运算,特征提取及分类。
(2)稀疏矩阵乘法也广泛应用于大规模数据的处理,如金融业决策支持,视频监控,天气预测,密码学等。
(3)它还可以应用于深度学习,机器学习,机器人控制及人工智能等领域,以便快速解决多项复杂问题。
pytorch 稀疏矩阵乘法
pytorch 稀疏矩阵乘法PyTorch 是已经成为了深度学习领域中最具有代表性的一种框架,而其本身的灵活性和强大性质也为其赢得了大量的忠实用户,其中之一就是在矩阵计算方面进行优化的 PyTorch 稀疏矩阵乘法。
对于机器学习和深度学习任务特别有效,不仅能提高执行效率,同时还可以大大减少计算和存储开销。
本篇文章主要介绍 PyTorch 稀疏矩阵乘法的应用和实现细节。
## 什么是稀疏矩阵稀疏矩阵是指大多数元素为零的矩阵。
在矩阵计算中,大多数操作都会涉及到元素的乘法操作,而稀疏矩阵的计算往往能够通过改进算法,提高计算效率。
在深度学习中,我们通常会处理高维矩阵,很多时候,这些高维矩阵的大多数元素都为零,这时候就可以利用稀疏矩阵优化计算,加快模型的训练速度。
## 稀疏矩阵乘法稀疏矩阵乘法是指对两个稀疏矩阵进行乘法操作的过程。
可以用矩阵的标准乘法表达式进行定义,如下所示:$$ c_{i,j}=\sum_k a_{i,k}b_{k,j} $$其中,矩阵 $A$ 的维度为 $m \times n$,矩阵$B$ 的维度为 $n \times k$,矩阵 $C$ 的维度为 $m\times k$。
对于稀疏矩阵乘法,相应的优化算法能够通过改变乘法操作的顺序来避免大量的费时操作,并实现更高效的计算。
下面介绍 PyTorch 中的稀疏矩阵乘法实现方法。
## PyTorch 稀疏矩阵乘法的实现PyTorch 中使用稀疏矩阵进行计算的方法是,将稀疏矩阵的非零元素保存在稀疏张量(sparse tensor)的indices、values 和 size 属性中,并通过 PyTorch 提供的稀疏矩阵乘法函数进行计算。
### 创建稀疏张量PyTorch 中提供了两种方式创建稀疏张量。
第一种方式是先创建一个密集矩阵,再将其转换为稀疏矩阵。
第二种方式是直接创建稀疏张量。
#### 创建密集矩阵下面是如何使用 PyTorch 创建密集矩阵的示例代码:```python import torchdense_matrix = torch.randn(3, 5) ```#### 将密集矩阵转换为稀疏矩阵下面是如何使用 PyTorch 将密集矩阵转换为稀疏矩阵的示例代码:```python sparse_matrix =torch.sparse_coo_tensor( dense_matrix.nonzero(), dense_matrix[dense_matrix.nonzero()],size=dense_matrix.shape ) ```在上述代码中,我们首先使用dense_matrix.nonzero() 获取矩阵 non-zero 元素的索引,然后使用 dense_matrix[dense_matrix.nonzero()]获取该索引处元素的值,最后使用这些索引和值创建稀疏矩阵。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计任务书学生姓名:专业班级:指导教师:夏红霞工作单位:计算机科学与技术学院题目: 稀疏矩阵乘法的运算课程设计要求:1、熟练掌握基本的数据结构;2、熟练掌握各种算法;3、运用高级语言编写质量高、风格好的应用程序。
课程设计任务:1、系统应具备的功能:(1)设计稀疏矩阵的存储结构(2)建立稀疏矩阵(3)实现稀疏矩阵的乘法2、数据结构设计;3、主要算法设计;4、编程及上机实现;5、撰写课程设计报告,包括:(1)设计题目;(2)摘要和关键字;(3)正文,包括引言、需求分析、数据结构设计、算法设计、程序实现及测试、不足之处、设计体会等;(4)结束语;(5)参考文献。
时间安排:2010年7月5日-9日(第19周)7月5日查阅资料7月6日系统设计,数据结构设计,算法设计7月7日 -8日编程并上机调试7月9日撰写报告7月10日验收程序,提交设计报告书。
指导教师签名: 2010年7月4日系主任(或责任教师)签名: 2010年7月4日目录1.摘要 (1)2.关键字 (1)3.引言 (1)4. 问题描述 (1)5. 系统设计 (1)6. 数据结构 (3)7. 算法描述 (3)8. 测试结果与分析 (4)9. 源代码 (12)10. 总结 (29)11.参考文献 (29)稀疏矩阵乘法的运算1.摘要:在一些数值计算中,一些二维矩阵的乘法运算很常见,我们经常采用线性代数中的知识进行运算,然而对一些含有非零元很少的二维矩阵也采用相同的方法时,就会发现那样的方法不仅需要很多的空间来存储0,造成空间复杂度比较大,而且算法的时间复杂度也较大。
因此需要采取其他的方法来解决这个问题,由于0在乘法中其结果总是0,所以可以考虑采用三元组的方式去存储稀疏矩阵中的非零元,这样在计算过程中不仅需要的内存空间减少了,而且运算的速率也提高了。
2.关键字:稀疏矩阵乘法二维矩阵算法复杂度3.引言:随着科学技术的发展,人们对矩阵的运算的几率越来越大,特别是高新科技研究中对矩阵的运算更是常见。
但是如何高效的并占内存少的进行矩阵运算就是一个急需解决的问题。
本文主要对稀疏矩阵的存储以及稀疏矩阵的乘法运算进行了研究和探讨。
4.问题描述:在一些数值计算中,一些二维矩阵的乘法运算很常见,我们经常采用线性代数中的知识进行运算,然而对一些含有非零元很少的二维矩阵也采用相同的方法时,就会发现那样的方法不仅需要很多的空间来存储0,造成空间复杂度比较大,而且算法的时间复杂度也较大。
为了减少空间和时间复杂度,可以根据给定的二维数组的数据设计稀疏矩阵的存储结构,然后根据设计的稀疏矩阵存储结构建立一个稀疏矩阵,最后获得两个二维数组得到他们各自的稀疏矩阵,计算这两个稀疏矩阵的乘积。
5.系统设计:5.1 设计目标:通过一定的数据结构,存储含有少量数据的矩阵,把他们存入一个稀疏矩阵中,然后实现稀疏矩阵的乘法运算。
[基本要求]设计稀疏矩阵的存储结构;建立稀疏矩阵;实现稀疏矩阵的乘法5.2 系统实现的操作和功能:5.2.1初始化:初始化一些数据5.2.2获得数据:根据客户的要求可以采用人工输入和从文件中读取数据两种方式获得二维矩阵的中的数据。
然后根据相应的数据建立稀疏矩阵。
5.2.3检查数据的合法性:当这两个二维矩阵不满足矩阵相乘的条件时,系统将报错,并退出系统。
5.2.4稀疏矩阵的乘法:当两个二维矩阵合法时将对其进行乘法运算,然后将结果输出并按用户的要求保存到相应的文件中。
5.3设计思想:在操作的过程中采用三元组建立稀疏矩阵。
用户可以通过输入数据或者文件名以后,系统会自动建立一个三元组的稀疏矩阵,然后对其进行乘法运算。
在里面主要包含两个函数文件:获得数据并建立稀疏矩阵,对稀疏矩阵进行合法性的检查并进行乘法运算。
5.4系统模块划分:6.数据结构:采用结构体存储每行每列的元素:typedef struct DataNode {int row ;//存储所在二维矩阵的行数 int col ;//存储所在二维矩阵的列数稀疏矩阵乘法的运算获得数据并建立稀疏矩阵检查矩阵合法性并进行乘法运算输出结果并存到指定文件中数据初始化ElemType data;//存储row行col列的元素的值}DataNode;采用结构体存储稀疏二维数组:typedef struct SparseMatrix{DataType *matrix;//用数组存储非零元int row;//二维数组的行数int col;//二维数组的列数int *rpos;//每行第一个非零元在matrix中的位置int num;//非零元的个数int con;//指定常数};注:在第二个结构体中num和con这两个变量,在本此系统中con默认为0,num的功能是检验数据是否完整。
当二维数组中出现很多非零元素值一样的时候,也可以采用三元组的方法存储,只要让con等于那个非零元素值即可。
7.算法描述:本系统的主要算法为稀疏矩阵的乘法运算。
算法如下:Q初始化;if (Q是非零矩阵){//逐行求积for(arow=1;arow<=M.row;++arow){//处理M的每一行ctemp[]=0;//累加器清零计算Q中第arow行的积并存入ctemp[]中;将ctemp[]中的非零元压缩存储到Q.matrix中;}}8.测试结果与分析:测试1:两个文件数据完全正确Input the method of getting data(1 is from file,2 is from inputting):1 Input two names of the data file:data1.txt data2.txtRead the first file successfully!Read the second file successfully!The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -13 2 4Input one name of the data file:data5.txt测试2:一个文件数据完全正确,另一个文件数据不正确Input the method of getting data(1 is from file,2 is from inputting):1 Input two names of the data file:data1.txt data4.txtRead the first file successfully!The data is wrong!The first data is wrong!Please check it carefully,then input it again:1 2 2The data is wrong!The 4th data is wrong!Please check it carefully,then input it again:3 2 4Read the second file successfully!The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -13 2 4Input one name of the data file:data6.txt测试3:两个数据文件都错误Input the method of getting data(1 is from file,2 is from inputting):1 Input two names of the data file:data3.txt data4.txtThe data is wrong!The second data is wrong!Please check it carefully,then input it again:The data is wrong!The 4th data is wrong!Please check it carefully,then input it again: 3 1 2Read the first file successfully!The data is wrong!The first data is wrong!Please check it carefully,then input it again: 1 2 2The data is wrong!The 4th data is wrong!Please check it carefully,then input it again: 3 2 4Read the second file successfully!The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -1Input one name of the data file:data7.txt测试4:不符合矩阵乘法运算条件Input the method of getting data(1 is from file,2 is from inputting):1Input two names of the data file:data.txt data1.txtRead the first file successfully!Read the second file successfully!The first matrix is:1 2 121 3 93 1 -33 6 144 3 245 2 186 1 156 4 -7The second matrix is:1 1 31 4 52 2 -13 1 2The matrix multiply is illegal!测试5:输入数据完全正确Input the method of getting data(1 is from file,2 is from inputting):2Input the first matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 3 4Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 1 31 4 52 2 -13 1 2Input the second matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 4 2Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 2 22 1 13 1 -23 2 4The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 22 1 -13 2 4Input one name of the data file:data8.txt测试6:输入数据时有错误Input the method of getting data(1 is from file,2 is from inputting):2Input the first matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 3 4Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 1 31 4 52 2 -13 1 2Input the second matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 4 2Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 2 22 1 13 1 -23 3 4The data is wrong!Input again:3 2 4The first matrix is:1 4 52 2 -13 1 2The second matrix is:1 2 22 1 13 1 -23 2 4The result is:3 0 3 21 2 62 1 -13 2 4Input one name of the data file:data9.txt测试7:输入数据不满足矩阵相乘的条件Input the method of getting data(1 is from file,2 is from inputting):2Input the first matrix:With the order of a specified number of constant,specified constant and rows and columns number:4 0 3 4Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 1 31 4 52 2 -13 1 2Input the second matrix:With the order of a specified number of constant,specified constant and rows and columns number:8 0 6 7Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:1 2 121 3 93 1 -33 6 144 3 245 2 186 1 156 4 -7The first matrix is:1 1 31 4 52 2 -13 1 2The second matrix is:1 2 121 3 93 1 -33 6 144 3 245 2 186 1 156 4 -7The matrix multiply is illegal!9.源代码:----------------------------Makefile------------------------------- CC=gccCLFAGS=-g -Wall -O2 -lmOBJECTS=main.o getdata.o init.o matrixmulti.o print.o main:$(OBJECTS)$(CC) $(CLFAGS) -o $@ $^.c.o:$(CC) -c $<.PHONY:cleanclean:rm -f $(OBJECTS) main-------------------------------main.c------------------------------- /*---------------------------基本信息------------------------------- 作者:方金卫日期:2010年7月8日系统名称:稀疏矩阵乘法系统功能:稀疏矩阵的乘法-------------------------------------------------------------------*/ #include<stdio.h>#include"data.h"int main(void){SparseMatrix sparsematrix1;SparseMatrix sparsematrix2;SparseMatrix sparsematrix3;char filename1[32];char filename2[32];char filename3[32];int tag;int sign;printf("Input the method of getting data(1 is from file,2 is from inputting):"); scanf("%d",&tag);InitSparseMatrix(&sparsematrix1);InitSparseMatrix(&sparsematrix2);/*初始化*//*获取数据*/if(tag==1){printf("Input two names of the data file:");scanf("%s %s",filename1,filename2);sign=GetData(&sparsematrix1,filename1);if(sign==1)printf("Read the first file successfully!\n");if(sign==-1)return 0;sign=GetData(&sparsematrix2,filename2);if(sign==1)printf("Read the second file successfully!\n");if(sign==-1)return 0;if(tag==2){printf("Input the first matrix:\n");InputData(&sparsematrix1);printf("Input the second matrix:\n");InputData(&sparsematrix2);}/*输出稀疏矩阵*/printf("The first matrix is:\n");PrintMatrix(sparsematrix1);printf("The second matrix is:\n");PrintMatrix(sparsematrix1);sparsematrix3=MatrixMulti(sparsematrix1,sparsematrix2);/*稀疏矩阵的乘法运算*//*输出结果*/printf("The result is:\n");printf("%d %d %d %d\n",sparsematrix3.num,sparsematrix3.con,sparsematrix3.row,sp arsematrix3.col);PrintMatrix(sparsematrix3);/*输出到指定的文件中*/printf("Input one name of the data file:");scanf("%s",filename3);PrintToFile(sparsematrix3,filename3);return 1;}--------------------------------data.h------------------------------#ifndef DATA_H_#define DATA_H_#include<stdio.h>#include<stdlib.h>#define INT#ifdef FLOATtypedef float DataType;#endif#ifdef INTtypedef int DataType;#endif#define MAXSIZE 30#define INITMAX 65535typedef int Status;/*-----------------定义数据结构-----------------*//*定义数据节点:每个节点存放所在的行数与列数,以及该处的值*/ typedef struct DataNode{int row,col;/*该元素所在的行数和列数*/DataType data;}DataNode;/*数组的行列数*/typedef struct SparseMatrix{int num;/*非指定元素的个数*/int con;/*指定常数*/int row,col;/*矩阵的行数和列数*/DataNode *matrix;int *rpos;/*各行第一个非指定元素的位置表,若不含某行时其值为-1*/}SparseMatrix;/*-----------------一些基本操作-----------------*//*In the getdata.c file*/Status InputData(SparseMatrix *sparsematrix);/*人工输入数据*/Status GetData(SparseMatrix *sparsematrix,char filename[]);/*从指定的文件中获得数据*//*In the init.c file*/Status InitSparseMatrix(SparseMatrix *sparsematrix);/*初始化稀疏矩阵的数据*//*In the matrixmulti.c file*/SparseMatrix MatrixMulti(SparseMatrix sparsematrix1,SparseMatrix sparsematrix2);/*稀疏矩阵相乘*//*In the print.c file*/void PrintMatrix(SparseMatrix sparsematrix);/*输出系数矩阵里的值*/void PrintToFile(SparseMatrix sparsematrix,char filename[]);/*将矩阵输入指定的文件中*/#endif--------------------------------init.c------------------------------#include"data.h"/*初始化数据*/Status InitSparseMatrix(SparseMatrix *sparsematrix){int i;(*sparsematrix).num=0;(*sparsematrix).con=0;(*sparsematrix).row=0;(*sparsematrix).col=0;(*sparsematrix).matrix=(DataNode*)malloc(sizeof(DataNode));if(!(*sparsematrix).matrix){printf("Memory allocation failed in init.c!\n");exit(1);}(*sparsematrix).matrix=NULL;(*sparsematrix).rpos=(int *)malloc(sizeof(int));if(!(*sparsematrix).rpos){printf("Memory allocation failed in init.c!\n");exit(1);}(*sparsematrix).rpos=NULL;return 1;}-----------------------------getdata.c-------------------------------#include"data.h"/*-----------------------检验数据的合法性--------------------------*/Status IsRight(SparseMatrix sparsematrix,int i){if(sparsematrix.matrix[i].row>sparsematrix.row||sparsematrix.matrix[i].col>sparsemat rix.col){printf("The data is wrong!\n");return 0;}return 1;}/*---------------------从文件中读取数据-------------------------*/Status GetData(SparseMatrix *sparsematrix,char filename[]){FILE *fp;int i;int *count;/*辅助确定每行第一个元素的位置*/InitSparseMatrix(sparsematrix);if((fp=fopen(filename,"r+"))==NULL){printf("Can't open this file!\n");exit(1);}/*分别获得二维矩阵非指定常数的个数,指定常数,以及它的行数和列数*/ fscanf(fp,"%d%d%d%d",&(*sparsematrix).num,&(*sparsematrix).con,&(*sparsematr ix).row,&(*sparsematrix).col);(*sparsematrix).matrix=(DataNode*)malloc(((*sparsematrix).num+1)*sizeof(DataNo de));if(!(*sparsematrix).matrix){printf("Memory allocation failed in getdata.c!\n");exit(1);}(*sparsematrix).rpos=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!(*sparsematrix).rpos){printf("Memory allocation failed in getdata.c!\n");exit(1);}count=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!count){printf("Memory allocation failed in getdata.c!\n");exit(1);}for(i=0;i<=(*sparsematrix).row;++i)/*初始化数组*/{(*sparsematrix).rpos[i]=0;count[i]=0;}/*0号单元都不用*/for(i=1;i<=(*sparsematrix).num&&!feof(fp);++i){fscanf(fp,"%d",&(*sparsematrix).matrix[i].row);fscanf(fp,"%d",&(*sparsematrix).matrix[i].col);++count[(*sparsematrix).matrix[i].row];/*统计每行非零元素个数*/ #ifdef FLOATfscanf(fp,"%f",&(*sparsematrix).matrix[i].data);#endif#ifdef INTfscanf(fp,"%d",&(*sparsematrix).matrix[i].data);#endifwhile(IsRight(*sparsematrix,i)==0)/*检验数据的合法性*/{if(i==1)printf("The first data is wrong!\n");else if(i==2)printf("The second data is wrong!\n");else if(i==3)printf("The third data is wrong!\n");elseprintf("The %dth data is wrong!\n",i);printf("Please check it carefully,then input it again:\n");--count[(*sparsematrix).matrix[i].row];/*第row的非指定常数的个数减一*/scanf("%d",&(*sparsematrix).matrix[i].row);scanf("%d",&(*sparsematrix).matrix[i].col);++count[(*sparsematrix).matrix[i].row];/*统计每行非零元素个数*/ #ifdef FLOATscanf("%f",&(*sparsematrix).matrix[i].data);#endif#ifdef INTscanf("%d",&(*sparsematrix).matrix[i].data);#endif}}if(i!=(*sparsematrix).num+1){printf("Get data wrong!\n");return -1;}/*确定每行第一个非指定常数在rpos数组的位置*/for(i=1;i<=(*sparsematrix).row;++i){(*sparsematrix).rpos[i]=count[i-1]+1;count[i]+=count[i-1];}fclose(fp);return 1;}/*----------------------通过终端人工输入数据---------------------*/Status InputData(SparseMatrix *sparsematrix){int i;int *count;InitSparseMatrix(sparsematrix);printf("With the order of a specified number of constant,specified constant and rows and columns number:\n");scanf("%d %d %d %d",&(*sparsematrix).num,&(*sparsematrix).con,&(*sparsematri x).row,&(*sparsematrix).col);(*sparsematrix).matrix=(DataNode*)malloc(((*sparsematrix).num+1)*sizeof(DataNo de));if(!(*sparsematrix).matrix){printf("Memory allocation failed in getdata.c!\n");exit(1);}(*sparsematrix).rpos=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!(*sparsematrix).rpos){printf("Memory allocation failed in getdata.c!\n");exit(1);}count=(int *)malloc(((*sparsematrix).row+1)*sizeof(int));if(!count){printf("Memory allocation failed in getdata.c!\n");exit(1);}for(i=0;i<=(*sparsematrix).row;++i){(*sparsematrix).rpos[i]=0;count[i]=0;}printf("Enter each element of a two-dimensional arrays in the number of rows and columns and the location of the element value:\n");for(i=1;i<=(*sparsematrix).num;++i){scanf("%d",&(*sparsematrix).matrix[i].row);scanf("%d",&(*sparsematrix).matrix[i].col);++count[(*sparsematrix).matrix[i].row];/*统计每行非零元素个数*/#ifdef FLOATscanf("%f",&(*sparsematrix).matrix[i].data);#endif#ifdef INTscanf("%d",&(*sparsematrix).matrix[i].data);#endifif(IsRight(*sparsematrix,i)==0)/*检验数据的合法性*/{printf("Input again:");--i;}}/*确定每行第一个非指定常数在rpos数组的位置*/for(i=1;i<=(*sparsematrix).row;++i){(*sparsematrix).rpos[i]=count[i-1]+1;count[i]+=count[i-1];}return 1;}---------------------------matrixmulti.c-----------------------------#include"data.h"/*两个稀疏矩阵相乘*/SparseMatrix MatrixMulti(SparseMatrix sparsematrix1,SparseMatrix sparsematrix2) {SparseMatrix sparsematrix3;int arow,ccol,brow,temp,tp,temp1,temp2;DataType ctemp[MAXSIZE+1]={};int i;if(sparsematrix1.col!=sparsematrix2.row){printf("The matrix multiply is illegal!\n");exit(1);}InitSparseMatrix(&sparsematrix3);/*结果矩阵的初始化*/sparsematrix3.row=sparsematrix1.row;sparsematrix3.col=sparsematrix2.col;sparsematrix3.num=0;/*为数组rpos分配空间*/sparsematrix3.rpos=(int *)malloc(sparsematrix3.row*sizeof(int));if(!sparsematrix3.rpos){printf("Memory allocation failed!\n");exit(1) ;}sparsematrix3.matrix=(DataNode*)malloc(sparsematrix3.row*sparsematrix3.col*sizeof(DataNode));if(!sparsematrix3.matrix){printf("Memory allocation failed!\n");exit(1);}if(!sparsematrix3.rpos){printf("Memory allocation failed!\n");exit(1);}if(sparsematrix3.col>MAXSIZE){printf("The MAXSIZE is defined smaller,please define it again!\n");exit(1);}if(sparsematrix1.num*sparsematrix2.num!=0)/*非零矩阵*/ {for(arow=1;arow<=sparsematrix1.row;++arow)/*处理第一个矩阵的每一行*/{for(i=0;i<=MAXSIZE;++i) /*当前行各元素累加器清零*/ctemp[i]=0;sparsematrix3.rpos[arow]=sparsematrix3.num+1;/*统计每行第一个非指定元素的位置*/if(arow<sparsematrix1.row) tp=sparsematrix1.rpos[arow+1];else tp=sparsematrix1.num+1;for(temp=sparsematrix1.rpos[arow];temp<tp;++temp){/*对当前行中每一个非零元*/brow=sparsematrix1.matrix[temp].col;/*找到对应元在第二个矩阵对应的行号*/if(brow<sparsematrix2.row)temp1=sparsematrix2.rpos[brow+1];else temp1=sparsematrix2.num+1;for(temp2=sparsematrix2.rpos[brow];temp2<temp1;++temp2){ccol=sparsematrix2.matrix[temp2].col;/*乘积元素结果矩阵中的列号*/ctemp[ccol]+=sparsematrix1.matrix[temp].data*sparsematrix2.matrix[temp2].data;}}for(ccol=1;ccol<=sparsematrix3.col;++ccol)/*压缩存储该行所有非指定常数*/if(ctemp[ccol]){if(++sparsematrix3.num>MAXSIZE) return ;sparsematrix3.matrix[sparsematrix3.num].row=arow;sparsematrix3.matrix[sparsematrix3.num].col=ccol;sparsematrix3.matrix[sparsematrix3.num].data=ctemp[ccol];}}}return sparsematrix3;}-----------------------------print.c-----------------------------#include"data.h"/*输出稀疏矩阵*/void PrintMatrix(SparseMatrix sparsematrix){int i;if(sparsematrix.num==0){printf("The sparse matrix is empty!\n");return ;}for(i=1;i<=sparsematrix.num;++i){#ifdef FLOATprintf("%d %d %f\n",sparsematrix.matrix[i].row,sparsematrix.matrix[i].col,sparsematr ix.matrix[i].data);#endif#ifdef INTprintf("%d %d %d\n",sparsematrix.matrix[i].row,sparsematrix.matrix[i].col,sparsemat rix.matrix[i].data);#endif}}/*输出稀疏矩阵到指定的文件里*/void PrintToFile(SparseMatrix sparsematrix,char filename[]){FILE *fp;int i;if((fp=fopen(filename,"w"))==NULL){printf("Open this file errror!\n");return ;}fprintf(fp,"%d %d %d %d\n",sparsematrix.num,sparsematrix.con,sparsematrix.row,sp arsematrix.col);for(i=1;i<=sparsematrix.num;++i){fprintf(fp,"%d ",sparsematrix.matrix[i].row);fprintf(fp,"%d ",sparsematrix.matrix[i].col);fprintf(fp,"%d",sparsematrix.matrix[i].data);fprintf(fp,"\n");}fclose(fp);}10.总结:这个系统的主要功能是计算两个稀疏矩阵的乘法运算,本系统可以采用人工输入和读取文件获得数据,在运算的过程中对数据的合法性进行了检查,以及两个矩阵是否满足进行乘法运算的条件,这保证了系统的健壮性。