4.2 矩阵乘法的Strassen算法

news2024/11/8 23:50:00

1.伪代码以及用到的公式

2.代码

package collection;
​
public class StrassenMatrixMultiplication {
    public static int[][] multiply(int[][] a, int[][] b) {
        int n = a.length;
        int[][] result = new int[n][n];
​
        if (n == 1) {
            result[0][0] = a[0][0] * b[0][0];
        } else {
            int[][] a11 = new int[n / 2][n / 2];
            int[][] a12 = new int[n / 2][n / 2];
            int[][] a21 = new int[n / 2][n / 2];
            int[][] a22 = new int[n / 2][n / 2];
            int[][] b11 = new int[n / 2][n / 2];
            int[][] b12 = new int[n / 2][n / 2];
            int[][] b21 = new int[n / 2][n / 2];
            int[][] b22 = new int[n / 2][n / 2];
​
            // Divide matrices into sub-matrices of size n/2 x n/2
            divide(a, a11, 0, 0);
            divide(a, a12, 0, n / 2);
            divide(a, a21, n / 2, 0);
            divide(a, a22, n / 2, n / 2);
            divide(b, b11, 0, 0);
            divide(b, b12, 0, n / 2);
            divide(b, b21, n / 2, 0);
            divide(b, b22, n / 2, n / 2);
​
            // Calculate p1 to p7
            int[][] p1 = multiply(add(a11, a22), add(b11, b22));
            int[][] p2 = multiply(add(a21, a22), b11);
            int[][] p3 = multiply(a11, sub(b12, b22));
            int[][] p4 = multiply(a22, sub(b21, b11));
            int[][] p5 = multiply(add(a11, a12), b22);
            int[][] p6 = multiply(sub(a21, a11), add(b11, b12));
            int[][] p7 = multiply(sub(a12, a22), add(b21, b22));
​
            // Calculate sub-matrices of result matrix
            int[][] c11 = add(sub(add(p1, p4), p5), p7);
            int[][] c12 = add(p3, p5);
            int[][] c21 = add(p2, p4);
            int[][] c22 = add(sub(add(p1, p3), p2), p6);
​
            // Combine sub-matrices into result matrix
            combine(c11, result, 0, 0);
            combine(c12, result, 0, n / 2);
            combine(c21, result, n / 2, 0);
            combine(c22, result, n / 2, n / 2);
        }
        return result;
    }
​
    // Divide matrix into sub-matrices
    public static void divide(int[][] parent, int[][] child, int i, int j) {
        for (int m = 0, n = i; m < child.length; m++, n++) {
            for (int p = 0, q = j; p < child.length; p++, q++) {
                child[m][p] = parent[n][q];
            }
        }
    }
​
    // Combine sub-matrices into matrix
    public static void combine(int[][] child, int[][] parent, int i, int j) {
        for (int m = 0, n = i; m < child.length; m++, n++) {
            for (int p = 0, q = j; p < child.length; p++, q++) {
                parent[n][q] = child[m][p];
            }
        }
    }
​
    // Add two matrices
    public static int[][] add(int[][] a, int[][] b) {
        int n = a.length;
        int[][] result = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                result[i][j] = a[i][j] + b[i][j];
            }
        }
        return result;
    }
​
    // Subtract two matrices
    public static int[][] sub(int[][] a, int[][] b) {
        int n = a.length;
        int[][] result = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                result[i][j] = a[i][j] - b[i][j];
            }
        }
        return result;
    }
}
​
​
​
​

3.原理

  1. 如果 n = 1,则每个矩阵包含一个元素。执行单个标量乘法和单个标量加法,就像 MATRIX-Multiply-RECURSIVE 的第3行那样,计算 Θ (1)的时间,然后返回。否则,将输入矩阵 A、 B 和输出矩阵 C 划分为 n/2 × n/2子矩阵,如方程(4.2)所示。这一步通过索引计算 Θ (1)的时间,就像在 MATRIX-Multiply-RECURSIVE 中一样。

  2. 创建 n/2 × n/2矩阵 S~1~,S~2~,... ,S~10~,每个矩阵都是步骤1中两个子矩阵的和或差。建立并归零七个 n/2 × n/2矩阵 P~1~,P~2~,... ,P~7~的条目以保持七个 n/2 × n/2矩阵乘积。所有17个矩阵都可以在 Θ (n2)时间内创建并初始化 P~i~

  3. 使用步骤1中的子矩阵和步骤2中创建的矩阵 S1,S2,... ,S10,递归地计算7个矩阵乘积 P~1~,P~2~,... ,P~7~中的每一个,花费7T (n/2)的时间。

  4. 对结果矩阵 C 的四个子矩阵 C11,C12,C21,C22进行修正,通过加减各种 P~i~ 矩阵来实现,这需要 Θ (n2)的时间。

