当前位置: 首页 > news >正文

用java实现矩阵链乘积_矩阵最优链乘及Java实现

矩阵最优链乘及Java实现

给一系列矩阵\(A_1,A_2,...A_n\)进行链乘,找出最优运算顺序

矩阵乘法

\(\begin{bmatrix}

{a_1,a_2}\\

{a_3,a_4}\\\end{bmatrix}*\begin{bmatrix}

{b_1,b_2}\\

{b_3,b_4}\\\end{bmatrix}=\begin{bmatrix}

{a_1*b_1+a_2*b_3,a_1*b_2+a_2*b_4}\\

{a_3*b_1+a_4*b_3,a_3*b_2+a_4*b_4}\\\end{bmatrix}\)

一个p行q列的矩阵乘以一个q行r列的矩阵最终得到一个p行r列的矩阵

新矩阵中第i行第j列的数字等于第一个矩阵的第i行数字和第二个矩阵第j列数字一一对应乘积的和

由此可以看出两矩阵相乘总共标量乘法运算数为pqr,这就是衡量的标准

矩阵乘法满足结合律

\((AB)C=A(BC)\)

运算顺序不同带来的差异

假设有三个矩阵A,B,C相乘

矩阵

A

B

C

维度

10*2

2*10

10*2

(AB)C代价

\(Cost(AB)=10*2*10\)

\(Cost((AB)C)=10*2*10+10*10*2=400\)

A(BC)代价

\(Cost(BC)=2*10*2\)

