让我们假设您可以将程序表示为数学函数,这是可能的。该函数的一阶导数的程序表示形式如何?有没有办法将程序转换为其“衍生”形式,这是否有意义?
7 回答
是的,它确实有意义,它被称为自动微分。有一个或两个实验性编译器可以做到这一点,例如NAGware 的Differential Enabled Fortran Compiler Technology。并且有很多关于这个主题的研究论文。我建议你去谷歌搜索。
首先,只有尝试获得纯函数的导数才有意义(一个不影响外部状态并为每个输入返回完全相同的输出的函数)。其次,许多编程语言的类型系统涉及很多阶跃函数(例如整数),这意味着您必须让您的程序按照连续函数工作才能获得有效的一阶导数。第三,获得任何函数的导数都涉及将其分解并象征性地操纵它。因此,如果不知道函数是如何构成的,就无法获得函数的导数。这可以通过反射来实现。
如果您的编程语言支持闭包(即嵌套函数以及将函数放入变量并返回它们的能力),您可以创建一个导数逼近函数。这是取自http://en.wikipedia.org/wiki/Closure_%28computer_science%29的 JavaScript 示例:
function derivative(f, dx) {
return function(x) {
return (f(x + dx) - f(x)) / dx;
};
}
因此,您可以说:
function f(x) { return x*x; }
f_prime = derivative(f, 0.0001);
在这里,f_prime
将近似function(x) {return 2*x;}
如果一种编程语言实现了高阶函数和足够多的代数,则可以在其中实现真正的导数函数。那真的很酷。
你如何定义程序的数学函数?
导数表示函数的变化率。如果您的函数不是连续的,那么它的导数将在大多数域中未定义。
我只想说这没有多大意义,因为程序比数学函数更抽象和“无规则”。由于导数是衡量输入变化时输出变化的量度,因此肯定有一些程序可以应用。 但是,您需要能够以数字形式量化您的输入/输出。
由于输入/输出都是数字的,因此可以合理地假设您的程序表示或操作类似于数学函数或一系列函数。因此,您可以轻松地表示导数,但这与将函数的数学导数转换为计算机程序没有什么不同。
如果程序被表示为分布(Schwartz),那么假设测试函数对您的后置条件建模(您仍然可以通过限制来获得特征函数),那么您就有了一些导数概念。例如,分配x:=x+1
与狄拉克分布相关联,\delta_{x_0+1}
其中x_0
是变量的初始值x
。但是,我不知道 的计算含义是什么\delta_{x_0+1}'
。
我想知道,如果您尝试“派生”的程序使用某种形式的启发式方法怎么办?那怎么推导出来呢?
半开玩笑地说,我们都知道所有真正的程序都至少使用 rand()。