python 分而治之(施特拉森矩阵乘法)

news2025/1/13 7:40:56

给定两个大小分别为 nxn 的方阵 A 和 B,求它们的乘法矩阵。 
朴素方法:以下是两个矩阵相乘的简单方法。

def multiply(A, B, C):
 
    for i in range(N):
     
        for j in range( N):
         
            C[i][j] = 0
            for k in range(N):
             
                C[i][j] += A[i][k]*B[k][j]
 
# this code is contributed by shivanisinghss2110 

上述方法的时间复杂度为O(N 3 )。 

分而治之 :
以下是两个方阵相乘的简单分而治之方法。 
1、将矩阵 A 和 B 分为 4 个大小为 N/2 x N/2 的子矩阵,如下图所示。 
2、递归计算以下值。 ae + bg、af + bh、ce + dg 和 cf + dh。 

执行:

# Python program to find the resultant 
# product matrix for a given pair of matrices
# using Divide and Conquer Approach
 
ROW_1 = 4
COL_1 = 4
ROW_2 = 4
COL_2 = 4
 
#Function to print the matrix
def printMat(a, r, c): 
    for i in range(r): 
        for j in range(c): 
            print(a[i][j], end = " ") 
        print() 
    print() 
 
#Function to print the matrix
def printt(display, matrix, start_row, start_column, end_row,end_column): 
    print(display + " =>\n")
    for i in range(start_row, end_row+1): 
        for j in range(start_column, end_column+1): 
            print(matrix[i][j], end=" ") 
        print() 
    print() 
 
#Function to add two matrices
def add_matrix(matrix_A, matrix_B, matrix_C, split_index): 
    for i in range(split_index): 
        for j in range(split_index): 
            matrix_C[i][j] = matrix_A[i][j] + matrix_B[i][j] 
 
#Function to initialize matrix with zeros
def initWithZeros(a, r, c): 
    for i in range(r): 
        for j in range(c): 
            a[i][j] = 0
 
#Function to multiply two matrices
def multiply_matrix(matrix_A, matrix_B): 
    col_1 = len(matrix_A[0]) 
    row_1 = len(matrix_A) 
    col_2 = len(matrix_B[0]) 
    row_2 = len(matrix_B) 
 
    if (col_1 != row_2): 
        print("\nError: The number of columns in Matrix A  must be equal to the number of rows in Matrix B\n") 
        return 0
 
    result_matrix_row = [0] * col_2
    result_matrix = [[0 for x in range(col_2)] for y in range(row_1)] 
 
    if (col_1 == 1): 
        result_matrix[0][0] = matrix_A[0][0] * matrix_B[0][0] 
 
    else: 
        split_index = col_1 // 2
 
        row_vector = [0] * split_index 
        result_matrix_00 = [[0 for x in range(split_index)] for y in range(split_index)] 
        result_matrix_01 = [[0 for x in range(split_index)] for y in range(split_index)] 
        result_matrix_10 = [[0 for x in range(split_index)] for y in range(split_index)] 
        result_matrix_11 = [[0 for x in range(split_index)] for y in range(split_index)] 
        a00 = [[0 for x in range(split_index)] for y in range(split_index)] 
        a01 = [[0 for x in range(split_index)] for y in range(split_index)] 
        a10 = [[0 for x in range(split_index)] for y in range(split_index)] 
        a11 = [[0 for x in range(split_index)] for y in range(split_index)] 
        b00 = [[0 for x in range(split_index)] for y in range(split_index)] 
        b01 = [[0 for x in range(split_index)] for y in range(split_index)] 
        b10 = [[0 for x in range(split_index)] for y in range(split_index)] 
        b11 = [[0 for x in range(split_index)] for y in range(split_index)] 
 
        for i in range(split_index): 
            for j in range(split_index): 
                a00[i][j] = matrix_A[i][j] 
                a01[i][j] = matrix_A[i][j + split_index] 
                a10[i][j] = matrix_A[split_index + i][j] 
                a11[i][j] = matrix_A[i + split_index][j + split_index] 
                b00[i][j] = matrix_B[i][j] 
                b01[i][j] = matrix_B[i][j + split_index] 
                b10[i][j] = matrix_B[split_index + i][j] 
                b11[i][j] = matrix_B[i + split_index][j + split_index] 
 
        add_matrix(multiply_matrix(a00, b00),multiply_matrix(a01, b10),result_matrix_00, split_index)
        add_matrix(multiply_matrix(a00, b01),multiply_matrix(a01, b11),result_matrix_01, split_index)
        add_matrix(multiply_matrix(a10, b00),multiply_matrix(a11, b10),result_matrix_10, split_index)
        add_matrix(multiply_matrix(a10, b01),multiply_matrix(a11, b11),result_matrix_11, split_index)
 
        for i in range(split_index): 
            for j in range(split_index): 
                result_matrix[i][j] = result_matrix_00[i][j] 
                result_matrix[i][j + split_index] = result_matrix_01[i][j] 
                result_matrix[split_index + i][j] = result_matrix_10[i][j] 
                result_matrix[i + split_index][j + split_index] = result_matrix_11[i][j] 
 
    return result_matrix 
 
