矩阵连乘积问题--动态规划

问题描述:
m×n矩阵A与n×p矩阵B相乘需耗费的时间。
方法分析:
我们把mnp作为两个矩阵相乘所需时间的测量值。
现在假定要计算三个矩阵A、B和C的乘积,有两种方式计算此乘积。

  • 先用A乘以B得到矩阵D,然后D乘以C得到最终结果,这种乘法的顺序为(AB)C;
  • 另一种乘法的顺序为A(BC)。

尽管这两种不同的计算顺序所得的结果相同,但时间消耗会有很大的差距。
在这里插入图片描述
因为矩阵乘法符合结合律,所以在计算ABC时,有两种方案,即(AB)C和A(BC)。

  • 对于第一方案(AB)C,计算:

在这里插入图片描述
其乘法运算次数为:2×3 ×2=12
在这里插入图片描述
其乘法运算次数为:2×2×4=16。
总计算量为:12+16=28

  • 对第二方案 A(BC),计算:
    在这里插入图片描述
    其乘法运算次数为:3×2×4=24
    在这里插入图片描述
    其乘法运算次数为:2×3×4=24。
    总计算量为:24+24=48
    可见,不同方案的乘法运算量可能相差很悬殊。
    定义:
    给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2,…n-1。考察这n个矩阵的连乘积A1A2…An。
  • 由于矩阵乘法满足结合律,所以计算矩阵的连乘可以有许多不同的计算次序。
  • 这种计算次序可以用加括号的方式来确定。
  • 若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积

完全加括号的矩阵连乘积可递归地定义为:
单个矩阵是完全加括号的;
矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)

  • 设有四个矩阵A, B, C, D,总共有五种完全加括号的方式:

(A((BC)D))
(A(B(CD)))
((AB)(CD))
(((AB)C)D)
((A(BC)D))

具体实例:
设有四个矩阵A, B, C, D,它们的维数分别是:
A=50×10, B=10×40, C=40×30, D=30×5
矩阵A和B可乘的条件: 矩阵A的列数等于矩阵B的行数。
设A是p×q的矩阵, B是q×r的矩阵, 乘积是p×r的矩阵;计算量是pqr
上述5种完全加括号方式的计算工作量为:
(A((BC)D)), (A(B(CD))), ((AB)(CD)), (((AB)C)D), ((A(BC)D))
16000, 10500, 36000, 87500, 34500
BC: 10×40×30 = 12000,
(BC)D: 10×30×5 = 1500,
(A((BC)D)): 50×10×5 = 2500
穷举法:
给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少?
穷举法:列举出所有可能的计算次序,并计算出每一种计算次序相应需要的数乘次数,从中找出一种数乘次数最少的计算次序。
算法复杂度分析:
对于n个矩阵的连乘积,设其不同的计算次序为P(n)。
由于每种加括号方式都可以分解为两个子矩阵的加括号问题:(A1…Ak)(Ak+1…An)可以得到关于P(n)的递推式如下:
在这里插入图片描述

分析最优解的结构:

将矩阵连乘积AiAi+1…Aj 简记为A[i:j], 这里i≤j;
考察计算A[1:n]的最优计算次序。
设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开,1≤k<n,则其相应完全加括号方式为(A1A2…Ak)(Ak+1Ak+2…An)
计算量:A[1:k]的计算量加上A[k+1:n]的计算量,再加上A[1:k]和A[k+1:n]相乘的计算量。
特征:
计算A[1:n]的最优次序所包含的计算矩阵子链 A[1:k]和A[k+1:n]的次序也是最优的。

  • 矩阵连乘计算次序问题的最优解包含着其子问题的最优解。
  • 这种性质称为最优子结构性质。
  • 问题的最优子结构性质是该问题可用动态规划算法求解的显著特征。

