如何安全地操作以字符串形式表示的MATLAB匿名函数

3

我有一个匿名函数,希望将其以字符串形式操作后再使用fsolve。但是当我这样做时,匿名函数中对常量的引用会丢失,导致fsolve失败。

问题可以很容易地说明:

以下代码能够正常工作:

A=3;
myfun=@(x)sin(A*x);
x = fsolve(@(x)myfun(x),[1 4],optimoptions('fsolve','Display','off'))

以下代码会抛出错误,详细解释在这里说明:
A=3;
myfun=@(x)sin(A*x);
mystring=func2str(myfun);
%string operations would go here such as strrep(mystring,'A','A^2') or whatever
myfun2=str2func(mystring);
x = fsolve(@(x)myfun2(x),[1 4],optimoptions('fsolve','Display','off'))

有没有一种安全的方法可以在保留对常量参数的引用的同时操作匿名函数?

更多信息:

具体来说,我正在编写一个简单的包装器,以便让fsolve在简单情况下接受虚数。以下示例演示了一个工作示例,不使用常量参数:

myeqn=@(x)0.5*x^2-5*x+14.5;
cX0=1+1*1i;
f1=strrep(func2str(myeqn),'@(x)','');
f2=strrep((f1),'x','(x(1)+(x(2))*1i)');
f3=strcat('@(x)[real(',f2,'); imag(',f2,')]');
fc=str2func(f3);
opts=optimoptions('fsolve','Display','off');
result=arrayfun(@(cinput)[1 1i]*(real(fsolve(fc,[real(cinput);imag(cinput)],opts))),cX0)

与上面失败的示例一样,如果我在包装器中包含一个参数,该过程将以与上述相同的错误失败。


你有符号数学工具箱的访问权限吗?它是解决这个问题的更好工具。 - Daniel
符号数学工具箱在匿名函数包含数值解而没有封闭形式解的问题时不相关。 - Mr Purple
我原本并不打算使用符号求解器,但符号工具箱(特别是subs函数)非常有帮助。 - Daniel
2个回答

3

我最初建议使用符号数学工具箱,但再次阅读您的问题后,我意识到这只是简单的替换输入参数。您可以使用函数句柄来实现此操作,无需进行任何字符串处理。

myeqn=@(x)0.5*x^2-5*x+14.5;
cX0=1+1*1i;
wrapper=@(x,f)([real(f(x(1)+x(2)*i)),imag(f(x(1)+x(2)*i))])
opts=optimoptions('fsolve','Display','off');
result=arrayfun(@(cinput)[1 1i]*(real(fsolve(@(x)wrapper(x,myeqn),[real(cinput);imag(cinput)],opts))),cX0)

不错。还值得一提的是,如果你想从匿名函数(或任何函数)内部检索参数,可以使用 functions 函数。 - transversality condition
哇,太简单了!非常好。 - Mr Purple
我想对我来说,这个故事的寓意是 - 不要使用字符串运算符来修改匿名函数 -> 使用匿名函数来修改匿名函数。 - Mr Purple
这些操作的一个重要注意事项是非常清楚每个匿名函数的作用域。例如,在我的情况下,我需要确保通过包装器传递任何额外的参数,否则它们会失去作用域。例如,wrapper=@(x,f,A)([real(f(x(1)+x(2)*i),A),imag(f(x(1)+x(2)*i),A)])。 - Mr Purple

-2

尽管我不太喜欢建议使用eval函数,但你可以这样做:

myfun2 = eval(mystring);

使用eval有点不受欢迎,因为它使代码难以分析(因为该字符串中可能存在任意恶意代码),但不要让其他人的编码风格阻止你做有效的事情 :)

在您的更长示例中,这将对应于更改以下行:

fc=str2func(f3);

到:

fc=eval(f3);

再次强烈不建议使用eval,因此您应该考虑替代这种字符串操作函数定义的方法。


这个回答如何解决问题? - Daniel
我是在回应帖子的第一个例子(其中定义了mystring并尝试使用myfun2 = str2func(mystring))并假设他/她能够推断出第二个例子。我将编辑我的答案以明确解决第二个例子。 - KQS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接