Does set_param have a numerical accuracy limit? If so, what can I do to solve the problem?

1 次查看(过去 30 天)
Hello,
I recently conceived a MATLAB/Simulink programming problem for my students. The problem was to adapt the coefficients of a 2nd order linear dynamical system such that the step response best fits a given function.
The structure shoud be as follows (see attaced files OptDynSysTest1.m, simuSys.m and DynSystem.slx, sprawsoll.m in setparamproblem.zip):
When the main file (OptDynSysTest1.m) is launched with a handle to the desired step response (@sprawsoll), the sampling points (for example (0:0.1:10)) and an ititial guess for the three system coefficients (for example [1,1,1]), the program opens DynSystem.slx and tries to optinize those coefficients to best fit the step response of the system to the given function. For this purpose the procedure lsqcurvefit is used. The objective function is represented by simuSys.m. This function simulates the system by setting the actual parameters to DynSystem.slx using set_param and the calling sim.
In a second version of this problem, I do not use Simulink to simulate the system but I'm using lsim instead (see attaced files OptDynSysTest3.m, simuSys3.m and DynSystem.slx, sprawsoll.m in setparamproblem.zip).
The problem is that this program works fine and finds the optimal step resonse approximation whereas the version using Simulink sticks in the first iteration saying that the initial guess is the optimum. Regardedless what the initial guess is!
After a couple of hours of analysis I found out what the reason is.
The problem is set_param!!!
This function passes parameters in a numerically inexact way. For example the parameter 2.001 is passed exactly whereas the parameter 2.0000001 will be simply 2 for Simulink. This is the reason why the optimizaton procedure doesn't work, because in the beginning the changements in the parameter values are very small. Since those small changements "disappear" when passed to Simulink by set_param, the optimization algorithm immediately finds a zero gradient and stops saying that this is an optimum.
My questions: Is this a set_param bug? How can I overcome this set_param problem?
Sincerily Ottmar Beucher
  2 个评论
Sainath Varikuti
Sainath Varikuti 2015-8-21
Hi Ottmar,
You can use get_param(gcb,'ParameterName') to get the value of the parameter. Do you see the truncation in the value returned by get_param?
Regards,
Sainath
Ottmar Beucher
Ottmar Beucher 2015-9-16
Hi Sainath,
thank you for this suggestion. I tried it out. Unfortunately get_param returns a STRING, so it is not clear how Simulink uses the values internally. But the result confirmed that there is most probably a truncation. Herr ist the result of my trial:
------------------------------------------ >> [Optcoeffs] = OptDynSysTest1(@sprawsoll, (0:0.1:10), [1,1,1]); iteration:
Coeffs =
1 1 1
Gain parameter to set for the first system: 1.000000000000000 Value read out by get_param for the gain parameter of the first system: 1 Time constant to set for the first system: 1.000000000000000 Value read out by get_param for the time constant of the first system (first number): [1 1] Time constant to set for the second system: 1.000000000000000 Value read out by get_param for the time constant of the second system (first number): [1 1] iteration:
Coeffs =
1.0000 1.0000 1.0000
Gain parameter to set for the first system: 1.000000014901161 Value read out by get_param for the gain parameter of the first system: 1 Time constant to set for the first system: 1.000000000000000 Value read out by get_param for the time constant of the first system (first number): [1 1] Time constant to set for the second system: 1.000000000000000 Value read out by get_param for the time constant of the second system (first number): [1 1] iteration:
Coeffs =
1.0000 1.0000 1.0000
Gain parameter to set for the first system: 1.000000000000000 Value read out by get_param for the gain parameter of the first system: 1 Time constant to set for the first system: 1.000000014901161 Value read out by get_param for the time constant of the first system (first number): [1 1] Time constant to set for the second system: 1.000000000000000 Value read out by get_param for the time constant of the second system (first number): [1 1] iteration:
Coeffs =
1.0000 1.0000 1.0000
Gain parameter to set for the first system: 1.000000000000000 Value read out by get_param for the gain parameter of the first system: 1 Time constant to set for the first system: 1.000000000000000 Value read out by get_param for the time constant of the first system (first number): [1 1] Time constant to set for the second system: 1.000000014901161 Value read out by get_param for the time constant of the second system (first number): [1 1]
Initial point is a local minimum.
Optimization completed because the size of the gradient at the initial point is less than the default value of the function tolerance.
iteration:
Coeffs =
1 1 1
Gain parameter to set for the first system: 1.000000000000000 Value read out by get_param for the gain parameter of the first system: 1 Time constant to set for the first system: 1.000000000000000 Value read out by get_param for the time constant of the first system (first number): [1 1] Time constant to set for the second system: 1.000000000000000 Value read out by get_param for the time constant of the second system (first number): [1 1]
-------------------------------------------
As you see, the value 1.000000014901161 produced by the optimization proceedure is truncated to 1 (seemingly also internally as a double). So for the optimization proceedure ther is no changement in the objective function an the algorithm stops with its initial value.
Sincerily Ottmar

请先登录,再进行评论。

采纳的回答

Titus Edelhofer
Titus Edelhofer 2015-9-16
Dear Prof. Beucher,
it's not a bug in set_param but the way it's used, e.g.
set_param('DynSystem/TF1','Numerator',num2str(Coeffs(1)));
num2str converts with 6 digits. Therefore everything else is lost. Call num2str with a precision to overcome the problem:
set_param('DynSystem/TF1','Numerator',num2str(Coeffs(1), 20));
Then it should work as expected.
Titus
  4 个评论
Ottmar Beucher
Ottmar Beucher 2015-9-16
Dear Titus,
great!!!! Thanks a lot. In fact I never suspected num2str;-)) It's never to late to learn new things. By the way: you are right! I should limit coefficients to positive numbers in order to avoid instable systems. I wonder why it worked withot this limitation when using lsim. Maybe a hazard.
Thanks a lot!! O. Beucher

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Programmatic Model Editing 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by