IGraph使用实例——线性代数计算(blas)

 1 概述

在图论中,BLAS(Basic Linear Algebra Subprograms)并不直接应用于图论的计算,而是作为一套线性代数计算中通用的基本运算操作函数集合,用于进行向量和矩阵的基本运算。然而,这些基本运算在图论的相关计算中可能会被用到,尤其是涉及到矩阵运算的时候。

BLAS主要包含以下三个级别的函数:

  1. Level 1 BLAS函数
    • 处理单一向量的线性运算,如向量的加、减、数乘等。
    • 处理两个向量的二元运算,如点积、向量外积等。
  2. Level 2 BLAS函数
    • 处理矩阵与向量的运算,如矩阵与向量的乘积、矩阵的秩1更新等。
    • 包含线性方程求解计算,如使用高斯消元法解线性方程组。
  3. 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)库的函数,用于执行线性代数操作,如矩阵-向量乘法、矩阵-矩阵乘法、向量的欧几里得范数计算和向量的点积。

文件中定义了几个函数,每个函数都与特定的线性代数操作相关:

  1. igraph_blas_dgemv:执行矩阵-向量乘法,使用BLAS库中的dgemv函数。它支持矩阵的转置操作,并允许用户指定alpha和beta系数。

  2. igraph_blas_dgemm:执行矩阵-矩阵乘法,使用BLAS库中的dgemm函数。它同样支持矩阵的转置操作,并允许用户指定alpha和beta系数。

  3. igraph_blas_dgemv_array:与igraph_blas_dgemv类似,但是它接受C语言数组作为输入,而不是IGraph库中的向量对象。

  4. igraph_blas_dnrm2:计算向量的欧几里得范数,使用BLAS库中的dnrm2函数。

  5. igraph_blas_ddot:计算两个向量的点积,使用BLAS库中的ddot函数。

3.1 示例1

 在下列代码中使用了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;  
}

3.2 示例2

 以下代码使用BLAS(Basic Linear Algebra Subprograms)库中的dgemm(Double-precision General Matrix Multiply)函数来执行两个矩阵的乘法,并将结果存储在第三个矩阵中。

// 引入igraph库的头文件  
#include <igraph.h>  
  
int main(void) {  
    // 声明三个igraph_matrix_t类型的变量a, b, c,用于存储矩阵  
    igraph_matrix_t a, b, c;  
  
    // 初始化一个2x2的矩阵a,并为其分配内存  
    igraph_matrix_init(&a, 2, 2);  
    // 设置矩阵a的元素  
    MATRIX(a, 0, 0) = 1;  // a[0][0] = 1  
    MATRIX(a, 0, 1) = 2;  // a[0][1] = 2  
    MATRIX(a, 1, 0) = 3;  // a[1][0] = 3  
    MATRIX(a, 1, 1) = 4;  // a[1][1] = 4  
  
    // 初始化一个2x2的矩阵b,并为其分配内存  
    igraph_matrix_init(&b, 2, 2);  
    // 设置矩阵b的元素  
    MATRIX(b, 0, 0) = 5;  // b[0][0] = 5  
    MATRIX(b, 0, 1) = 6;  // b[0][1] = 6  
    MATRIX(b, 1, 0) = 7;  // b[1][0] = 7  
    MATRIX(b, 1, 1) = 8;  // b[1][1] = 8  
  
    // 初始化一个2x2的矩阵c,用于存储a和b的乘法结果  
    igraph_matrix_init(&c, 2, 2);  
  
    // 使用igraph_blas_dgemm函数计算a和b的乘积,并将结果乘以0.5后存储在c中  
    // 第一个和第二个参数分别是矩阵a和b的alpha(这里是1,即不缩放)  
    // 第三个参数是缩放因子(这里是0.5)  
    // 第四和第五个参数是矩阵a和b的指针  
    // 第六个参数是矩阵c的beta(这里是0,即不使用c的原始值)  
    // 第七个参数是结果矩阵c的指针  
    igraph_blas_dgemm(1, 1, 0.5, &a, &b, 0, &c);  
  
    // 打印矩阵c的内容  
    igraph_matrix_printf(&c, "%g");  
  
    // 释放矩阵a, b, c所占用的内存  
    igraph_matrix_destroy(&a);  
    igraph_matrix_destroy(&b);  
    igraph_matrix_destroy(&c);  
  
    // 程序正常退出  
    return 0;  
}

4 运行结果

4.1 结果1

首先,我们初始化了几个向量xyz和一个矩阵m。然后为矩阵m赋值了一个4x3的矩阵。

