在 Mathematica 中计算此递推关系的更有效方法

2024-04-02

Verbeia 对 Mathematica 中函数式编程风格的表现展开了一场相当有趣的讨论。在这里能找到它:在 Mathematica 中构建大型分块矩阵最有效的方法是什么? https://stackoverflow.com/q/6867079/312124)

我正在解决一个问题,在对代码进行一些计时后,一个特别耗时的部分是我通过递归关系计算矩阵的条目:

c = Table[0, {2L+1}, {2L+1}];

c[[1, 1]] = 1;
Do[c[[i, i]] = e[[i - 1]] c[[i - 1, i - 1]], {i, 2, 2 L + 1}];
Do[c[[i, 1]] = (1 - e[[i - 1]]) c[[i - 1, 1]], {i, 2, 2 L + 1}];
Do[c[[i, j]] = (1 - e[[i - 1]]) c[[i - 1, j]] + 
    e[[i - 1]] c[[i - 1, j - 1]], {i, 2, 2 L + 1}, {j, 2, i - 1}];

Where e是一些外部定义的列表。有什么办法可以更有效地写这个吗?我似乎找不到任何明显的方法来使用内置函数以更惯用和更有效的方式完成此任务。

我意识到我只能做这么多,因为这段代码是O(n^2),但我有一系列矩阵乘法(总共大约 6 次),它们的运行时间比这个语句要少。我能做的任何事情来加快速度,哪怕是稍微加快一点,都会对我的运行时间产生明显的影响。

Update:符合什么acl推荐,我尝试使用Compile来加快我的表达速度。对于一个相对较小的L = 600,我天真地得到了 3.81 秒Do[...], 普通旧版 1.54 秒Compile,以及 0.033 秒Compile[..., CompilationTarget->"C"].

为了获得更真实的尺寸L = 1200,时间变为 16.68、0.605 和 0.132Do, Compile and Compile[.., CompilationTarget->"C"]分别。我能够实现 acl 在他的帖子中提到的相同 2 个数量级的加速。


Try Compile。这里我定义了3个函数:f正如你所定义的,fc编译(某种字节码)并且fcc编译为 C(查看文档以了解如何检查生成的代码)。

首先,让 mma 告诉我们是否有东西无法编译:

SetSystemOptions["CompileOptions"->"CompileReportExternal"->True]

然后是函数:

ClearAll[f];
f=Function[{ell,e},
    Module[{c=Table[0,{2ell+1},{2ell+1}]},
        c[[1,1]]=1;
        Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
        Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
        Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
            {i,2,2 ell+1},{j,2,i-1}];
        c
    ]
];


ClearAll[fc];
fc=Compile[{{ell,_Integer},{e,_Integer,1}},
    Module[{c},
        c=Table[0,{2ell+1},{2ell+1}];
        c[[1,1]]=1;
        Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
        Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
        Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
            {i,2,2 ell+1},{j,2,i-1}];
        c
    ]
];

ClearAll[fcc];
fcc=Compile[{{ell,_Integer},{e,_Integer,1}},
    Module[{c},
        c=Table[0,{2ell+1},{2ell+1}];
        c[[1,1]]=1;
        Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
        Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
        Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
            {i,2,2 ell+1},{j,2,i-1}];
        c
    ],
    CompilationTarget->"C",
    RuntimeOptions->"Speed"
];

没有错误,所以没问题。现在测试(在配备 2.4GHz core 2 duo、使用电池运行的 MacBook 上进行测试):

ell=400;
e=RandomInteger[{0,1},2*ell];
f[ell,e];//Timing
fc[ell,e];//Timing
fcc[ell,e];//Timing

giving

{2.60925, Null}
{0.092022, Null}
{0.022709, Null}

因此编译为 C 的版本在这里快了两个数量级。

如果更改类型并出现编译错误,请询问。

编辑:如果e包含实数,尝试

ClearAll[fc];
fc=Compile[{{ell,_Integer},{e,_Real,1}},
    Module[{c},
        c=Table[0.,{2ell+1},{2ell+1}];
        c[[1,1]]=1;
        Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
        Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
        Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
            {i,2,2 ell+1},{j,2,i-1}];
        c
    ]
];

ClearAll[fcc];
fcc=Compile[{{ell,_Integer},{e,_Real,1}},
    Module[{c},
        c=Table[0.,{2ell+1},{2ell+1}];
        c[[1,1]]=1;
        Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
        Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
        Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
            {i,2,2 ell+1},{j,2,i-1}];
        c
    ],
    CompilationTarget\[Rule]"C",
    RuntimeOptions\[Rule]"Speed"
];

instead.

人们可以通过说来感受一下这是如何工作的

Needs["CompiledFunctionTools`"]
CompilePrint[fc]

