1 概述
在图论中,BLAS(Basic Linear Algebra Subprograms)并不直接应用于图论的计算,而是作为一套线性代数计算中通用的基本运算操作函数集合,用于进行向量和矩阵的基本运算。然而,这些基本运算在图论的相关计算中可能会被用到,尤其是涉及到矩阵运算的时候。
BLAS主要包含以下三个级别的函数:
- Level 1 BLAS函数:
- 处理单一向量的线性运算,如向量的加、减、数乘等。
- 处理两个向量的二元运算,如点积、向量外积等。
- Level 2 BLAS函数:
- 处理矩阵与向量的运算,如矩阵与向量的乘积、矩阵的秩1更新等。
- 包含线性方程求解计算,如使用高斯消元法解线性方程组。
- Level 3 BLAS函数:
- 包含矩阵与矩阵的运算,如矩阵乘法、矩阵的三角分解等。
在图论中,如果涉及到矩阵表示的图(如邻接矩阵)、线性方程组的求解(如网络流问题中的势能法)或者特征值问题(如图的谱分析)等,就可能会使用到BLAS库中的函数。
2 运行环境
操作系统:win10 64位
编程语言:C/C++
编译平台:vs2019 x64 debug | release
igraph版本: 0.10.12
3 示例代码
在IGraph中的blas.c文件中提供了丰富的功能来处理图和网络数据结构。这个特定的文件包含了一些使用BLAS(Basic Linear Algebra Subprograms)库的函数,用于执行线性代数操作,如矩阵-向量乘法、矩阵-矩阵乘法、向量的欧几里得范数计算和向量的点积。
文件中定义了几个函数,每个函数都与特定的线性代数操作相关:
-
igraph_blas_dgemv
:执行矩阵-向量乘法,使用BLAS库中的dgemv
函数。它支持矩阵的转置操作,并允许用户指定alpha和beta系数。 -
igraph_blas_dgemm
:执行矩阵-矩阵乘法,使用BLAS库中的dgemm
函数。它同样支持矩阵的转置操作,并允许用户指定alpha和beta系数。 -
igraph_blas_dgemv_array
:与igraph_blas_dgemv
类似,但是它接受C语言数组作为输入,而不是IGraph库中的向量对象。 -
igraph_blas_dnrm2
:计算向量的欧几里得范数,使用BLAS库中的dnrm2
函数。 -
igraph_blas_ddot
:计算两个向量的点积,使用BLAS库中的ddot
函数。
在下列代码中使用了igraph
库,特别是它的线性代数部分(通过igraph_blas
函数集)来进行一些基本的矩阵和向量运算。
#include <igraph.h> // 引入igraph库的头文件 int main(void) { // 定义igraph的矩阵和向量对象 igraph_matrix_t m; igraph_vector_t x, y, z; igraph_real_t xz, xx; // 用于存储计算结果的两个实数变量 // 初始化向量x,包含3个元素,分别为1.0, 2.0, 3.0 igraph_vector_init_real(&x, 3, 1.0, 2.0, 3.0); // 初始化向量y,包含4个元素,分别为4.0, 5.0, 6.0, 7.0 // 注意:虽然y之后会被用于计算,但这里先初始化为一些值 igraph_vector_init_real(&y, 4, 4.0, 5.0, 6.0, 7.0); // 初始化向量z,包含3个元素,分别为-1.0, 0.0, 0.5 igraph_vector_init_real(&z, 3, -1.0, 0.0, 0.5); // 初始化一个4x3的矩阵m,并为其赋值 igraph_matrix_init(&m, 4, 3); // 填充矩阵m的元素 MATRIX(m, 0, 0) = 1;MATRIX(m, 0, 1) = 2;MATRIX(m, 0, 2) = 3;MATRIX(m, 1, 0) = 2;MATRIX(m, 1, 1) = 3;MATRIX(m, 1, 2) = 4;MATRIX(m, 2, 0) = 3;MATRIX(m, 2, 1) = 4;MATRIX(m, 2, 2) = 5;MATRIX(m, 3, 0) = 4;MATRIX(m, 3, 1) = 5;MATRIX(m, 3, 2) = 6;// 计算 2 * m.x + 3 * y,并将结果存储在y中 // 注意:这里的操作会改变y的内容 igraph_blas_dgemv(/* transpose= */ 0, /* alpha= */ 2, &m, &x, /* beta= */ 3, &y); // 打印向量y的新内容 igraph_vector_print(&y); // 计算向量x的模的平方(即x与自身的点积),存储在xx中 igraph_blas_ddot(&x, &x, &xx); // 计算向量x和z的点积,存储在xz中 igraph_blas_ddot(&x, &z, &xz); // 打印结果 printf("x.x = %g, x.z = %g\n", xx, xz); // 销毁之前创建的矩阵和向量对象,释放内存 igraph_matrix_destroy(&m); igraph_vector_destroy(&z); igraph_vector_destroy(&y); igraph_vector_destroy(&x); return 0;
}
4 运行结果
首先,我们初始化了几个向量x
, y
, z
和一个矩阵m
。然后为矩阵m
赋值了一个4x3的矩阵。
在第一个igraph_blas_dgemv
函数调用中,我们试图计算2 * m * x + 3 * y
并将结果存储在y
中。但是,请注意,由于igraph_blas_dgemv
的默认操作是y = alpha * A * x + beta * y
(其中A
是矩阵,x
和y
是向量,alpha
和beta
是标量),因此,实际上是在更新y
的值,而不是简单地计算结果。由于y
的初始值不为零,这会影响最终结果。
y
向量初始化为[4.0, 5.0, 6.0, 7.0]
。在调用igraph_blas_dgemv
后,y
将被更新为2 * m * x + 3 * y
。
矩阵m
与向量x
的乘法结果是一个4x1的向量,其值为[1*1 + 2*2 + 3*3, 2*1 + 3*2 + 4*3, 3*1 + 4*2 + 5*3, 4*1 + 5*2 + 6*3]
,即[14, 20, 26, 32]
。
然后,我们将这个结果与y
的初始值相加,并乘以相应的系数:
y[0]
变为2 * 14 + 3 * 4.0 = 28 + 12 = 40
y[1]
变为2 * 20 + 3 * 5.0 = 40 + 15 = 55
y[2]
变为2 * 26 + 3 * 6.0 = 52 + 18 = 70
y[3]
变为2 * 32 + 3 * 7.0 = 64 + 21 = 85
因此,y
向量的最终值是[40, 55, 70, 85]
。
接下来,我们使用igraph_blas_ddot
来计算x
与x
的点积(即x.x
),以及x
与z
的点积(即x.z
)。这些计算的结果是:
x.x
是[1.0, 2.0, 3.0]
与[1.0, 2.0, 3.0]
的点积,即1*1 + 2*2 + 3*3 = 14
x.z
是[1.0, 2.0, 3.0]
与[-1.0, 0.0, 0.5]
的点积,即1*(-1) + 2*0 + 3*0.5 = -1 + 1.5 = 0.5
因此输出x.x = 14, x.z = 0.5
。