假定一旦矩阵规模从n变为1,就进行简单的标量乘法计算,正如SQUARE-MATRIX-MULTIPLY­RECURSIVE的第4行那样。当n>l时,步骤1、2和4共花费Θ(n2)时间,步骤3要求进行7次n/2Xn/2矩阵的乘法。因此,我们得到如下描述Strassen算法运行时间T(n)的递归式:

4.数学计算原理

步骤2,创建如下10个矩阵

10个矩阵:​

由于必须进行10次n/2Xn/2矩阵的加减法,因此,该步骤花费8(n^2^)时间。

步骤3,递归地计算7次n/2*n/2矩阵的乘法

步骤4,对步骤3创建的P;矩阵进行加减法运算,计算出C的4个n/2* n/2的子矩阵.

C11 = C11 + P5 + P4-P2 + P6.​

C​~12~​ = ​C​~12~​ + ​P​~1~​ + ​P​~2~​

C​~21~​ = ​C​~21~​ + ​P​~3~​ + ​P​~4~​

C22 = C22 + P5 + P1-P3-P7​​

5.疑问

1.为什么要使用P1 到p7

用加减法来降低乘法的次数

在 Strassen 算法中,使用了七个中间矩阵 P1 到 P7 来计算矩阵乘积,具体原因如下: 为了避免重复计算,需要将输入的两个矩阵分别拆分成四个小矩阵,然后将这些小矩阵用来计算中间矩阵 P1 到 P7。 中间矩阵 P1 到 P7 的计算方式是通过加减法来实现的,因此可以减少乘法的次数,从而减少计算量。 通过使用中间矩阵 P1 到 P7,可以将原来需要进行 8 次矩阵乘法的计算量减少到 7 次。 综上所述,使用中间矩阵 P1 到 P7 可以提高矩阵乘法的效率,减少计算量。

2.可以使用p1到p10吗

在 Strassen 算法中,使用中间矩阵 P1 到 P7 是该算法的核心思想之一,它们用于表示两个矩阵相乘的结果。通常情况下,使用七个中间矩阵是足够的,因为它们已经能够减少矩阵乘法的计算量,从而提高算法的效率。 虽然可以添加更多的中间矩阵,例如 P8、P9、P10 等,但是这样并不一定能够进一步提高算法的效率,反而可能会增加计算量和程序的复杂度。因此,使用七个中间矩阵 P1 到 P7 是 Strassen 算法的常规做法,也是较为有效的优化策略。

3.至于为什么c11,c12 是这样的表达式

在 Strassen 算法中,矩阵乘积的计算采用了递归的方式,将输入矩阵分解成多个子矩阵进行计算,最终将这些子矩阵合并得到矩阵乘积。

具体地说,对于两个 n×n 的矩阵 A 和 B,Strassen 算法将 A 和 B 分解成四个 n/2×n/2 的子矩阵,然后通过以下公式计算矩阵乘积 C = A × B:

C11 = P5 + P4 - P2 + P6
C12 = P1 + P2
C21 = P3 + P4
C22 = P5 + P1 - P3 - P7

其中,P1 到 P7 是中间矩阵,表示为:

P1 = A11 × (B12 - B22)
P2 = (A11 + A12) × B22
P3 = (A21 + A22) × B11
P4 = A22 × (B21 - B11)
P5 = (A11 + A22) × (B11 + B22)
P6 = (A12 - A22) × (B21 + B22)
P7 = (A11 - A21) × (B11 + B12)

在这个公式中,C11 表示乘积的左上角 n/2×n/2 的子矩阵,P5、P4、P2 和 P6 都是中间矩阵,它们通过加减法来计算 C11 的值。具体来说:

