将匿名函数拆分为术语

Split Anonymous Function into Terms

我想采用类似 @(x) = x + x^2 的 matlab 匿名函数并将其拆分为元胞数组,以便

f{1} = @(x) x
f{2} = @(x) x^2

我希望能够使用一些任意函数句柄来执行此操作。到目前为止,我想出的最好的方法是将 @(x) = x + x^2 作为一个字符串,然后用加号将其拆分,然后将 @(x) 附加到它的开头。但是,我希望能够直接使用函数句柄作为函数参数。这也很好,因为使用其他变量可能会导致字符串方法出现一些困难。

我也在考虑将函数句柄的元胞数组作为参数,这对用户来说会更困难,但在我的代码中更容易。

对于某些背景,我想对我正在为 class 编写的一些最小二乘数据拟合代码执行此操作。此代码将用于将模型函数作为参数,我需要针对最小二乘过程分别评估每个项。我并没有将这些模型限制为多项式,即使模型是多项式,我也希望可以选择忽略多项式中的某些幂。如果有人对模型函数有更好的建议,那也太好了。

更新:有人想知道我的意思

I'm not limiting these models to polynomials and even if a polynomial is the model, I want the option to leave out certain powers in the polynomial.

澄清一下,我是说我不想将模型限制为

c0 + c1*x + ... + cn*x^n

在这种情况下,我可以将 n 作为参数并从中创建类似于 polyfit 中发生的术语。例如,如果我知道我的输入数据适合偶函数或奇函数,我可能想要以下模型之一

c0 + c1*x^2 + c2*x^4 + ... + ck*x^(2k)
c1*x + c2*x^3 + ... + cm*x^(2m-1)

其中 k 是偶数,m 是奇数。或者可能不是严格的多项式模型,但保持系数线性,例如

c0 + exp(x) * ( c1 + c2*x + ... cn*x^(n-1) )

这是一个有趣的问题。该字符串不应在括号组内的 + 符号处拆分。例如,

f = @(x) x + (x+1)*sqrt(x) + x^2 + exp(x+2);

字符串应在第一个符号处拆分,但不应在第二个 + 符号处拆分。

这可以按如下方式完成。要仅检测括号外的 + 符号,请为每个左括号加 1,为每个右括号减 1。然后所需的 + 符号是计数为 0 的符号。

我假设输出应该是函数句柄的元胞数组。如果它应该是一个字符串元胞数组,只需删除最后一行。

F = functions(f);
str = F.function; %// get string from function handle
[pref, body] = regexp(str, '@\(.+?\)', 'match', 'split'); %// pref is the '@(...)' part
body = body{2}; %// body is the main part
ind = cumsum((body=='(')-(body==')'))==0 & body=='+'; %// indices for splitting
body(ind) = '?'; %// '?' will be used as split marker
ff = strcat(pref, strsplit(body, '?')); %// split, and then add prefix
ff = cellfun(@str2func, ff, 'uniformoutput', 0); %// convert strings to functions

本例中的结果:

ff{1} =
    @(x)x
ff{2} =
    @(x)(x+1)*sqrt(x)
ff{3} =
    @(x)x^2
ff{4} =
    @(x)exp(x+2)