前几日在地铁上和好友讨论起MySQL数据库,由于MySQL数据库不支持复合类型变量,就想到能否用MySQL去实现一些算法呢。最近在学习MySql存储程序,昨天闲来无事,就动手写写吧,借此巩固一下存储过程的用法。

这次要用MySQL实现的算法是矩阵快速幂,并借此解决斐波那契数列问题,首先我们要简单普及一下基本知识。一,菲波那切数列。即我们熟知的兔子繁殖问题,菲波那切数列的数学表达式:F(n) = F(n-1)+F(n-2),(n>2,F(1)=F(2)=1);第n项为前两项之和。二,快速幂。顾名思义幂运算的快速实现,对于普通的a的b次幂运算,需要进行b次乘法运算,而快速幂只用log2(b)级别的次数就可以做到。至于算法原理这里就不再赘述。三,矩阵乘法运算。线性代数里面的知识。这里只使用公式表达一下。A(x,y)

= A(x,y)+B(x,z)*C(z,y);四,矩阵快速幂。其实就是对于矩阵A的b次幂,采用快速幂的原理实现而已。

好了,下面我们就开始用MySQL实现矩阵快速幂。但是迎面而来的问题是,MySQL不支持复合类型,而我们需要用二位数组来实现矩阵的表示,并进行乘法运算。想到这里,你恐怕感觉无法实现了,但是我们有一个变通的方案可用,我们可以用数据表去充当一维的数组,使用自增的id用来标识第几个元素。既然有了一维数组,那我们完全可以用一维数组去充当二维数组啊,只需对下标进行适当的转换就行了。下标id是用1开始递增的,所以转换规则可以这样表示

A(x,y)=A((x-1)*len+y),(len为数组维度的长度),将二维下标转换成一维下标。数据类型的问题已经解决,那我们就首先实现矩阵相乘。首先我们要做的就是创建三张表(matrix,matrix_a,matrix_b)用来存储数据,数据表结构如下:DROP TABLE IF EXISTS matrix;

CREATE TABLE matrix(

id INT(11) NOT NULL AUTO_INCREMENT,

val INT(11) DEFAULT NULL,

PRIMARY KEY (id)

);由于MySQL的函数不支持数据表的操作,我们只能借用存储过程来实现。把两个表名以字符串的形式传递进去,但是在存储过程中变量值又不能作为查询语句中的表名或者字段名,这是一个问题。还好MySQL提供的有一个替代方案,那就是动态查询,只需要编写好查询字符串,然后动态编译查询就行了。此时的存储过程代码如下:DROP PROCEDURE IF EXISTS p_multiply;

DELIMITER $$;

CREATE PROCEDURE p_multiply(IN matrix_a VARCHAR(16),IN matrix_b VARCHAR(16),IN lengths INT)

BEGIN

SET @sql_a = CONCAT('SELECT val INTO @temp_aa FROM ',matrix_a,' WHERE id=(?-1)*?+?');

SET @sql_b = CONCAT('SELECT val INTO @temp_bb FROM ',matrix_b,' WHERE id=(?-1)*?+?');

SET @len = lengths;

END;貌似MySQL动态查询功能不支持DECLARE声明的变量,只能使用用户自定义变量。接下来就是一个三层的循序进行矩阵乘法运算。在运算中,我们只需使用以上说过的转换规则,从matrix_a和matrix_b表示的表中去除所要的数据,然后相乘之后添加的matrix表相对性的位置上。以下就是完整的代码:DROP PROCEDURE IF EXISTS p_multiply;

DELIMITER $$;

CREATE PROCEDURE p_multiply(IN matrix_a VARCHAR(16),IN matrix_b VARCHAR(16),IN lengths INT)

BEGIN

-- MySQL动态查询貌似不支持DECLARE声明的变量,只能使用用户自定义变量,即: SET @var = value;

-- DECLARE sql_str_a,sql_str_b VARCHAR(128);

SET @temp_aa = 0,@temp_bb = 0;

SET @xi=1,@yi=1,@zi=1;

SET @sql_a = CONCAT('SELECT val INTO @temp_aa FROM ',matrix_a,' WHERE id=(?-1)*?+?');

SET @sql_b = CONCAT('SELECT val INTO @temp_bb FROM ',matrix_b,' WHERE id=(?-1)*?+?');

SET @len = lengths;

-- 初始化一个新矩阵,用来存储运算结果

TRUNCATE TABLE matrix;

WHILE @xi<=lengths*lengths DO

BEGIN

INSERT INTO matrix(val) VALUES (0);

SET @xi = @xi+1;

END;

END WHILE;

-- 矩阵相乘运算,A(xy) = A(xy)+B(xz)*C(zy);

SET @xi=1;

WHILE @xi<=lengths DO

SET @yi=1;

WHILE @yi<=lengths DO

SET @zi=1;

WHILE @zi<=lengths DO