P5 表示 (A11 + A22) × (B11 + B22) 的结果,它包含 C11、C12、C21 和 C22 中的所有元素。 P4 表示 A22 × (B21 - B11) 的结果,它包含 C11 和 C21 中的所有元素。 P2 表示 (A11 + A12) × B22 的结果,它包含 C11 和 C12 中的所有元素。 P6 表示 (A12 - A22) × (B21 + B22) 的结果,它包含 C11 和 C21 中的所有元素。 因此,将这些中间矩阵相加减,可以得到 C11 的值。具体来说,C11 = P5 + P4 - P2 + P6。这个公式的含义是,将 P5、P4、P2 和 P6 中包含 C11 的部分相加减,可以得到 C11 的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/411242.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么是毫末智行成为了DriveGPT的破壁人?

作者 | 魏启扬 来源 | 洞见新研社 毫末智行有着天生的紧迫感。 很多科技公司一年才举办一次的品牌日活动&#xff0c;毫末智行硬是办成了一个季度一次&#xff0c;活动频次的提高&#xff0c;则意味着组织内部新陈代谢的提速&#xff0c;从研发到落地乃至运营&#xff0c;都要…

ChatGPT 这个风口,普通人怎么抓住?

最近在测试ChatGPT不同领域的变现玩法&#xff0c;有一些已经初见成效&#xff0c;接下来会慢慢分享出来。 今天先给大家分享一个&#xff0c;看完就能直接上手的暴力引流玩法。 所需工具&#xff1a; 1&#xff09;ChatGPT&#xff08;最好是plus版&#xff0c;需要保证快速…

一个开源的大型语言模型LLaMA论文简单解读,LLaMA: Open and Efficient Foundation Language Models

一个开源的大型语言模型LLaMA论文解读&#xff0c;LLaMA: Open and Efficient Foundation Language Models返回论文和资料目录 1.导读 LLaMA 是 Meta AI 发布的包含 7B、13B、33B 和 65B 四种参数规模的基础语言模型集合&#xff0c;LLaMA-13B 仅以 1/10 规模的参数在多数的 …

ASEMI代理AD8638ARJZ-REEL7原装ADI车规级AD8638ARJZ-REEL7

编辑&#xff1a;ll ASEMI代理AD8638ARJZ-REEL7原装ADI车规级AD8638ARJZ-REEL7 型号&#xff1a;AD8638ARJZ-REEL7 品牌&#xff1a;ADI /亚德诺 封装&#xff1a;SOT-23-5 批号&#xff1a;2023 安装类型&#xff1a;表面贴装型 引脚数量&#xff1a;5 类型&#xff1…

初谈 ChatGPT

引子 最近&#xff0c;小编发现互联网中的大 V 突然都在用 ChatGPT 做宣传&#xff1a;“ChatGPT不会淘汰你&#xff0c;能驾驭ChatGPT的人会淘汰你”、“带领一小部分人先驾驭ChatGPT”。 确实&#xff0c;ChatGPT这个新生事物&#xff0c;如今被视为蒸汽机、电脑、iPhone 般的…

【ChatGPT 】国内无需注册 openai 即可访问 ChatGPT:ChatGPT Sidebar 浏览器扩展程序的安装与使用

一、前言 问题&#xff1a;国内注册 openai 账号麻烦&#xff0c;新必应有部分人也无法登录成功&#xff0c;存在域名单点登录失败等问题&#xff0c;所以无法真正使用 ChatGPT 解决&#xff1a;大部分人仅需使用 ChatGPT 的搜索功能&#xff0c;无需真正对话&#xff0c;需要…

云计算技术的现状和未来发展趋势分析

近年来&#xff0c;随着互联网、物联网、大数据等技术的不断发展&#xff0c;云计算技术也随之崛起并迅速发展。云计算技术作为一种新的计算模式&#xff0c;不断地改变着我们的生活和工作方式&#xff0c;成为了当今IT产业的一股强大的力量。本文将详细探讨云计算技术的现状和…

第十天面试实战篇

目录 一、springboot的常用注解&#xff1f; 二、springmvc常用注解&#xff1f; 三、mysql的内连接和外连接有什么区别&#xff1f;比如有两张表&#xff1a;A和B内连接只返回两个表A和B的交集部分 四、redis分布式锁的缺点有哪些&#xff1f; 五、如何使用reddssion解决r…

多个渠道成功销售的秘诀速递

