罗兰谈MATLAB的艺术

将想法转化为MATLAB

使用嵌套函数来记忆昂贵的函数

一些语言提供了存储代价高昂的计算结果的方法,因此如果之前已经执行了计算,以后请求时就不需要重复。在MATLAB中也有一种方法可以实现这一点,使用嵌套函数。考虑这个函数:
function f = memoize1(f) %one-arg f,输入可测试== x = [];Y = [];F = @inner;函数out = inner(in) ind = find(in == x);if isempty(ind) out = F(in);X (end+1) = in;Y (end+1) = out;Else out = y(ind);结束结束
让我们看看当我们使用这个函数时,会发生什么,不可否认,没有那么昂贵的计算函数。此外,您可以在这里替换任何其他函数句柄,包括引用匿名函数的句柄,前提是它有一个输入和一个输出。
>> f = memoize1(@sin) f = @memoize1/inner >> x = f(3) x = 0.1411 >> y = f(7) y = 0.6570 >> z = f(3) z = 0.1411 >> f(.2) ans = 0.1987 >> f(pi/8) ans = 0.3827
现在让我们看看我们的函数发生了什么f使用功能函数。这应该主要用于调试和获得洞察力,而不是作为编程工具。

获取函数句柄的信息:

>> s = functions(f) s = function: 'memoize1/inner' type: 'nested' file: 'H:DocumentsLORENv7memoize1. 'M ' workspace: {[1x1 struct]}

获取关于嵌套函数的信息,包括它的工作空间:

>> s.workspace{1} ans = f: @memoize1/inner f: @sin x: [3 7 0.2000 0.3927] y: [0.1411 0.6570 0.1987 0.3827]
如果我们把断点放在内心的并发出命令f (3)从提示中,我们将能够遵循索引到已保存值的逻辑,而不是再次进行计算。此外,如果我们想退出MATLAB并在稍后返回,我们可以将函数句柄保存在mat文件中并稍后重新加载它。我们会需要保存除句柄之外的任何东西,因为相关的工作空间也将被保存。memoize1可以通过向量化(可能使用ismember).以下是该代码变体的最新版本:

函数f = memoize2(f) %one-arg f,输入可测试== %允许非标量输入。X = [];Y = [];F = @inner;函数out = inner(in) out = 0 (size(in));[tf,loc] = ismember(in,x);%查找哪个in已经计算在x ft = ~tf;% 1要计算出(ft) = F(in(ft));在存储x = [x in(ft(:).')];Y = [Y shape(out(ft),1,[])]; out(tf) = y(loc(tf)); % fill in the rest of the output values end end

这种memoize代码模式的变体可能对具有递归关系的函数、递归函数或细化底层网格的函数有用。您可能希望有一个缓冲区限制,以便嵌套函数中存储的数据的大小不会超过某个界限。但你懂的。

|

评论

如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。