并获得

        2 arguments
        18 Integer registers
        6 Real registers
        3 Tensor registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        I0 = A1
        T(R1)0 = A2
        I12 = 0
        I1 = 2
        I3 = 1
        I14 = -1
        R0 = 0.
        Result = T(R2)2

1   I11 = I1 * I0
2   I11 = I11 + I3
3   I7 = I1 * I0
4   I7 = I7 + I3
5   I17 = I12
6   T(R2)2 = Table[ I11, I7]
7   I15 = I12
8   goto 13
9   I16 = I12
10  goto 12
11  Element[ T(R2)2, I17] = R0
12  if[ ++ I16 < I7] goto 11
13  if[ ++ I15 < I11] goto 9
14  R1 = I3
15  Part[ T(R2)2, I3, I3] = R1
16  I4 = I1 * I0
17  I4 = I4 + I3
18  I5 = I3
19  goto 26
20  I10 = I5 + I14
21  I8 = I10
22  R4 = Part[ T(R1)0, I8]
23  R5 = Part[ T(R2)2, I8, I8]
24  R4 = R4 * R5
25  Part[ T(R2)2, I5, I5] = R4
26  if[ ++ I5 < I4] goto 20
27  I4 = I1 * I0
28  I4 = I4 + I3
29  I5 = I3
30  goto 40
31  I10 = I5 + I14
32  I13 = I10
33  R4 = Part[ T(R1)0, I13]
34  R5 = - R4
35  R4 = I3
36  R4 = R4 + R5
37  R5 = Part[ T(R2)2, I13, I3]
38  R4 = R4 * R5
39  Part[ T(R2)2, I5, I3] = R4
40  if[ ++ I5 < I4] goto 31
41  I4 = I1 * I0
42  I4 = I4 + I3
43  I5 = I3
44  goto 63
45  I6 = I5 + I14
46  I17 = I3
47  goto 62
48  I16 = I5 + I14
49  I9 = I16
50  R4 = Part[ T(R1)0, I9]
51  R2 = R4
52  R4 = - R2
53  R5 = I3
54  R5 = R5 + R4
55  R4 = Part[ T(R2)2, I9, I17]
56  R5 = R5 * R4
57  I16 = I17 + I14
58  R4 = Part[ T(R2)2, I9, I16]
59  R3 = R2 * R4
60  R5 = R5 + R3
61  Part[ T(R2)2, I5, I17] = R5
62  if[ ++ I17 < I6] goto 48
63  if[ ++ I5 < I4] goto 45
64  Return

