How can I fix the error in my MATLAB program's objective function, which aims to optimize Simulink model parameters to match simulated data with experimental data (y_exp)?

I am trying to code a Matlab program that optimizes the parameters of a Simulink model called "R1Model" and simultaneously compares the simulation data (simulated_data) generated by the model with the experimental data (y_exp). Once the optimization is complete, the code should display the values of the optimized parameters such that the simulated data matches the real data. I think the error is in the objective function. This Error message always occurs:
Error using fmincon (line 321)
Row dimension of A is inconsistent with length of b.
Error in Try1 (line 27)
[optimal_param, optimal_value] = fmincon(objective_function, initialRCParams, lb, ub);
Help is highly appreciated:)
Thanks!
The Code:
%load('Res_1st_run.mat');
ExpData = importdata("Res_1st_run.mat");
t_exp = ExpData.results.I_cmd_A.Time.';
%y_exp = ExpData.results.U_measured_V.Data.';
y_exp = ExpData.results.SOC_BAT.Data.'./100;
% the Simulink model function to be optimized
simulink_model = @(param) simulate_model(param, t_exp);
% the objective function to minimize (sum of squared differences)
objective_function = @(param) sum((y_exp - simulink_model(param)).^2);
% Initial parameter guess
initialRCParams = [RCParameters.R_i, RCParameters.R_1, RCParameters.R_2, RCParameters.C_1, RCParameters.C_2];
% Define parameter bounds
lb = double([0, 0, 0, 0, 0]);
ub = double([10, 10, 10, 10, 10]);
% Optimization using fmincon
% options = optimset('Display', 'iter', 'MaxIter', 100); % Modify options as needed
[optimal_param, optimal_value] = fmincon(objective_function, initialRCParams, lb, ub);
% Display optimized parameter and objective value
fprintf('Optimized Parameter: %.4f\n', optimal_param);
fprintf('Optimized Objective Value: %.4f\n', optimal_value);
% Simulate the model with the optimized parameter
simulated_data = simulate_model(optimal_param, t_exp);
% Plot the experimental and simulated data for comparison
plot(t_exp, y_exp, 'b', t_exp, simulated_data, 'r');
xlabel('Time');
ylabel('Data');
legend('Experimental Data', 'Simulated Data');
function simulated_data = simulate_model(param, t_exp)
open_system('R1Model');
%param = initialRCParams;
RCParameters = param;
% Simulate the model and return the simulated data
simulated_data = sim('R1Model', 'StartTime', num2str(t_exp(1)), 'StopTime', num2str(t_exp(end)));
simulated_data = simulated_data.yout{1}.Values.Data;
end

 Accepted Answer

[optimal_param, optimal_value] = fmincon(objective_function, initialRCParams, lb, ub);
Mathworks-provided functions never look at the names of variables that you are passing in as parameters in order to guess what functional role the contents of those parameters have.
Mathworks-provided functions work with a mix of positional parameters and name-value pairs (all name-value pairs must go after positional parameters.)
fmincon() does not accept any name-value pairs, only positional parameters. If you do not wish to actively use a particular positional parameter, pass in [ ] in that location.
[optimal_param, optimal_value] = fmincon(objective_function, initialRCParams, [], [], [], [], lb, ub);

4 Comments