在第一个igraph_blas_dgemv函数调用中,我们试图计算2 * m * x + 3 * y并将结果存储在y中。但是,请注意,由于igraph_blas_dgemv的默认操作是y = alpha * A * x + beta * y(其中A是矩阵,xy是向量,alphabeta是标量),因此,实际上是在更新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来计算xx的点积(即x.x),以及xz的点积(即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

4.2 结果2 

根据矩阵乘法的定义和给定的代码,矩阵ab的乘积再乘以0.5会得到矩阵c,其元素计算如下:

a = [1 2; 3 4]

b = [5 6; 7 8]

c = 0.5 * (a * b)

矩阵乘法a * b的结果为:

[1*5 + 2*7 1*6 + 2*8; 3*5 + 4*7 3*6 + 4*8] = [1 + 14 6 + 16; 15 + 28 18 + 32] = [15 22; 43 50]

然后,我们将这个结果乘以0.5得到矩阵c

c = [15*0.5 22*0.5; 43*0.5 50*0.5] = [7.5 11; 21.5 25]

最后程序执行结果如下:

11.5 15.5

17 23

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/684731.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度神经网络——什么是扩散模型?

1. 概述 在人工智能的浩瀚领域中&#xff0c;扩散模型正成为技术创新的先锋&#xff0c;它们彻底改变了我们处理复杂问题的方式&#xff0c;特别是在生成式人工智能方面。这些模型基于高斯过程、方差分析、微分方程和序列生成等坚实的数学理论构建。 业界巨头如Nvidia、Google…

STM32(七):ADC电位检测 (标准库函数)

前言 上一篇文章已经介绍了如何用STM32单片机中的定时器的PWM波来实现LED的“呼吸”。这篇文章我们来介绍一下如何用STM32单片机中ADC进行电位检测&#xff0c;并发送到XCOM串口中显示。 一、实验原理 1.ADC模数转换的介绍 首先&#xff0c;我们先介绍一下AD模数模块&#…

驱动开发:内核扫描SSDT挂钩状态

100编程书屋_孔夫子旧书网 在笔者上一篇文章《驱动开发:内核实现SSDT挂钩与摘钩》中介绍了如何对SSDT函数进行Hook挂钩与摘钩的,本章将继续实现一个新功能,如何检测SSDT函数是否挂钩,要实现检测挂钩状态有两种方式,第一种方式则是类似于《驱动开发:摘除InlineHook内核钩…

免费,C++蓝桥杯等级考试真题--第11级(含答案解析和代码)

C蓝桥杯等级考试真题--第11级 答案&#xff1a;D 解析&#xff1a; A. a b; b a; 这种方式会导致a和b最终都等于b原来的值&#xff0c;因为a的原始值在被b覆盖前没有保存。 B. swap(a&#xff0c;b); 如果没有自定义swap函数或者没有包含相应的库&#xff0c;这个选项会编…

Mysql执行一条语句都有哪些操作

Mysql的执行流程 MySQL 的架构共分为两层&#xff1a;Server 层和存储引擎层&#xff0c; Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包括连接器&#xff0c;查询缓存、解析器、预处理器、优化器、执行器等。另外&#xf…

Linux——PXE_FTP_EL8

PXE Kickstart &#xff08; el8 &#xff09; 使用两个网口一个用net接口用于下载服务和软件包&#xff0c;另一个为仅主机用于与其他的空主机相连 PXE(preboot execute environment) 预启动执行环境。支持工作站通过网络从远端服务器下载映像&#xff0c;并由此支持通过网络启…

JavaWeb2-Vue

Vue 前端框架&#xff0c;免除原生JS中的DOM操作简化书写 &#xff08;以前学过又忘了&#xff0c;现在才知道原来vue是前端的&#xff09; 基于MVVM思想&#xff08;model-view -viewModel&#xff09;实现数据双向绑定 model是数据模型 view负责数据展示 即DOM 中间这个负责…

可视化表单生成器好用吗?

当前的社会竞争是非常大的&#xff0c;随着业务的上涨&#xff0c;很多客户都需要找到更高效、更理想的软件平台产品实现流程化办公。这就需要了解低代码技术平台了。作为新的办公助力软件平台&#xff0c;低代码技术平台更好操作、更灵活、功能更多&#xff0c;其中可视化表单…

生产管理看板系统为优化工厂车间生产工艺

一、行业现状&#xff0c;管理中普遍存在的问题 1. 先进的管理流程与相应管理制度匮乏。大量管理工作依旧主要采取“人治”模式&#xff0c;众多高层自身理论知识欠缺&#xff0c;并且还难以听取相关人员的意见。 2. 生产过程的控制较为薄弱。企业全面质量控制&#xff08;TQ…

LSP5526 直接替用 LSP5502 SOP-8降压直流转换器

LSP5526 作为一款高性能的降压型直流-直流转换器&#xff0c;在医疗设备中的应用非常广泛。由于其具有高效率、宽输入电压范围以及良好的稳定性等特点&#xff0c;它可以为医疗设备中的关键电子系统提供稳定的电源支持。以下是一些具体的医疗设备应用案例&#xff1a; 1. 医用监…

人大金仓数据库报sys_user表字段不存在的问题

目录 一.问题&#xff1a; 二.原因 三.解决方法&#xff1a; 一.问题&#xff1a; 公司的一个项目从oracle切换到人大金仓之后&#xff0c;突然报了一个sys_user里面的字段不存在。 二.原因 检查了很多次确信sys_user表没问题&#xff0c;查了相应的文档之后发现原来人大金…

笔记96:前馈控制 + 航向误差

1. 回顾 对于一个 系统而言&#xff0c;结构可以画作&#xff1a; 如果采用 这样的控制策略&#xff0c;结构可以画作&#xff1a;&#xff08;这就是LQR控制&#xff09; 使用LQR控制器&#xff0c;可以通过公式 和 构建一个完美的负反馈系统&#xff1b; a a 但是有上…

【C语言】指针(4)

一、回顾 在这之前&#xff0c;我们学习了很多关于指针的内容&#xff0c;我们先在这里简单的回顾一下。 1、一级指针 int* p; -- 整形指针-指向整形的指针 char* p; ... void* p;... ... 2、二级指针 int** p; char** p; ... 3、数组指针 -- 指向数组的指针 int (*p)[ ]…

采用_findfirst和_findnext获取当前文件夹下以及子文件夹下特定文件

1.相关知识点&#xff1a; 在实现此功能&#xff0c;主要使用到的函数包含&#xff0c;_findfirst()、_findnext()、_findclose()。通过使用上述函数以及配合结构体 _finddata_t 来达到一个遍历的效果。 _finddata_t的结构体信息 struct _finddata64i32_t {unsigned attrib…

Linux.小技巧快捷键

1. ctrl c 强制停止 终止某些程序的运行 也可以取消某行命令 2. ctrl d 退出或登出 进入python环境中&#xff0c;使用ctrl d 退出 3.history 查看历史使用了哪些命令 4. ! 历史最近使用的命令的开头 5.使用ctrl r 搜索历史使用的命令 按下 ctrl r 会进入 reverse -…

course-nlp——5-nn-imdb

本文参考自https://github.com/fastai/course-nlp。这部分是fastai1.0版本的教程&#xff0c;由于现在fastai2.0重构的改变非常大&#xff0c;所以文中的很多api都变了&#xff0c;由于学习目的并不是熟练掌握fastai&#xff0c;因此这里就简单的存一下&#xff0c;本文是用IMD…

2024-04-27 - AI for everyone - 第三周 - 吴恩达

摘要 2024-05-01 周三 杭州 阴 小记: (☆-v-) 2024-05-03 周四 杭州 🌤 小记: 这几天地铁好拥挤呀!不过体重已经减了 2 公斤 ,咔咔咔,继续坚持 2024-05-04 周四 杭州 🐟 小记: 因为在意,所以昨天有些事情超级不开心,但是我决定要彻底舍弃了,羁绊这种东西本就可…

探索数据结构:堆,计数,桶,基数排序的分析与模拟实现

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 堆排序 1.1. 算法思想 堆排序(Heap Sort)是一种基于堆数据结构的排…

R语言绘图 | 双Y轴截断图

教程原文&#xff1a;双Y轴截断图绘制教程 本期教程 本期教程&#xff0c;我们提供的原文的译文&#xff0c;若有需求请回复关键词&#xff1a;20240529 小杜的生信笔记&#xff0c;自2021年11月开始做的知识分享&#xff0c;主要内容是R语言绘图教程、转录组上游分析、转录组…

【kubernetes】探索k8s集群安全机制

目录 一、认证&#xff08;Authentication&#xff09; 1.1三种认证方式 1.2需要被认证的访问类型&#xff1a; 1.3安全性说明&#xff1a; 1.4证书颁发&#xff1a; 1.5kubeconfig 1.6Service Account 1.7Secret 与 SA 的关系 1.7.1Kubernetes 设计了一种资源对象叫做…