Borrar filtros
Borrar filtros

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

2 visualizaciones (últimos 30 días)
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 comentarios
Sainath Varikuti
Sainath Varikuti el 21 de Ag. de 2015
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 el 16 de Sept. de 2015
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

Iniciar sesión para comentar.

Respuesta aceptada

Titus Edelhofer
Titus Edelhofer el 16 de Sept. de 2015
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 comentarios
Ottmar Beucher
Ottmar Beucher el 16 de Sept. de 2015
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
Titus Edelhofer
Titus Edelhofer el 17 de Sept. de 2015
Happy to help :). I think it's o.k. to mark the question as answered then ...

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Programmatic Model Editing en Help Center y File Exchange.

Productos

Community Treasure Hunt

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

Start Hunting!

Translated by