矩阵连乘最优结合 动态规划求解

简介: 1.引言  多矩阵连乘 对于一般的矩阵乘法来说,如矩阵A(m,n)与矩阵B(n,p)相乘需要进行的加法次数为m*n*p次乘法。 由于矩阵乘法满足结合律,因此矩阵相乘的结合性,会影响整个计算表达式的乘法执行次数。

1.引言  多矩阵连乘

对于一般的矩阵乘法来说,如矩阵A(m,n)与矩阵B(n,p)相乘需要进行的加法次数为m*n*p次乘法。

由于矩阵乘法满足结合律,因此矩阵相乘的结合性,会影响整个计算表达式的乘法执行次数。

如下面的例子,其中A(10,5)、B(5,20)、C(20,3):

    (1) ((AB)C) 执行乘法次数为1300次

    (2) (A(BC)) 执行乘法次数为450次

2.求最优的矩阵结合表达式

(1)设矩阵连乘积AiAi+1…Aj简记为A[i:j],设最优计算次序在Ak和Ak+1之间断开,则加括号方式为:

    ((AiAi+1…Ak) (Ak+1…Aj) )

则依照这个次序,先计算A[i:k]和A[k+1:j]然后再将计算结果相乘,计算量是:

    A[i:k]的计算量+A[K+1:j]的计算量+它们两者相乘的计算量

这里的关键是:计算A[i:j]的最优次序所包含的两个子过程(计算A[i:k]和A[K+1:j])也是最优次序

(2)具体计算

  设计算A[i,j]需要的乘法次数记为m[i,j]。

    M[i,j] = 0;    (i == j,表示一个矩阵,当然不需要乘法运算)

    M[i,j] = min(M[i,k]+M[k+1,j]+pi*pk*pj);   (k在[i,j)之间取值,表示分割点的位置,求最适合的分割点使得乘法次数最少)

  下面是使用动态规划计算6个矩阵连乘的示意图。可以使用自底向上计算,这样矩阵的分割点好计算。如先计算01两个矩阵乘积,在计算02三个矩阵乘积,在计算03四个矩阵乘积:

       01 12 23 34 45

       02 13 24 35

       03 14 25

       04 15

       05

 3.程序实例

程序可以根据给出的多个矩阵的行、列,生成最优结合的相乘表达式。

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <limits.h>
 5 #include <string>
 6 using namespace std;
 7 ///计算M矩阵
 8 int calculate_M(vector<vector<int> >&num,vector<pair<int,int> > &data,vector<vector<int> > &points){
 9     int len = data.size();
10     for(int span = 1;span<len;span++){  ///间隔距离
11         for(int col=0;col<len-span;col++){  ///操作起始列
12 
13             for(int i=col;i<col+span;i++){
14                 int tmp = num[col][i] + num[i+1][col+span] + data[col].first*data[i].second*data[col+span].second;
15                 if(tmp < num[col][col+span]){
16                     points[col][col+span] = i;  ///记录分割点
17                     num[col][col+span] = tmp;   ///记录最少乘法次数
18                 }
19             }
20         }
21     }
22     return 0;
23 }
24 
25 ///根据记录的分割点,生成最后的矩阵相乘表达式
26 string make_result(vector<vector<int> > &points,int t1,int t2){
27     if(t1 == t2)
28         return string(1,'A'+t1);
29     int split = points[t1][t2];
30     return "("+make_result(points,t1,split)+"*"+make_result(points,split+1,t2)+")";
31 }
32 
33 int main()
34 {
35     vector<pair<int,int>> data; ///保存矩阵的行、列
36     data.push_back(make_pair(10,100));  //A
37     data.push_back(make_pair(100,5));   //B
38     data.push_back(make_pair(5,25));    //C
39     data.push_back(make_pair(25,15));   //D
40     data.push_back(make_pair(15,20));   //E
41 
42 
43     int len = data.size();
44     vector<vector<int> > num(len,vector<int>(len)); ///定义二维向量,并预先分配空间,记录乘法次数
45     vector<vector<int> > points(len,vector<int>(len)); ///定义二维向量,并预先分配空间,记录分割点
46     for(int i=0;i<len;i++){
47         for(int j=0;j<len;j++){
48             points[i][j] = -1;
49             if(i == j)
50                 num[i][j] = 0;  ///自己和自己相乘,所以为0
51             else
52                 num[i][j] = INT_MAX;    ///否则,记为最大整数值
53         }
54     }
55 
56     calculate_M(num,data,points);
57     cout<<make_result(points,0,len-1)<<"\t最少乘法次数为:"<<num[0][len-1]<<endl;
58     return 0;
59 }
View Code

输入矩阵,表示每个矩阵的行、列:

输出最优的结合表达式:

  

相关文章
|
存储 JSON API
小红书笔记评论数据接口(小红书 API 系列)
小红书凭借庞大的用户群体和丰富的内容生态,成为重要的数据来源。其笔记评论数据对企业了解市场需求、优化产品策略等具有极高价值。为高效、合法获取数据,可使用小红书笔记评论数据接口。该接口通过HTTP请求获取指定笔记的评论内容、时间、昵称等信息,返回JSON格式数据。开发者可利用Python的requests库发送GET请求并处理响应,实现批量收集评论数据,支持舆情监测、竞品分析等业务场景。
1761 5
|
人工智能 文字识别 数据挖掘
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
MarkItDown 是微软开源的多功能文档转换工具,支持将 PDF、PPT、Word、Excel、图像、音频等多种格式的文件转换为 Markdown 格式,具备 OCR 文字识别、语音转文字和元数据提取等功能。
4271 9
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
|
消息中间件 监控 NoSQL
Redis脑裂问题详解及解决方案
Redis脑裂问题是分布式系统中常见的复杂问题,合理配置Redis Sentinel、使用保护模式、采用分布式锁机制以及优化网络和客户端连接策略等措施,可以有效预防和解决脑裂问题。通过深入理解Redis脑裂问题的成因和影响,采取相应的解决方案,能够提高系统的可用性和数据一致性,保障Redis集群的稳定运行。希望本文能帮助你更好地理解和应对Redis脑裂问题。
1440 2
|
负载均衡 监控 算法
每个程序员都应该知道的 6 种负载均衡算法
每个程序员都应该知道的 6 种负载均衡算法
1711 2
|
存储 负载均衡 监控
redis 集群模式(redis cluster)介绍
redis 集群模式(redis cluster)介绍
|
存储 Java Unix
什么是线程?为什么需要线程?和进程的区别?
什么是线程?为什么需要线程?和进程的区别?
5211 0
|
SQL 缓存 算法
主从不一致解决方案 && 如何降低主从延迟
主从不一致解决方案 && 如何降低主从延迟
主从不一致解决方案 && 如何降低主从延迟
|
存储 SQL 关系型数据库
【MySQL进阶-10】深入理解redolog,undolog和binlog的底层原理
【MySQL进阶-10】深入理解redolog,undolog和binlog的底层原理
2159 0
|
算法 Oracle 关系型数据库
|
Android开发 应用服务中间件 开发工具
IntelliJ IDEA 创建Web项目(全教程)
说明:IntelliJ IDEA 版本为14.JDK 版本为1.7tomcat 版本为apache-tomcat-7.0.70 注:在创建过程中注意相关软件版本位数的问题。32位,64位的软件混搭会导致访问不成功的问题!!! 首先要理解一个基本问题:对比eclipse ,在IntelliJ IDEA中“new Project”相当于eclipse中的工作空间(Workspace),而“new Module”相当于eclipse中的工程(Project)。
4799 0