将您的电子商务业务扩展到多个渠道销售似乎是一项艰巨的任务吗&#xff1f;但如果有了正确的多渠道增长战略&#xff0c;这可能是实现快速增长的好方法。当然&#xff0c;您需要考虑借助一些工具与策略&#xff0c;而SaleSmartly&#xff08;ss客服&#xff09;可以为您提供。 …

Python做个猫狗识别系统,给人美心善的邻居

嗨害大家好鸭&#xff01;我是爱摸鱼的芝士❤ 宠物真的看着好治愈 谁不想有一只属于自己的乖乖宠物捏~ 这篇文章中我放弃了以往的model.fit()训练方法&#xff0c; 改用model.train_on_batch方法。 两种方法的比较&#xff1a; model.fit()&#xff1a;用起来十分简单&#…

【剧前爆米花--爪哇岛寻宝】java文件操作和io流

作者&#xff1a;困了电视剧 专栏&#xff1a;《JavaEE初阶》 文章分布&#xff1a;这是一篇关于文件操作的文件&#xff0c;介绍了文件读写以及相关对象的内容&#xff0c;希望对你有所帮助&#xff01; 目录 文件操作 文件路径 绝对路径 相对路径 File类 File类的构造方…

REDIS Hash 槽 与 一致性hash

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

Spring boot+Vue3博客平台:文章发布与编辑功能的技术实现

本文将详细介绍如何实现一个博客平台中的文章发布与编辑功能&#xff0c;包括前端的Vue组件设计和后端的Spring Boot接口实现。在阅读本文后&#xff0c;您将了解如何设计和实现高效、易用的文章发布与编辑功能。 一、发布文章 设计思路 在设计文章发布功能时&#xff0c;我们…

vscode中调试rust程序

文章目录一、vscode运行和调式rust程序二、常见问题1.rust: Request textDocument/formatting failed.2.cargo命令3.使用rust-gdb调试rust程序4.cargo build太慢一、vscode运行和调式rust程序 环境&#xff1a;在WSL&#xff08;ubuntu20.04&#xff09;中使用vscode &#xf…

数据技术嘉年华星光璀璨,云和恩墨全栈数据技术能力闪耀会场

导语 2023年4月7-8日&#xff0c;由中国DBA联盟&#xff08;ACDU&#xff09;和墨天轮社区联合主办的第十二届『数据技术嘉年华』&#xff08;DTC 2023&#xff09;在北京成功举办。云和恩墨作为大会的协办方和深度参与者&#xff0c;以6场演讲2大展台全面呈现公司的全栈数据技…

几何算法——4.交线(intersection curve)的表达与参数化、微分性质

几何算法——4.曲面求交的交线&#xff08;intersection curve&#xff09;的表达与参数化、微分性质1 关于曲面求交的交线表达2 交线的微分性质3 交线的参数化4 修正弦长参数化的微分性质1 关于曲面求交的交线表达 两个曲面求交&#xff0c;比较经典的方法是用跟踪法&#xf…

wsl使用vscode搭建自己的MySQL

装wsl装MySQL装wsl 我已经装好了,就不说了 装MySQL 安装 MySQL 服务器&#xff1a;终端命令行输入sudo apt install mysql-server 安装完成后&#xff0c;MySQL 服务器会自动启动并在 Ubuntu 启动时启动。您可以使用以下命令检查 MySQL 服务器是否正在运行&#xff1a;sudo ser…

【三十天精通Vue 3】第六天 Vue 3 计算属性和监听器详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录引言一、Vue 3 计算属性概述1.1 计算属性的简介1.2 计算属性的分类…

第二十章 案例TodoList之动态数据

我们之前已经实现了静态的组件拆分&#xff0c;既然是静态说明数据就是死的&#xff0c;显然这不是我们需要的结果&#xff0c;之前我们学习了React组件&#xff0c;知道组件里面的状态数据驱动了页面的显示&#xff0c;每个组件都有属于自己的状态数据。接下来我们改造组件使得…

SAR ADC系列25:作业和上机实践

作业&#xff1a; 异步SAR逻辑中VALID信号如何产生&#xff1f;答&#xff1a;OUTP和OUTN与非。单纯通过减小“比较器环路”的延时(t1t22*t32*t4)的方式来提升ADC的转换速率可行吗&#xff1f;为什么&#xff1f;答&#xff1a;不可行&#xff0c;还要考虑CDAC建立的速度&…