BEGIN

PREPARE val_a FROM @sql_a;

PREPARE val_b FROM @sql_b;

EXECUTE val_a USING @xi,@len,@zi; DEALLOCATE PREPARE val_a;

EXECUTE val_b USING @zi,@len,@yi; DEALLOCATE PREPARE val_b;

UPDATE matrix SET val=val+@temp_aa*@temp_bb WHERE id=(@xi-1)*@len+@yi;

SET @zi=@zi+1;

END;

END WHILE;

SET @yi=@yi+1;

END WHILE;

SET @xi=@xi+1;

END WHILE;

END;紧接着就到到快速幂的核心部分,快速幂有好几种写法,这里使用我最喜欢的一种,无需递归无需数组。由于是矩阵快速幂,因此里面的运算需要改为基于矩阵的运算。需要一个单位矩阵开始,由于没有编程语言里面的数据类型的灵活性。一个简单的表达式matrix_b

= matrix_b*matrix_a;我们就需要分成好几部实现,这里matrix_b*matrix_a的运算已经有上面得到存储过程给出。但是赋值语句是必须的,每次矩阵相乘都会重置matrix表,必须将表中存储的运算结果复制出来,防止丢失。使用者两条语句来进行进行数据复制,同时保证id的正确性。TRUNCATE TABLE matrix_b;INSERT INTO matrix_b(val) SELECT val FROM matrix ORDER

BY id;DROP PROCEDURE IF EXISTS p_matrix_pow;

DELIMITER $$;

CREATE PROCEDURE p_matrix_pow(IN num INT,IN lengths INT)

BEGIN

-- 初始化matrix_b为单位矩阵

DECLARE i INT DEFAULT 1;

TRUNCATE TABLE matrix_b;

WHILE i<=lengths*lengths DO

BEGIN

IF (i-1)%lengths = (i-1) DIV lengths THEN

INSERT INTO matrix_b(val) VALUES (1);

ELSE

INSERT INTO matrix_b(val) VALUES (0);

END IF;

SET i = i+1;

END;

END WHILE;

-- 快速幂运算

WHILE num>0 DO

BEGIN

IF num%2!=0 THEN

BEGIN

-- matrix_b = matrix_b*matrix_a;

CALL p_multiply('matrix_b','matrix_a',lengths);

TRUNCATE TABLE matrix_b;

INSERT INTO matrix_b(val) SELECT val FROM matrix ORDER BY id;

END;

END IF;

SET num = num DIV 2;

-- matrix_a = matrix_a*matrix_a;

CALL p_multiply('matrix_a','matrix_a',lengths);

TRUNCATE TABLE matrix_a;

INSERT INTO matrix_a(val) SELECT val FROM matrix ORDER BY id;

END;

END WHILE;

-- return matrix_b;

END;当快速幂进行结束,最终结果就在matrix_b表中。

说到这里,细心的可能会有疑问,矩阵快速幂和斐波那契数列有什么关系啊。斐波那契数列的数学表达式又不是幂运算,连乘法运算都没有。很明显,直接参照那个递推公式是不能使用矩阵快速幂的。这里需要用到一个不可思议的转换,此转换能适用很多递推表达式。我们再来看看这个表达式F(n) = F(n-1)+F(n-2)。此时将等号量表的位置替换一下,F(n-2)+F(n-1)

= F(n);如果F(n)参与下次递推的话,就是这样的F(n-1)+F(n) =F(n+1);转换成矩阵乘法就如下所示:| 1 1 | |F(n) | |F(n+1)|

| | * | | = | |

| 1 0 | |F(n-1)| |F(n) |F(n+2)就可以这样表示:| 1 1 | | 1 1 | |F(n) | | 1 1 | |F(n+1)| |F(n+2)|

| | * | | * | | = | | * | | = | |

| 1 0 | | 1 0 | |F(n-1)| | 1 0 | |F(n) | |F(n+1)|这样我们就可以依照矩阵乘法运算的结合律,先使用快速幂求出前面的常数矩阵的连乘部分,然后再和最后的一个2*1的矩阵相乘,求出最终的结果。

下面是执行求解的MySQL命令:TRUNCATE TABLE matrix_a;

INSERT matrix_a(val) VALUES (1),(1),(1),(0);

CALL p_matrix_pow(42,2); -- F(n) = F(n-1)+F(n-2),(n>2,F(1)=F(2)=1)

SELECT SUM(val) FROM matrix_b WHERE id=1 OR id=2;快速幂的运算结果最终保存在matrix_b表中,同时此处省去了最后一步矩阵相乘的运算,直接相加求的结果。p_matrix_pow(42,2);实际求解的是F(44);F(1)和F(2)并适用这里的快速幂算法。

以上就是用MySQL实现矩阵快速幂的全过程。再次强调一下,MySQL并没有C/C++,java等编程语言在算法处理上的的灵活性,这里只是尝试实现一下,纯属娱乐。