寄存器的名称表明其类型等。如果使用“C”选项,您还可以查看生成的 C 代码(但这有点难以阅读)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Mathematica 中计算此递推关系的更有效方法 的相关文章

  • 在 CakePHP 中向 Containable 添加条件

    以前我依赖递归 但我没有得到一些解决方案 然后我发现 Containable 对于这些问题工作得很好 我正在开发一个电影评论网站 我需要显示与特定类型相关的电影列表 我有下面的代码 example genre drama options a
  • 阿克曼函数的这种实现可以称为尾递归吗?

    我用 C 语言编写了以下代码 我们可以将其称为尾递归实现吗 include
  • 使用 F# 进行循环与递归

    这里的示例代码解决了一个项目欧拉问题 从数字 1 开始 按顺时针方向向右移动 方向 5 x 5 螺旋形成如下 21 22 23 24 25 20 7 8 9 10 19 6 1 2 11 18 5 4 3 12 17 16 15 14 13
  • PHPExcel_Style_Fill 无限递归

    我使用图书馆PHPExcel 1 7 9跟 共事Excel文件 首先 我创建一个模板 对其进行样式化和润色 然后 为了避免样式硬编码 使用上述库打开该模板 更改一些值并将其保存为新的 xlsx file 首先 我们从单元格中获取该样式 th
  • 使用PHP通过FTP递归扫描目录和子目录

    我正在尝试创建目录中所有文件 及其大小 的列表 包括子目录中的所有内容 这些文件位于远程服务器上 所以我的脚本通过 FTP 连接 然后使用以下命令运行递归函数ftp chdir浏览每个目录 如果有其他方法可以做到这一点 我愿意接受建议 fl
  • 使用递归查找数组中的最大值

    对于我被要求解决的问题之一 我使用 for 循环找到了数组的最大值 所以我尝试使用递归来找到它 这就是我想到的 public static int findMax int a int head int last int max 0 if h
  • 动态规划——自上而下与自下而上

    我了解到动态规划 DP 有两种 自上而下和自下而上 In top down 您可以使用递归和记忆 在自下而上 你只需填充一个数组 一个表 此外 这两种方法都使用相同的时间复杂度 就我个人而言 我发现自上而下的方法更容易 更自然地遵循 给定的
  • unix下C++递归复制目录

    没有任何可供使用的功能示例c without additional libs将递归文件和文件夹复制到新位置 一些替代方案system cp R f dir call 我只找到这个C 中的递归目录复制 https stackoverflow
  • 将模块定义为 Manipulate 表达式的一部分与在初始化部分中定义有任何性能问题吗?

    我想问是否有人知道任何问题 性能或其他 如果要定义 放置 Manipulate 表达式使用的模块 就在 Manipulate 表达式本身内部 而不是在初始化部分 通常是在哪里完成的 两种方法都有效 但是当涉及到从模块直接访问 Manipul
  • 如何获得字符串的所有字谜

    我试图找到一个字符串的所有可能的字谜并仅使用递归将它们存储在数组中 我被困住了 这就是我所拥有的一切 int main const int MAX 10 string a ABCD string arr 10 permute arr a 0
  • c中使用递归的strlen函数

    我对递归主题很陌生 我一直在尝试使用递归编写 strlen 函数 这就是我尝试过的 int strlen char str int i if str i 0 return i 1 return strlen str i 我尝试了一些非常相似
  • 在 Clojure 中退出 Recur 循环

    我想跳出下面的循环 并在第 10 行计算结果为 true 时返回最佳最小移动 我查看了 print 语句的输出 当第 10 行的计算结果为 true 时 它 找到了我正在查找的数据 但仍然重复出现 在 Clojure 中 有没有办法在语句计
  • 用于从深层嵌套列表/元组中提取元素的递归函数

    我想编写一个从深层嵌套元组和列表中提取元素的函数 假设我有这样的东西 l THIS THAT a b c THAT d e f 我想要一个没有 这个 和 那个 的简单列表 list a b c d e f 这是我到目前为止所拥有的 def
  • Java中的递归排列生成错误结果

    问题是生成字典排列 起初 我的代码是这样的 public class Problem24 public static void main String args permutation 123 public static void perm
  • NodeJS 在目录中递归地哈希文件

    我能够实现目录中的递归文件遍历 即探索目录中的所有子目录和文件 为此我使用了answer https stackoverflow com questions 5827612 node js fs readdir recursive dire
  • 递归方法比交互式方法慢 10 倍 [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 代码已尽可
  • 使用一次递归调用实现递归

    给定一个函数如下 f n f n 1 f n 3 f n 4 f 0 1 f 1 2 f 2 3 f 3 4 我知道使用递归来实现它 并在一个函数内进行三个递归调用 但我想在函数内仅使用一次递归调用来完成此操作 怎样才能做到呢 要实现使用
  • 这个对自身单位的列表理解是如何工作的?

    在 haskell IRC 频道中有人问 是否有一种简洁的方法来定义一个列表 其中第 n 个条目是之前所有条目的平方和 我认为这听起来像一个有趣的谜题 递归定义无限列表是我真正需要练习的事情之一 所以我启动了 GHCi 并开始尝试递归定义
  • 如何用流程图表示递归函数?

    我需要在流程图上表示递归函数 我的问题是我不知道如何指示该函数可以一次在多个元素上调用自身 例如扫描图形的函数 有人有什么建议吗 在流程图中 您通常不会为循环之类的内容添加多次调用 您只需指示可以重复调用代码 直到满足条件为止 因此 对于递
  • 线程“main”中的异常 java.lang.StackOverflowError

    我有一段代码 但我无法弄清楚为什么它在线程 main java lang StackOverflowError 中给出异常 这是问题 Given a positive integer n prints out the sum of the

随机推荐

  • SSIS 2008 中 ADO NET 源和 OLE DB 源之间的区别?

    谁能说出 SSIS 2008 中 ADO NET 源和 OLE DB 源之间的区别 它们在任何上下文中都相同吗 对于小型数据集 SSIS 2008 中的 ADO NET 源和 OLE DB 源之间几乎没有什么区别 它们之间的区别在于它们与其
  • 作为承诺的结果表示重新发送

    我不明白发生了什么事 Using q承诺 这有效 const deferred q defer deferred resolve Hellow const myPromise deferred promise router get item
  • OpenGL 统一缓冲区 std140 布局

    我正在尝试通过 GeForce 8600 GT 上的统一块将整数数组传递给片段着色器 一切均根据 GLSL version 330 在应用程序方面我有 int MyArray 7102 filling binding etc glBuffe
  • 为控制台应用程序制作 UI [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何为控制台应用程序制作一个界面 使它们看起来像edit com在微软的操作系统下 目标语言是 C C 和 C NET 看一下curs
  • 如何将序列中的下一个值放入变量中?

    因此 我正在编写一个存储过程 但无法将序列的下一个值放入变量中 序列名称被传递到函数中并存储为varchar2多变的 如何将该序列中的下一个值放入局部变量中 像这样的东西吗 create or replace procedure next
  • gulp 命令给出找不到模块的错误

    我正在尝试在 Windows 上设置基本的 aurelia 应用程序 我已遵循以下指示 http aurelia io get started html http aurelia io get started html 包括 安装节点js
  • 如何获取宿主元素引用?

    如何获取 Angular 2 中的宿主元素引用 就我而言 我想知道我的组件是否有焦点 您可以使用以下方式获取宿主元素引用 class MyComponent constructor private elRef ElementRef cons
  • 为什么我不应该有一个单一的整体实用程序库?

    我们有一些通用库 C 但我想这不是特定于平台或语言的 我们称它们为 A B 和 C 库 A 引用了 B 和 C 库 B 引用了第三方 DLL 库 C 是独立的 三个独立项目背后的想法是 每个库都有不同的功能 但随着时间的推移 库 A 或多或
  • mysql 使用另一个表中的值更新列

    我有两张桌子 看起来都像 id name value 1 Joe 22 2 Derk 30 我需要复制的值value from tableA to tableB基于每个表中的检查名称 对此有何建议UPDATE陈述 除了这个答案之外 如果您需
  • 连接表达式以获取数据帧的子集

    我正在尝试创建一个函数来计算子集数据框中列的平均值 这里的技巧是 我总是想要有几个子集条件 然后可以选择将更多条件传递给函数以进一步子集数据帧 假设我的数据如下所示 dat lt data frame var1 rep letters 26
  • Paster db init -c XXXX/development.ini 不适用于 CKAN 命令“db”不知道

    我是 CKAN 和 python 的第一次用户 我的大部分开发都是在 NET 我是第一次在 Windows 7 计算机上设置 CKAN 我正在尝试运行该行 paster db init c FOLDER NAME development i
  • PHP中如何获取最后修改的文件?

    我想创建一个列表 列出上次修改的文件的名称 http www searchr us web search 我想在我的主页上显示这些文件名 它们应该根据上次修改的文件进行更改 你可以使用这个功能 function listdir by dat
  • 调用未定义函数password_hash()

    我正在开发我的网站时 现在正在本地主机上运行 php 版本 5 4 16 我想用password hash 但我不断收到此错误 致命错误 调用未定义函数password hash dir to file php在线的123 为什么会发生这种
  • 如何加载目录中的所有文件?

    正如标题所说 如何加载目录中的每个文件 我对c 和lua都感兴趣 编辑 对于 Windows 我很高兴能得到一些真正的工作代码 尤其是 lua 我可以用 boost filesystem for c 来做 对于 Lua 你需要模块Lua文件
  • Heroku 30 秒超时(长外部查询)的解决方法

    注意 这篇文章中的某些内容可能不是最佳实践 被警告 我正在开发一个连接到微实例 AWS 服务器的管理仪表板 该数据库拥有数千万条记录 大多数查询都会在几秒钟内返回 但有些查询需要长达一两分钟的时间才能返回 这取决于我无法控制的一些事情 由于
  • GHC如何实现unsafePerformIO?

    从 开始unsafePerformIO并以 RTS libc 或操作系统 API 结束 GHC 如何实现 IO 我试图了解当标准前奏不可用时 IO 在 Haskell 中如何工作 例如 如果我们出于某种原因自己实现标准前奏 我原本希望在 G
  • 寻找参考nodejs,expressjs和mongodb应用程序用作模板

    我想构建一个 Nodejs 应用程序 并且正在寻找一个很好的参考应用程序来用作模板 理想情况下 该应用程序应具有以下功能 使用nodejs expressjs 和 mongodb 有一个用户认证子系统 我想下载这样一个应用程序并让它开箱即用
  • stylesheet_pack_tag 在使用 webpacker gem 的 Rails 5.1 中找不到 app/javascript/src/application.css

    当我尝试使用 webpacker 在新的 Rails 5 1 应用程序中加载页面时 收到此错误 我希望 webpacker 也能处理 CSS Started GET for 1 at 2017 09 01 12 20 23 0400 Pro
  • Git暂存区只是一个索引吗?

    Pro Git 一书说 暂存区域只是一个列表或索引 它说明了当某个文件发生变化时将提交哪些文件 git commit完成了 现在的名字index通常被称为 暂存区 但是如果我们修改文件foo txt这已经是回购协议的一部分 并使用git a
  • 在 Mathematica 中计算此递推关系的更有效方法

    Verbeia 对 Mathematica 中函数式编程风格的表现展开了一场相当有趣的讨论 在这里能找到它 在 Mathematica 中构建大型分块矩阵最有效的方法是什么 https stackoverflow com q 6867079