# Driver Code 
matrix_A = [ [1, 1, 1, 1], 
            [2, 2, 2, 2], 
            [3, 3, 3, 3], 
            [2, 2, 2, 2] ] 
 
print("Array A =>") 
printMat(matrix_A,4,4) 
 
matrix_B = [ [1, 1, 1, 1], 
            [2, 2, 2, 2], 
            [3, 3, 3, 3], 
            [2, 2, 2, 2] ] 
 
print("Array B =>") 
printMat(matrix_B,4,4) 
 
result_matrix = multiply_matrix(matrix_A, matrix_B) 
 
print("Result Array =>")
printMat(result_matrix,4,4) 

输出
数组A =>
         1 1 1 1
         2 2 2 2
         3 3 3 3
         2 2 2 2


数组 B =>
         1 1 1 1
         2 2 2 2
         3 3 3 3
         2 2 2 2


结果数组=>
         8 8 8 8
        16 16 16 16
        24 24 24 24
        16 16 16 16
        
在上述方法中,我们对大小为 N/2 x N/2 的矩阵进行 8 次乘法和 4 次加法。两个矩阵相加需要 O(N 2 ) 时间。所以时间复杂度可以写成 

T(N) = 8T(N/2) + O(N 2 )  

根据马斯特定理,上述方法的时间复杂度为 O(N 3 )
不幸的是,这与上面的简单方法相同。

简单的分而治之也导致O(N 3 ),有更好的方法吗? 

        在上面的分而治之的方法中,高时间复杂度的主要成分是8次递归调用。Strassen 方法的思想是将递归调用次数减少到 7 次。Strassen 方法与上述简单的分而治之方法类似,该方法也将矩阵划分为大小为 N/2 x N/2 的子矩阵:如上图所示,但在Strassen方法中,结果的四个子矩阵是使用以下公式计算的。

Strassen 方法的时间复杂度

两个矩阵的加法和减法需要 O(N 2 ) 时间。所以时间复杂度可以写成 

T(N) = 7T(N/2) + O(N 2 )

根据马斯特定理,上述方法的时间复杂度为
O(N Log7 ) 大约为 O(N 2.8074 )

一般来说,由于以下原因,施特拉森方法在实际应用中并不优选。 

1、Strassen 方法中使用的常数很高,对于典型应用,Naive 方法效果更好。 
2、对于稀疏矩阵,有专门为其设计的更好的方法。 
3、递归中的子矩阵占用额外的空间。 
4、由于计算机对非整数值的运算精度有限,Strassen 算法中累积的误差比 Naive 方法中更大。

执行: 

# Version 3.6
 
import numpy as np
 
def split(matrix):
    """
    Splits a given matrix into quarters.
    Input: nxn matrix
    Output: tuple containing 4 n/2 x n/2 matrices corresponding to a, b, c, d
    """
    row, col = matrix.shape
    row2, col2 = row//2, col//2
    return matrix[:row2, :col2], matrix[:row2, col2:], matrix[row2:, :col2], matrix[row2:, col2:]
 