mysql 矩阵运算_MySQL实现算法:矩阵快速幂相关推荐

  1. H - Fibonacci POJ - 3070 (矩阵快速幂)

    H - Fibonacci POJ - 3070 (矩阵快速幂) Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and ...

  2. mysql 矩阵运算_HDU 2276 Kiki amp; Little Kiki 2 (位运算+矩阵快速幂)

    HDU 2276 Kiki Little Kiki 2 (位运算矩阵快速幂) ACM 题目地址:HDU 2276 Kiki Little Kiki 2 题意 : 一排灯,开关状态已知,每过一秒:第i个 ...

  3. 51nod 算法马拉松18 B 非010串 矩阵快速幂

    51nod 算法马拉松18 B 非010串 矩阵快速幂 非010串 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 如果一个01字符串满足不存在010这样的子串,那么称它为非010串 ...

  4. 蓝桥杯 算法提高 递推求值(矩阵快速幂)详解

    传送门 问题描述 已知递推公式: F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5, F(n, 2)=F(n-1, 1) + 3F(n-3, 1) + 2F(n-3, 2) + 3 ...

  5. 算法分类整理+模板①:矩阵快速幂

    一直有一个想法,感觉自己很多基础算法不是很扎实,想要找个机会写一些算法的整理,顺便自己总结一些实用的模板. 最近偶然在训练赛中连续做了2道思维+矩阵快速幂的题目,碰巧有时间,就以矩阵快速幂作为这个系列 ...

  6. 杭电ACM-LCY算法进阶培训班-专题训练(矩阵快速幂)

    杭电ACM-LCY算法进阶培训班-专题训练(矩阵快速幂)[模板] 传送门 杭电ACM-LCY算法进阶培训班-专题训练(矩阵快速幂)[模板] 矩阵快速幂模板 Count Problem Descript ...

  7. python【数据结构与算法】快速幂and矩阵快速幂取模(看不懂你来打我)

    文章目录 1 解释快速幂 2 代码(这里就不考虑指数为小于0的情况了) 3 下面是矩阵快速幂,区别只是底数换成了矩阵 1 解释快速幂 传统的幂运算,是对底数进行连乘,时间复杂度为o(n),例如:2^1 ...

  8. 2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)- 分组(矩阵快速幂套NTT优化dp)

    题目链接:点击查看 题目大意:给出 nnn 个连续的小球,每次可以选择单独的一个或者相邻的两个小球分成一组,允许有剩余的小球,问恰好分成 k∈{1,2,3,⋯,m}k\in\{1,2,3,\cdots ...

  9. 疯子的算法总结(五) 矩阵乘法 (矩阵快速幂)

    学过线性代数的都知道矩阵的乘法,矩阵乘法条件第为一个矩阵的行数等与第二个矩阵的列数,乘法为第一个矩阵的第一行乘以第二个矩阵的第一列的对应元素的和作为结果矩阵的第一行第一列的元素.(详解参见线性代数) ...

最新文章

  1. php mysql商品管理_PHP基础示例:商品信息管理系统v1.1[转]
  2. python进阶:闭包、map/reduce/filter函数、lambda函数、装饰器
  3. 解决fixed在苹果手机抖动问题/头部底部固定布局
  4. ajax如何实现、readyState五中状态的含义
  5. 基础算法 —— 递归算法
  6. Setimer和Ontimer的使用
  7. Android Studio开发学习 - 1. 添加Activity
  8. Spark Streaming三种运行场景
  9. Windows2000系统下Apache2和PHP4安装终级宝典
  10. Ubuntu中搭建ICE服务器(Coturn)
  11. ios开发 各种字体
  12. python模拟gps定位_python 模拟 GPS, $GPRMC $GPRMC
  13. vue3中json编辑器
  14. 收藏 :数据资源下载网址大全
  15. 谈到电影,我们收获了什么
  16. 前端处理图片脱敏效果,给图片进行马赛克处理
  17. H5网页微信授权登录
  18. 杨校老师课堂之集群内SSH免密登录功能配置
  19. css一些零零散散的问题
  20. H5 3d立体相册 CSS3特性

热门文章

  1. 网络 - V2X与VANET
  2. 叶胜超:Polkadot(波卡)---跨链之王!
  3. 聚醚砜染料吸附膜纳米纤维膜
  4. python搭建自动化测试平台_AutoMagic 开源自动化测试平台搭建之修改默认python版本
  5. [双语阅读]奥巴马:希望故地重游 品尝印尼美食
  6. ubuntu16.04开发环境总结
  7. 天龙AVR-X4800H怎么样,天龙AVR-X4800H和X4700H区别对比
  8. 如同使用postman实现接口签名
  9. [网播][podcast] Born to MISrepresent 第十五集:Jouston Huang 谈 Nokia N900
  10. 一次无线网络故障排查