MATLAB Answers

Using Matlab coder with lsqcurvefit(), can not pass optimoptions as an argument to the target function

11 ビュー (過去 30 日間)
Xingwang Yong
Xingwang Yong 2021 年 1 月 17 日
編集済み: Xingwang Yong 2021 年 5 月 12 日
I want to convert my function to mex using matlab coder. The function fits data to an exponential model.
function ab_fitted = my_fit_ab_1(x0, xdata, ydata)
simple_exp_func = @(x, xdata) x(1)*exp(-x(2)*xdata); % y=a*exp(-b)
Opt = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt','MaxIter', 100);
ab_fitted = lsqcurvefit(simple_exp_func, x0, xdata, ydata, [],[], Opt);
end
The script main_1.m that calls my_fit_ab_1() is as follows,
clear
a = rand();
b = rand();
xdata = rand(8,1);
ydata = a*exp(-b*xdata);
x0 = [rand, rand];
ab_fitted = my_fit_ab_1(x0, xdata, ydata);
With matlab coder App, I can easily convert my_fit_ab_1() to mex file my_fit_ab_1_mex.mexw64.
However, if I want to pass the variable Opt as an argument, i.e. my_fit_ab_2.m
function ab_fitted = my_fit_ab_2(x0, xdata, ydata, Opt)
simple_exp_func = @(x, xdata) x(1)*exp(-x(2)*xdata); % y=a*exp(-b)
ab_fitted = lsqcurvefit(simple_exp_func, x0, xdata, ydata, [],[], Opt);
end
and main_2.m
clear
a = rand();
b = rand();
xdata = rand(8,1);
ydata = a*exp(-b*xdata);
Opt = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt','MaxIter', 100);
x0 = [rand, rand];
ab_fitted = my_fit_ab_2(x0, xdata, ydata, Opt);
the coder says " The 'optim.options.Lsqcurvefit' class does not support code generation. "
Why optimoptions can be set inside the function while can not be passed as an argument?
I've attached the four files mentioned above.

採用された回答

Steve Grikschat
Steve Grikschat 2021 年 1 月 17 日
Hi Xingwang,
Despite support for the optimoptions function, the objects it generates are not supported for code generation. In the generated code, optimoptions generates structs of options.
As a workaround, I can suggest 2 alternatives, both of which require you to call optimoptions in the function that is being codegened:
  1. The most simple, which will work for this case but won't scale well is to pass the individual options you want set as inputs to your function. This won't be as easy to update as you add more options.
function ab_fitted = my_fit_ab_2(x0, xdata, ydata, maxiter)
Opt = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt','MaxIterations',maxiter);
simple_exp_func = @(x, xdata) x(1)*exp(-x(2)*xdata); % y=a*exp(-b)
ab_fitted = lsqcurvefit(simple_exp_func, x0, xdata, ydata, [],[], Opt);
end
2. If you anticipate wanting to toggle different options in the future, then try passing a struct of options that can be copied over into the optimoptions:
function ab_fitted = my_fit_ab_2(x0, xdata, ydata, optIn)
f = fieldnames(optIn);
Opt = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
for k = 1:numel(f)
thisOption = f{k};
Opt.(thisOption) = optIn.(thisOption);
end
simple_exp_func = @(x, xdata) x(1)*exp(-x(2)*xdata); % y=a*exp(-b)
ab_fitted = lsqcurvefit(simple_exp_func, x0, xdata, ydata, [],[], Opt);
end
To generate code for this, try this script:
dblMatType = coder.typeof(double(1), [8, 1], [1, 1]);
dblVecType = coder.typeof(double(1), [2, 1], [1, 1]);
dblScalarType = coder.typeof(double(1), [1, 1], [1, 1]);
optsType = struct('Algorithm', 'levenberg-marquardt', 'MaxIterations', dblScalarType);
cfg = coder.config('mex');
% x0 xdata ydata opts
cArgs = {dblVecType, dblMatType, dblMatType, optsType};
codegen -config cfg my_fit_ab_2 -args cArgs
Note that the 4th input is a struct of "typeof" objects that you can add to as needed.
  10 件のコメント
Xingwang Yong
Xingwang Yong 2021 年 5 月 12 日
Steve, thanks for your expertise. This dummy Jacobian solution works perfectly.

サインインしてコメントする。

その他の回答 (0 件)

タグ

製品


リリース

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by