def strassen(x, y):
    """
    Computes matrix product by divide and conquer approach, recursively.
    Input: nxn matrices x and y
    Output: nxn matrix, product of x and y
    """
 
    # Base case when size of matrices is 1x1
    if len(x) == 1:
        return x * y
 
    # Splitting the matrices into quadrants. This will be done recursively
    # until the base case is reached.
    a, b, c, d = split(x)
    e, f, g, h = split(y)
 
    # Computing the 7 products, recursively (p1, p2...p7)
    p1 = strassen(a, f - h)  
    p2 = strassen(a + b, h)        
    p3 = strassen(c + d, e)        
    p4 = strassen(d, g - e)        
    p5 = strassen(a + d, e + h)        
    p6 = strassen(b - d, g + h)  
    p7 = strassen(a - c, e + f)  
 
    # Computing the values of the 4 quadrants of the final matrix c
    c11 = p5 + p4 - p2 + p6  
    c12 = p1 + p2           
    c21 = p3 + p4            
    c22 = p1 + p5 - p3 - p7  
 
    # Combining the 4 quadrants into a single matrix by stacking horizontally and vertically.
    c = np.vstack((np.hstack((c11, c12)), np.hstack((c21, c22)))) 
 
    return c 

输出
数组A =>
         1 1 1 1
         2 2 2 2
         3 3 3 3
         2 2 2 2


数组 B =>
         1 1 1 1
         2 2 2 2
         3 3 3 3
         2 2 2 2


结果数组=>
         8 8 8 8
        16 16 16 16
        24 24 24 24
        16 16 16 16 

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

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

相关文章

创建python字典的两种方法:直观与函数式

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、直观创建法:直接定义键值对 二、函数式创建法:使用内置函数dict…

Linux——进程与线程

进程与线程 前言一、Linux线程概念线程的优点线程的缺点线程异常线程用途 二、Linux进程VS线程进程和线程 三、Linux线程控制创建线程线程ID及进程地址空间布局线程终止线程等待分离线程 四、习题巩固请简述什么是LWP请简述LWP与pthread_create创建的线程之间的关系简述轻量级进…

【产品经理】如何培养对市场的洞察力

引言:        在最近频繁的产品管理职位面试中,我深刻体会到了作为产品经理需要的不仅仅是对市场和技术的敏锐洞察,更多的是在复杂多变的环境中,如何运用沟通、领导力和决策能力来引导产品从概念走向市场。这一系列博客将分享…

基于springboot+html的二手交易平台(附源码)

基于springboothtml的二手交易平台 介绍部分界面截图如下联系我 介绍 本系统是基于springboothtml的二手交易平台,数据库为mysql,可用于毕设或学习,附数据库 部分界面截图如下 联系我 VX:Zzllh_