\(Cost(A(BC)=10*2*2+2*10*2=80\)

解决思路

最优方案的子方案也是最优方案

当一个链乘的方案最优,那么它的子方案也是最优

思路分解

n个矩阵链乘可以分解为三部分

0-k矩阵链乘

k+1-n矩阵链乘

前两者相乘

n个矩阵就可以分为n-1种分解情况

0-0矩阵链乘,1-n矩阵链乘

0-1矩阵链乘,2-n矩阵链乘

...

0-(n-1)矩阵链乘,(n-1)-n矩阵链乘

如果用m[i,j]表示第i到第j个矩阵相乘的代价

p[i]表示矩阵的维度(p[i]表示第i个矩阵的行数,p[i+1]表示第i个矩阵的列数)

\(m[i,j]=\begin{cases}

0,i=j\\

\min\{m[i,k]+m[k+1,j]+p_i*p_{k+1}*p_{j+1}\}\\

\end{cases}

\)

也就是说要求出m[i,j]必须要先求出m[i,k],m[k+1,j]

也就是说要求出n个矩阵链乘的最小代价,要先求出子链乘的代价

自底向上

我们可以从最小的子链乘开始计算最小代价

计算流程

所有单个矩阵链乘的最小代价(0)

所有两个矩阵链乘的最小代价

所有三个矩阵链乘的最小代价

...

所有n个矩阵链乘的最小代价

Java实现

数据结构

m

二维矩阵,存储最小代价和最优分解点

m(0,2)

m(1,2)

m(2,2)

m(0,1)

m(1,1)

m(2,1)

m(0,0)

m(1,0)

m(2,0)

\(m[i,j]=\begin{cases}

矩阵i到j链乘的最小代价,i\le j\\

矩阵j到i链乘最小代价的分解点 i>j\\

\end{cases}\)

p

p[i]表示矩阵的维度(p[i]表示第i个矩阵的行数,p[i+1]表示第i个矩阵的列数)

代码

/**

* @Date 2020/4/30

* @Author Redo

* @Description 矩阵链乘

**/

public class MCM {

//内容矩阵

private int[][] m;

//维数数组

private int[] p;

private int size;

/**

* 以维数为输入的构造

* @param p

*/

public MCM(int ...p){

this.p=p;

//维数数组元素个数较矩阵个数多1

this.size=p.length-1;

m=new int[size][size];

}

/**

* 设置分解点

* @param i 第i个矩阵

* @param j 链乘到第j个矩阵

* @param value 的最优分解点

*/

private void setSplit(int i, int j, int value){

m[j][i]=value;

}

/**

* 设置分解点

* @param i 第i个矩阵

* @param j 链乘到第j个矩阵

* @return 最优分解点

*/

private int getSplit(int i,int j){

return m[j][i];

}

/**

* 获取i到j的矩阵链乘分解点为k的最小代价

* @param start 起始位置

* @param k 分解点

* @param end 结束位置

* @return 以k为分解点的最小代价

*/

private int m(int start, int k,int end){

return m[start][k]+m[k+1][end]+p[start]*p[k+1]*p[end+1];

}

/**

* 获取i到j的矩阵链乘的最小代价

* @param start 起始位置

* @param end 结束位置

* @return 最小代价

*/

private int m(int start,int end){

if(start==end)

return 0;

else if(start+1==end){

//相邻的矩阵链乘设置分解点为第一个矩阵

setSplit(start,end,start);

return m(start,start,end);

}

else {

//设置为最大值,找出最小代价

int temp=Integer.MAX_VALUE;

for(int k=start;k

if(temp>m(start,k,end)){

temp=m(start,k,end);

setSplit(start,end,k);

}

}

return temp;

}

}

/**

* 计算所有最小代价和分解点

*/

private void cal(){

for(int i=1;i

for (int j=0;j+i

m[j][j+i]=m(j,j+i);

}

}

}

/**

* 返回 start到end的矩阵链乘的最优方案

* @param start 起始点

* @param end 结束点

* @return 最优方案

*/

private String subDisplay(int start,int end){

if(start==end)

return "A"+end;

else

return "("+subDisplay(start,m[end][start])+""+subDisplay(m[end][start]+1,end)+")";

}

/**

* 返回最优方案

* @return

*/

public String display(){

return subDisplay(0,p.length-2);

}

private int getMinCost(int start,int end){

return m[start][end];

}

/**

* 获取最小代价

* @return

*/

public int getMinCost(){

return m[0][size-1];

}

public static void main(String[] args) {

MCM mcm=new MCM(10,2,10,2);

mcm.cal();

System.out.println(mcm.display());

System.out.println("MinCost:"+mcm.getMinCost());

}

}

相关文章:

  • java泛型 语法_Java泛型中的? super T语法
  • java 模块化 组件化_关于模块化、组件化的理解
  • java isnull方法_Java 检查判断变量null(空值)的方法示例代码
  • java容器类的实现_java容器类总结——基于JDK1.8
  • MySQL实验7存储过程_存储过程 · MySQL5.7文档 · 看云
  • php mysql insert 默认_PHP MySQL Insert Into
  • 称重机 java_Java实现称重3次找到假球
  • triangle java_LeetCode Triangle Java版本
  • python用户重复输入_在Python中从用户输入中查找重复值
  • java类与类之间的类图_UML类图(Class Diagram)中类与类之间的关系及表示方式(转)
  • java按时间范围过滤_Java列表按日期过滤
  • java员工表代码_基于java+ssh员工考勤管理系统源代码
  • java返回指定json格式_java返回json格式数据
  • java字符型数据的长度_Java字符串创建和长度
  • java正则表达式笔记_java正则表达式笔记
  • 网络传输文件的问题
  • Go 语言编译器的 //go: 详解
  • Java 多线程编程之:notify 和 wait 用法
  • Java超时控制的实现
  • Linux Process Manage
  • spring security oauth2 password授权模式
  • SQLServer之创建数据库快照
  • 构建工具 - 收藏集 - 掘金
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 数据库巡检项
  • # 数论-逆元
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • ###项目技术发展史
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (编译到47%失败)to be deleted
  • (二)WCF的Binding模型
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (三)uboot源码分析
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (四)图像的%2线性拉伸
  • (五)c52学习之旅-静态数码管
  • (一)基于IDEA的JAVA基础1
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)大型网站的系统架构
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET 设计模式—适配器模式(Adapter Pattern)
  • .net 使用ajax控件后如何调用前端脚本
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .NET学习教程二——.net基础定义+VS常用设置
  • .net中的Queue和Stack
  • @RestControllerAdvice异常统一处理类失效原因
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [1]-基于图搜索的路径规划基础
  • [⑧ADRV902x]: Digital Pre-Distortion (DPD)学习笔记
  • [ABP实战开源项目]---ABP实时服务-通知系统.发布模式
  • [acwing周赛复盘] 第 94 场周赛20230311