Thank you for the quick reply! However I now get this result which is quit unsatiesfying:
Optimization completed because at the initial point, the objective function is non-decreasing
in feasible directions to within the value of the optimality tolerance, and
constraints are satisfied to within the value of the constraint tolerance.
<stopping criteria details>
Optimized Parameter: 0.0373
Optimized Parameter: 0.0168
Optimized Parameter: 0.0029
Optimized Parameter: 1680.0000
Optimized Parameter: 2999.0100
Optimized Objective Value: 13865.2475
I think the problem lies in the objective function or that the parameters are somehow not updated correctly...
I tried to plot the objective function while keeping R_2 ,C_1 and C_2 constant and R_i, R_1 as variables and the result was that the objective function is a constant.
Any help or suggestions are highly appreciated:) Thank you!
Here is my code slightly modiefied code:
% Open and Access Data Dictionary
Parameters_myDictionaryObj = Simulink.data.dictionary.open('/Users/eliasweingartner/Desktop/Forschungspraxis/Battery_DataDic.sldd');
dDataSectObj = getSection(Parameters_myDictionaryObj, 'Design Data');
entryObj = getEntry(dDataSectObj, 'RCParameters');
RCParameters = getValue(entryObj);
% Load Experiment Data
ExpData = importdata("Res_1st_run.mat");
time_I_s = ExpData.results.I_cmd_A.Time.';
I_cmd_A = squeeze(ExpData.results.I_cmd_A.Data).';
time_U_s = ExpData.results.U_measured_V.Time.';
U_measured_V = ExpData.results.U_measured_V.Data.';
time_SOC_s = ExpData.results.SOC_BAT.Time.';
SOC_measured = ExpData.results.SOC_BAT.Data.' ./ 100;
% Data Preparation
time_input_s = time_I_s;
u_input = [I_cmd_A(1), I_cmd_A(1:end-1)];
time_measurements_s = time_U_s;
z_SOC = interp1(time_SOC_s, SOC_measured, time_U_s);
z_measurements = [z_SOC; U_measured_V];
y_exp = z_measurements(2,:);
t_exp = time_U_s;
% Define the initial parameter guess
initialRCParams = double([RCParameters.R_i, RCParameters.R_1, RCParameters.R_2, RCParameters.C_1, RCParameters.C_2]);
% Define the Simulink model function to be optimized
simulink_model = @(param) simulate_model(param, t_exp, Parameters_myDictionaryObj, dDataSectObj);
% Define the objective function to minimize (sum of squared differences)
%objective_function = @(param) sum((y_exp' - simulink_model(param)).^2);
%Mean Squared Error (MSE)
%objective_function = @(param) mean((y_exp' - simulink_model(param)).^2);
%Root Mean Squared Error (RMSE)
%objective_function = @(param) sqrt(mean((y_exp' - simulink_model(param)).^2));
%Mean Absolute Error (MAE)
%objective_function = @(param) mean(abs(y_exp' - simulink_model(param)));
lambda = 0.01; % Regularization parameter, adjust as needed
objective_function = @(param) sum((y_exp' - simulink_model(param)).^2) + lambda * sum(param.^2);
% % Assuming RCParameters contains the nominal values for the parameters
% RCParameters_nominal = RCParameters;
%
% % Define a coarser range of the first two parameters for plotting
% R_i_range = linspace(0, 1, 20); % Coarser range
% R_1_range = linspace(0, 1, 20); % Coarser range
%
% % Initialize a matrix to store the objective function values
% objective_values = zeros(length(R_i_range), length(R_1_range));
%
% for i = 1:length(R_i_range)
% for j = 1:length(R_1_range)
% try
% % Update the parameters
% param = RCParameters_nominal;
% param.R_i = R_i_range(i);
% param.R_1 = R_1_range(j);
%
% % Convert struct to array
% param_array = [param.R_i, param.R_1, param.R_2, param.C_1, param.C_2];
%
% % Evaluate the objective function
% objective_values(i, j) = objective_function(param_array);
% catch e
% disp('Error during objective function evaluation:');
% disp(e.message);
% return; % Exit the loop on error
% end
% end
% end
%
%
% % Plotting
% [R_i_mesh, R_1_mesh] = meshgrid(R_i_range, R_1_range);
% disp('Plotting the objective function surface...');
% surf(R_i_mesh, R_1_mesh, objective_values);
% xlabel('R_i');
% ylabel('R_1');
% zlabel('Objective Function Value');
% title('Objective Function Surface for R_i and R_1');
%
% if all(objective_values(:) == objective_values(1))
% disp('Warning: The objective function is constant over the specified parameter range.');
% end
% Define parameter bounds
lb = double([0, 0, 0, 0, 0]);
ub = double([1, 1, 1, 2000, 3000]);
% Run the optimization
try
[optimal_param, optimal_value] = fmincon(objective_function, initialRCParams, [], [], [], [], lb, ub);
catch exception
fprintf('An error occurred: %s\n', getReport(exception));
optimal_param = [];
optimal_value = Inf;
end
% Display optimized parameter and objective value
fprintf('Optimized Parameters:\n');
disp(optimal_param);
fprintf('Optimized Objective Value: %.4f\n', optimal_value);
% Simulate the model with the optimized parameter
simulated_data = simulate_model(optimal_param, t_exp, Parameters_myDictionaryObj, dDataSectObj);
% Plot the experimental and simulated data for comparison
plot(t_exp, y_exp, 'b', t_exp, simulated_data, 'r');
xlabel('Time');
ylabel('Data');
legend('Experimental Data', 'Simulated Data');
function simulated_data = simulate_model(param_array, t_exp, Parameters_myDictionaryObj, dDataSectObj)
% Update data dictionary with the new parameters
F_assign2DD('R_i', param_array(1), dDataSectObj);
F_assign2DD('R_1', param_array(2), dDataSectObj);
F_assign2DD('R_2', param_array(3), dDataSectObj);
F_assign2DD('C_1', param_array(4), dDataSectObj);
F_assign2DD('C_2', param_array(5), dDataSectObj);
saveChanges(Parameters_myDictionaryObj);
% Force Simulink to load new parameters
set_param('R1Model', 'SimulationCommand', 'update');
% Refresh or reload the Simulink model
set_param('R1Model', 'DataDictionary', 'Battery_DataDic.sldd');
% Run the Simulink model
simulated_data = sim('R1Model', 'StartTime', num2str(t_exp(1)), 'StopTime', num2str(t_exp(end)));
simulated_data = simulated_data.yout{2}.Values.Data;
% Display some of the simulation output for debugging
disp('Simulation output (first few values):');
disp(simulated_data(1:min(end, 5)));
end
Since we can't run your code, there is no chance for us to spot the error.
But as you wrote: If the simulated data don't change, it's an indication that your Simulink model returns the same simulated data independent of the parameter array.
Okay thank you! But if I change the parameters manually the simulated data does change. So probably the updating of parameters does not work probably but all my debugging test suggests it does. Could it be something else?
Did you try a different initial point ?
Did you write the simulated data to file during execution and compare them with those you obtain with the initial parameters ?

Sign in to comment.

More Answers (0)

Asked:

Max
on 16 Nov 2023

Commented:

on 29 Nov 2023

Community Treasure Hunt

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

Start Hunting!