建立递归关系:

  • 设计算A[i: j],1≤i≤j≤n,所需要的最少数乘次数m[i, j],则原问题的最优值为m[1,n]

  • 当i=j时,A[i: j]=Ai,因此,m[i, i]=0,i=1,2,…,n

  • 当i<j 时,

在这里插入图片描述

  • 这里Ai的维数是Pi-1×Pi

在这里插入图片描述
m[i][j]给出了最优值,最优断开位置为k:

在这里插入图片描述

若将对应于m[i, j]的断开位置k记为s[i, j],在计算出最优值m[i, j]后,可递归的由s[i, j]构造出相应的最优解。

计算最优值:

  • 对于1≤i≤j≤n不同的有序对(i, j)对应于不同的子问题。因此,不同子问题的个数最多只有

在这里插入图片描述

  • 在递归计算时,许多子问题被重复计算多次。
  • 这也是该问题可用动态规划算法求解的又一显著特征。
  • 用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。
  • 在计算过程中,保存已解决的子问题答案。
  • 每个子问题只计算一次,在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法。

计算矩阵连乘积的动态规划算法:

#define NUM 51
int p[NUM];
int m[NUM][NUM];
int s[NUM][NUM];
void MatrixChain (int n)
{
  for (int i=1;  i<=n;  i++) m[i][i] = 0;
  for (int r=2;  r<=n;  r++)
	for (int i=1;  i<=n-r+1;  i++) 
	{
	  int j=i+r-1; 
	  //计算初值,从i处断开
	  m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
	  s[i][j] = i; 
	  for (int k=i+1;  k<j;  k++) 
	  { 
		int t = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
		if (t < m[i][j]) {m[i][j] = t; s[i][j] = k;}
	  }
	}
}

在这里插入图片描述
在这里插入图片描述
计算顺序
在这里插入图片描述
举例:
在这里插入图片描述
在这里插入图片描述
依据其递归式以自底向上的方式进行计算。
在计算过程中 , 保存已解决的子问题答案。
每个子问题只计算一次 , 而在后面需要时只要简单查一下 ,从而避免大量的重复计算, 最终得到多项式时间的算法。
算法复杂度分析:
算法matrixChain的主要计算量取决于算法中对r,i和k的3重循环。

  • 循环体内的计算量为O(1)。
  • 3重循环的总次数为O(n3)。

因此算法的计算时间上界为O(n3)。
算法所占用的空间显然为O(n2)。

计算矩阵连乘积最优解的递归算法:

s[i][j]已经存储了构造最优解所需要的足够的信息。

  • 每个部分的最优加括号方式可以根据数组s的相应元素得出。
  • 照此递推下去,最终可以确定A[1:n]的最优完全加括号方式,即构造出问题的一个最优解。
void TraceBack(int i, int j) 
{ 
	if(i==j) printf("A%d", i);
	else 
	{
		printf("(");
		TraceBack(i,s[i][j]); 
		TraceBack(s[i][j]+1,j); 
		printf(")"); 
	}
}

计算矩阵连乘积的递归算法:

int Recurve(int i, int j)
{
  if (i == j) return 0;
  int u = Recurve(i, i)+Recurve(i+1,j)+p[i-1]*p[i]*p[j];
  s[i][j] = i;
  for (int k = i+1; k<j; k++) 
  {
	int t = Recurve(i, k) + Recurve(k+1,j)+p[i-1]*p[k]*p[j];
	if (t<u) { u = t; s[i][j] = k;}
  }
  m[i][j] = u;
  return u;
} 

有大量重复子问题
在这里插入图片描述

计算矩阵连乘积的备忘录算法

int LookupChai  (int i, int j)
{
  if (m[i][j]>0) return m[i][j];
  if (i==j) return 0;
  int u = LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
  s[i][j] = i;
  for (int k = i+1; k<j; k++) 
  {
	int t = LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
	if (t < u) { u = t; s[i][j] = k;}
  }
  m[i][j] = u;
  return u;
}
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值