【问题标题】:Matlab: How do I convert multivariable symbolic expression to a function that fminsearch can use?Matlab:如何将多变量符号表达式转换为 fminsearch 可以使用的函数?
【发布时间】:2015-09-02 23:16:34
【问题描述】:

我有一个多变量符号表达式说

c = x^2 +y^2 + z^2

使用 matlabFunction(c) 返回

ans = @(x,y,z)x.^2+y.^2+z.^2

我无法将它输入到 fminsearch 中(因为它有多个标量输入,对吗?)。如何更改输出的格式,使其采用 fminsearch 实际允许的内容,例如

@(x)x(1)^2+x(2)^2+x(3)^2

对 3 个变量手动执行此操作是可行的,但对于数百个变量则不行。

如果有帮助,错误看起来像这样:

Error using symengine?makeFhandle/@(......) Not enough input arguments.
Error in fminsearch (line 190) fv(:,1) = funfcn(x,varargin{:}):

【问题讨论】:

    标签: matlab symbolic-math


    【解决方案1】:

    想到的一个快速解决方法是创建另一个匿名函数作为中间人:

    fun          = @(x,y,z)x.^2+y.^2+z.^2;
    funMiddleMan = @(x) fun(x(1),x(2),x(3));
    

    对于大量参数,解决方案变得有点复杂。 我的第一直觉是按以下方式使用str2func

    nVar         = 3;
    funMiddleMan = str2func(['@(x)fun(',sprintf('x(%d),',1:nVar-1),'x(',num2str(nVar),'))']);
    

    但是,这将不起作用,因为str2func 不能(当前)将fun 的定义嵌入到附加到funMiddleMan 的本地工作区中;这意味着以这种方式调用funMiddleMan 将产生“Undefined function 'fun'”错误。使用eval可以绕过该问题:

    funMiddleMan = eval(['@(x)fun(',sprintf('x(%d),',1:nVar-1),'x(',num2str(nVar),'))']);
    

    这将起作用,因为实际评估了字符串;但是,出于多种原因,eval 的使用是 typically discouraged,仅出于完整性考虑(以及一种快速而肮脏的方式让球滚动)。


    另一种选择是将向量 x 转换为元胞数组,并按以下方式使用 comma-separated list 扩展:

    splay        = @(x) fun(x{:});
    funMiddleMan = @(x) splay(mat2cell(x(:),ones(1,numel(x)),1));
    

    这不一定是最佳的,但有效。

    【讨论】:

    • 我发现的一个问题是,如果我尝试: fminsearch(funMiddleMan,[0,0,0]) 它不起作用,因为 fun 尚未定义。我试图解决这个问题,只在命令窗口中复制 funMiddleMan 的输出并将其粘贴到 funMiddleMan 的位置。这对少数变量有效。对于我正在处理的项目,我有一个方程很长,以至于输出被截断,因为文本超过了 25,000 个字符的最大行长。有什么想法吗?
    • @Lawng 为什么在创建funMiddleMan之前没有定义fun
    • @Lawng 至于项目问题,鉴于方程的长度,这听起来像是永远不应该触及符号工具箱的东西,解决方案将是针对特定问题的数值处理。
    • @TroyHaskin 只是让人们知道您更新的方法对我和我的方程式有效。谢谢!
    • @David 他们俩都做到了。我只是快速运行和时间,结果发现单元阵列方法要长几秒钟。当您考虑 eval 方法的问题时,还不错。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多