我有一个很大的解析函数myfunc.m
,我需要以代码格式d_myfunc_dx.m
获得导数。问题的约束是我需要生成可以重构的代码,以便满足一些质量要求,并且函数本身具有一些特殊性,这些特殊性将在下面的最小示例中重现。
function[out] = myfunc(x,a, max_iterations)
count = 0;
theta = 0;
delta = 1;
while (count<max_iterations && abs(delta)<eps)
cout = count+1;
delta = theta - cos(theta*x);
theta = theta - delta;
end
if(theta<a)
out = theta+x
else
out = x
end
end
理想情况下,导数函数应如下所示:
function[d_out_dx] = myfunc(x,a, max_iterations)
count = 0;
theta = 0;
delta = 1;
while (count<max_iterations && abs(delta)<eps)
cout = count+1;
delta = theta - cos(theta*x);
theta = theta - delta;
end
%assuming convergence: theta = cos(theta*x):
d_theta_dx = -theta*sin(theta*x);
if(theta>a)
d_out_dx = d_theta_dx+1
else
d_out_dx = 1
end
end
即这是可读的,因此我可以对其进行重构,它包含原始功能中存在的分支。边缘情况theta=a
会被忽略,这实际上是理想的。
但是我不期望任何工具能够假定迭代方法的收敛性并执行隐式导数。因此,如果我得到以下信息,我将感到满意:
function[d_out_dx] = myfunc(x,a, max_iterations)
count = 0;
theta = 0;
delta = 1;
d_theta_dx = 0;
while (count<max_iterations && abs(delta) < eps)
cout = count+1;
delta = theta - cos(theta*x);
d_delta_dx = d_theta_dx + theta*sin(theta*x)
theta = theta - delta;
d_theta_dx = d_theta_dx - d_delta_dx
end
if(theta>a)
d_out_dx = d_theta_dx+1
else
d_out_dx = 1
end
end
如果我可以找到一些免费的工具来完成这项工作,那总是很好。
我还需要测试独立检查的代码,所以我会知道是否有任何问题。无需担心工具的可靠性。由于重构期间采用了标准,因此我不必担心所生成代码的安全性(即防止零分割的保护)。
到目前为止,我已经尝试过:
-手动编码:因为我需要使用的功能非常庞大,并且过程容易出错,所以我根本无法获得正确的代码。另外,我需要针对几个变量进行推导,这意味着该过程将花费大量时间。
-ADiMat :引入了诸如adimat_opdiff_mult(t_theta,theta,t_x,x)之类的函数,这使我不符合我的编码标准。重构它意味着与手写衍生物几乎具有相同的工作。
-ADiGator :它无法解析条件语句,因此我需要从目标函数中删除分支,并为每种情况重新获取导数。它创建了许多中间变量,这些中间变量的名称无济于事,但至少是可读的。
-Casadi::据我所尝试,它创建的是文本而不是代码,并且在此文本内,函数内部的变量会丢失名称,并被{{ 1}},@1
,@2
等。手工重新编码将是一场噩梦,并且难以依靠自定义脚本对其进行重构。