笔记98:按列压缩矩阵 csc_matrix 的 “含义”

1. 如何按列压缩矩阵:


注:按列压缩(Compressed Sparse Column -- CSC),是一种使用三个特征数组就可以表示整个矩阵的方法;

标准二次规划问题
  • x:状态量
  • P:矩阵
  • q:向量
  • A:矩阵
  • l:向量(x 的最小边界取值限制)
  • u:向量(x 的最大边界取值限制)

解释:一般我们在求解二次规划问题的时候,需要将矩阵 P 和 A 传入求解器;但如果我们通过一个个指定矩阵 P 和 A 的每个元素的方式定义矩阵,这样的代码可太脑瘫了;因此我们可以使用按列压缩的方式来表示一个矩阵,这样我们只需要3个特征数组,就可以知道整个矩阵到底是什么样的;需要完整的矩阵 A 和 P 时,将这3个特征数组传入函数 csc_matrix() 就可以了;


如何使用3个特征数组表示一个矩阵:

矩阵:A=\begin{bmatrix} 1 & 0 &4 \\ 0& 0 &5 \\ 2& 3 &6 \end{bmatrix}

定义特征数组:

  • A_data:从左到右按列遍历矩阵 A,记录每一列中每一个非零元素的值
    • A_data = [ 1 , 2 , 3 , 4 , 5 , 6 ]
  • A_indices:从左到右按列遍历矩阵 A,记录每一列上的非零数字的行索引值
    • A_indices = [ 0 , 2 , 2 , 0 , 1 , 2 ]
  • A_indptr:从左到右按列遍历矩阵 A,截止到当前列(不含当前列)时已遍历到的非零元素的个数
    • A_indptr = [ 0 , 2 , 3 , 6 ]
    • 解释:在数组 A_indptr 的索引为0处,代表当前列为第0列,不含当前列已遍历到的非零元素数量为0;
    • 解释:数组 A_indptr 的索引为3处,表示当前列为第3列,代表矩阵 A 的所有列(0~2)都已遍历,非零元素元素个数为6;

注1:通过这三个特征数组就可以得到矩阵 A 原本的模样;将矩阵 A 按列压缩,意思就是得到矩阵 A 的这三个特征数组;
注2:除了按列压缩,还有按行压缩等等各种压缩方法,基本原理一致,在此不再赘述;


a

a

a

a

2. 如何通过三个特征数组恢复矩阵


有特征数组:

  • A_data = [ 1 , 2 , 3 , 4 , 5 , 6 ]
  • A_indices = [ 0 , 2 , 2 , 0 , 1 , 2 ]
  • A_indptr = [ 0 , 2 , 3 , 6 ]

通过数组 A_indptr = [ 0 , 2 , 3 , 6 ] 可知:

  • 矩阵 A 有3列
  • 第零列 2 个非零元素;第一列 3-2=1 个非零元素;第二列 6-3=3 个非零元素;
  • 可以将 A_indices = [ 0 , 2 | 2 | 0 , 1 , 2 ] 分割为三段,一段代表一列;

通过数组 A_indices = [ 0 , 2 | 2 | 0 , 1 , 2 ] 可知,非零元素位置为:

  • 第0列:(0 , 0)  (2 , 0)
  • 第1列:(2 , 1)
  • 第2列:(0 , 2)  (1 , 2)  (2 , 2)

通过数组 A_data = [ 1 , 2 , 3 , 4 , 5 , 6 ] 给这些位置赋值即可得到矩阵 A;


a

a

a

a

3. 关于函数 csc_matrix


函数作用:通过传入的三个数组,恢复稀疏矩阵 A 原有的样子;

注1:这个函数是我们自己定义的;这个函数是没有C++版本的,只有Python版本,但是我们可以借助C++的 Eigen 库自己定义这个函数;

注2:我在使用 MPC 控制器控制车辆的运动时,建立了一个二次规划模型,需要使用 OSQP 库进行求解;

>>> indptr = np.array([0, 2, 3, 6])
>>> indices = np.array([0, 2, 2, 0, 1, 2])
>>> data = np.array([1, 2, 3, 4, 5, 6])
>>> csc_matrix((data, indices, indptr), shape=(3, 3)).toarray()
array([[1, 0, 4],
       [0, 0, 5],
       [2, 3, 6]])

参考文章:

  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
稀疏矩阵CSC(Compressed Sparse Column)存储方式是一种压缩列存储方式,它将所有的非零元素按列压缩存储,每一列的非零元素都存储在一个连续的数组中,同时记录每一列的非零元素在该列中的起始位置和终止位置。 具体地,CSC格式包含三个数组:data、indices和indptr。 - data:是一个一维数组,存储所有的非零元素,按列压缩存储,从左到右,从上到下,每列的非零元素按行顺序存储; - indices:是一个一维数组,存储所有非零元素的行索引,按列压缩存储,从左到右,从上到下,每列的非零元素按行顺序存储; - indptr:是一个一维数组,存储每一列的第一个非零元素在data和indices中的位置,以及最后一个非零元素的下一个位置,也就是说,indptr[k+1]-indptr[k]就是第k列的非零元素个数。 以一个例子来说明CSC格式的存储方式。给定一个3×3的矩阵: ``` 1 0 0 0 0 2 0 3 0 ``` 将其用CSC格式存储,得到以下三个数组: ``` data = [1, 3, 2] indices = [0, 2, 1] indptr = [0, 1, 3, 3] ``` 其中,data、indices和indptr分别表示非零元素的值、行索引和列指针。例如,data中的第一个元素1表示第一列的第一个非零元素的值,indices中的第一个元素0表示第一列的第一个非零元素在原矩阵中的行索引,indptr中的第一个元素0表示第一列的第一个非零元素在data和indices中的起始位置,最后一个元素3表示最后一列的最后一个非零元素的下一个位置。 CSC格式的存储方式在矩阵乘法和其他矩阵运算中具有很好的性质,例如,可以高效地进行矩阵乘法、矩阵转置、矩阵向量乘法等运算。同时,CSC格式也是SciPy中的稀疏矩阵存储和计算的默认格式之一,对于大规模矩阵的处理具有非常重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值