IGraph使用实例——线性代数计算(blas)
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函数。
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

首先,我们初始化了几个向量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 = 40y[1]变为2 * 20 + 3 * 5.0 = 40 + 15 = 55y[2]变为2 * 26 + 3 * 6.0 = 52 + 18 = 70y[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 = 14x.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 
根据矩阵乘法的定义和给定的代码,矩阵a和b的乘积再乘以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
相关文章:
IGraph使用实例——线性代数计算(blas)
1 概述 在图论中,BLAS(Basic Linear Algebra Subprograms)并不直接应用于图论的计算,而是作为一套线性代数计算中通用的基本运算操作函数集合,用于进行向量和矩阵的基本运算。然而,这些基本运算在图论的相…...
【MySQL】(基础篇五) —— 排序检索数据
排序检索数据 本章将讲授如何使用SELECT语句的ORDER BY子句,根据需要排序检索出的数据。 排序数据 还是使用上一节中的例子,查询employees表中的last_name字段 SELECT last_name FROM employees;输出结果: 发现其输出并没有特定的顺序。其实…...
C++ C_style string overview and basic Input funcitons
write in advance 最近在做题,遇到一个简单的将console的输入输出到文件中的简单题目,没有写出来。悔恨当初没有踏实地总结string 相关的 I/O 以及与文件的操作。这篇文章旨在记录基础的字符I/O, 简单常用的文件I/O操作函数。 当然,你会说C…...
VS2022+Qt雕刻机单片机马达串口上位机控制系统
程序示例精选 VS2022Qt雕刻机单片机马达串口上位机控制系统 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《VS2022Qt雕刻机单片机马达串口上位机控制系统》编写代码,代码整洁&a…...
Android Ble低功耗蓝牙开发
一、新建项目 在Android Studio中新建一个项目,如下图所示: 选择No Activity,然后点击Next 点击Finish,完成项目创建。 1、配置build.gradle 在android{}闭包中添加viewBinding,用于获取控件 buildFeatures {viewB…...
Visual Studio的快捷按键
Visual Studio的快捷按键对于提高编程效率至关重要。以下是一些常用的Visual Studio快捷按键,并按照功能进行分类和归纳: 1. 文件操作 Ctrl O:打开文件Ctrl S:保存文件Ctrl Shift S:全部保存Ctrl N:…...
【WEB系列】过滤器Filter
Filter,过滤器,属于Servlet规范,并不是Spring独有的。其作用从命名上也可以看出一二,拦截一个请求,做一些业务逻辑操作,然后可以决定请求是否可以继续往下分发,落到其他的Filter或者对应的Servl…...
[书生·浦语大模型实战营]——LMDeploy 量化部署 LLM 实践
1.基础作业 1.1配置 LMDeploy 运行环境 创建开发机 创建新的开发机,选择镜像Cuda12.2-conda;选择10% A100*1GPU;点击“立即创建”。注意请不要选择Cuda11.7-conda的镜像,新版本的lmdeploy会出现兼容性问题。其他和之前一样&…...
TiDB-从0到1-配置篇
TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCCTiDB-从0到1-部署篇TiDB-从0到1-配置篇 一、系统配置 TiDB的配置分为系统配置和集群配置两种。 其中系统配置对应TiDB Server(不包含TiKV和PD的参数࿰…...
微信小程序按钮设计与交互:打造极致用户体验
微信小程序作为一种流行的应用形式,其界面设计和交互体验对于用户吸引力和留存率至关重要。其中,按钮作为用户与小程序进行交互的主要方式之一,其设计和实现直接影响到用户体验的质量。在本文中,我们将探讨微信小程序按钮的设计与…...
ES6中如何使用class和extends关键字实现继承?
在ES6中,可以使用class关键字来定义类,使用extends关键字来实现继承。下面是一个示例: // 父类 class Parent {constructor(name) {this.name name;}sayHello() {console.log(Hello, my name is ${this.name});} }// 子类 class Child ex…...
Linux:基本指令
文章目录 ls指令pwd指令cd指令touch指令mkdir指令rmdir指令 && rm指令cp指令man指令echo指令输出重定向追加重定向 cat指令输入重定向 mv指令which指令alias指令more && less指令head && tail指令事件相关的指令date显示时间戳 cal指令find指令grep指令…...
商业C++静态代码检测工具PC-lint Plus 、 polysace和sonarqube对比
商业C静态代码检测工具PC-lint Plus 、 polysace和sonarqube对比 特性/工具PC-lint PlusPolyspaceSonarQube主要功能高精度静态代码分析、编码标准检查高级静态分析和形式验证、优化嵌入式系统综合性代码质量管理、静态分析、技术债务管理集成方式可集成到IDE和构建系统与开发…...
邬家桥公园
文|随意的风 原文地址 我游览过现存规模最大、保存最完整的皇家园林颐和园,瞻仰过拥有世界上最大祭天建筑群的天坛公园,那都是多年前的事情了。 邬家桥公园相比颐和园、天坛公园,气势雄伟倒谈不上。它没有西湖的水平如镜ÿ…...
Flutter 中的 RenderObjectToWidgetAdapter 小部件:全面指南
Flutter 中的 RenderObjectToWidgetAdapter 小部件:全面指南 Flutter 是一个功能强大的 UI 框架,由 Google 开发,允许开发者使用 Dart 语言构建跨平台的移动、Web 和桌面应用。在 Flutter 的渲染体系中,RenderObjectToWidgetAdap…...
SNAT与DNAT
一、SNAT策略概述 1、SNAT 策略的典型应用环境 局域网主机共享单个公网IP地址接入Internet(私有IP不能在Internet中正常路由) 局域共享上网 2、 SNAT 策略的原理 修改数据包的源地址 把从内网 --> 外网的数据的源内网地址转换成公网源地址 3、SN…...
MySql八股文知识点总结,一篇文章让mysql成为面试加分项
MySql八股文知识点总结(自检) 1.前言 参与了几次中大厂的面试,你会发现一面时对于八股文的考察也具有侧重点(MySQLRedis > 网络 > 系统 >设计模式 > java集合 >spring) 本文的目标就是通过这一篇文章让你能在面…...
Python 很好用的爬虫框架:Scrapy:
了解Scrapy 爬虫框架的工作流程: 在scrapy中, 具体工作流程是这样的: 首先第一步 当爬虫引擎<engine>启动后, 引擎会到 spider 中获取 start_url<起始url> 然后将其封装为一个request对象, 交给调度器<…...
C/C++|关于 namespace 在C++中的代码组织
命名空间(namespace)在C中用于组织代码,避免命名冲突,并提供更好的代码结构和可读性。下面详细解释命名空间在C多文件编写中的各种作用和表达。 基本概念 命名空间是一个声明区域,用于组织代码,防止不同部…...
selenium自动化测试入门 —— 上传文件
selenium无法识别非web的控件,上传文件窗口为系统自带,无法识别窗口元素。 上传文件有两种场景:input控制上传和非input控件上传。 大多数情况都是input控件上传文件,只有非常少数的使用自定义的非input上传文件。 一、input控…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