深入解析力扣162题:寻找峰值(线性扫描与二分查找详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣! 推荐:数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航: LeetCode解锁100…

3D视觉技术|螺栓分拣测试

随着制造业自动化程度的不断提高,某大型汽配企业为提升生产效率、减少人力成本,提出了使用复合机器人完成螺栓分拣的需求。富唯智能通过采用复合机器人,结合3D工业相机和高性能控制器,实现螺栓的自动抓取,从而提升生产…

全网讲的最详细的Docker镜像分层存储原理

先说结论,容器镜像分层存储图示 欢迎关注 实验环境准备 当前实验docker版本24.0.7如下,当前docker版本使用overlay2机制存储镜像 Client: Docker Engine - CommunityVersion: 24.0.7API version: 1.43Go version: go1.20.10…

STM32电机驱动模块(L9110S)

一、L9110S简介 L9110S是一种常用的双通道H桥电机驱动器集成电路,用于控制直流电机的方向和速度。它可以同时控制两个电机,每个通道最大可输出800mA的电流。L9110S具有高效的电源管理和过流保护功能,可以保护电路免受电机反冲电流的损害。它…

springcloud第4季 springcloud-gateway网关predict案例场景

一 predict案例场景 1.1 说明 本博客所有案例操作,都在上篇博客的基础上进行: springcloud第4季 springcloud-gateway网关的功能作用_cloud gateway干嘛的-CSDN博客 1.2 案例前提准备 1. 启动zipkin服务 2.启动consul服务 3.启动3个应用服务 二 …

Python中别再用 ‘+‘ 拼接字符串了!

大家好,在 Python 编程中,我们常常需要对字符串进行拼接。你可能会自然地想到用 操作符将字符串连接起来,毕竟这看起来简单明了。 在 Python 中,字符串是不可变的数据类型,这意味着一旦字符串被创建,它就…

【游戏引擎】Unity脚本基础 开启游戏开发之旅

持续更新。。。。。。。。。。。。。。。 【游戏引擎】Unity脚本基础 Unity脚本基础C#语言简介C#基础 Unity脚本基础创建和附加脚本MonoBehaviour生命周期生命周期方法 示例脚本 Unity特有的API常用Unity API 实践示例:制作一个简单的移动脚本步骤1:创建…

完成商品SPU管理页面

文章目录 1.引入前端界面1.将前端界面放到commodity下2.创建菜单3.进入前端项目,使用npm添加依赖1.根目录下输入2.报错 chromedriver2.27.2的问题3.点击链接下载压缩包,然后使用下面的命令安装4.再次安装 pubsub-js 成功5.在main.js中引入这个组件 4.修改…

海外媒体发稿的关键步骤和投稿策略:如何撰写高质量的新闻稿?国外软文发布平台有哪些?

发布国外新闻稿件是一个涉及多步骤的过程,旨在确保您的新闻稿能够有效覆盖目标受众。以下是一些关键步骤和实用的技巧,帮助你实现海外媒体发稿。 1. 明确目标和受众 首先,明确您发布新闻稿的目标,是为了增加品牌曝光、推出新产品…

byzer sql 详细参考

数据加载 load excel load excel.tmp/upload/exceltest.xls where header"true" as hello_world; load csv load csv.tmp/upload/taxi_tour_table_train_simple.csv where delimiter"," and header "true" as taxi_tour_table_train_simple…

【JavaScript】文件下载

文件下载的消息格式 服务器只要在响应头中加入 Content-Disposition: attachment; filename"kxx" 即可触发浏览器的下载功能其中: attachment 表示附件,浏览器看到此字段,触发下载行为(不同的浏览器下载行为有所区别&…

[Linux]服务管理

一.服务的概念,状态,查看系统服务 服务(service)本质就是进程 如(mysqld,sshd 防火墙等) 是运行在后台的,通常都会监听某个端口,等待其它程序的请求 -------比如mysqld,防火墙等,因此我们又称为…

抖音运营_如何开抖店

截止20年8月,抖音的日活跃数高达6亿。 20年6月,上线抖店 (抖音官方电商) 一 抖店的定位和特色 1 一站式经营 帮助商家进行 商品交易、店铺管理、客户服务 等全链路的生意经营 2 多渠道拓展 抖音、今日头条、西瓜、抖音火山版…

Python爬取B站视频:封装一下

📚博客主页:knighthood2001 ✨公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下) 🎃知识星球:【认知up吧|成长|副业】介绍 ❤️如遇文章付费,可先看…

【Python】—— lambda表达式

目录 (一)应用场景 (二)lambda 语法 (三)示例分析 (四)lambda参数形式 4.1 无参数 4.2 一个参数 4.3 默认参数 4.4 可变参数 :*args 4.5 可变参数 :…

保存商品信息功能(VO)

文章目录 1.分析前端保存商品发布信息的json数据1.分析commoditylaunch.vue的submitSkus1.将后面的都注销,只保留查看数据的部分2.填写基本信息3.保存信息,得到json4.使用工具格式化一下 2.使用工具将json转为model3.根据业务修改vo,放到vo包…