# How do I find the minimum between a matrix and a varying matrix function? I get "Error in fmincon (line 563) initVals.f = feval(funf​cn{3},X,va​rargin{:})​;"

2 views (last 30 days)
Goncalo Costa on 1 Dec 2023
Commented: Star Strider on 1 Dec 2023
I am trying to analyse how close, percentually, my samples are to pure water (0%) and to "no water"/dried (100%). In theory my results should give me a value between 0% and 100% (or 0 and 1, labelled below as fitvar)
I have a 2D data array for water, a 2D data array for "dried" and a 2D data for each data set that I am trying to analyse. All data arrays are composed of complex numbers, hence why I can't solve this analytically.
% the size of the data arrays are 75 x 75 matrices.
num_x = 75;
num_y = 75;
perc_water = zeros(num_latex_measurements, num_x, num_y);
% loading a 75 x 75 matrix of the current sample to analyse, of pure water
% and of dried sample.
%relabelling the data (as it had been saved with the variable name of
%I3.epsilon)
eps_water = eps_water.I3_epsilon;
eps_dried = eps_dried.I3.epsilon;
for x=1:num_x
for y=1:num_y
% calculating the theoretical values for eps over a range of
% fit_var, from 0 to 1
eps_theory = @(fit_var) FORMULA( eps_water(x, y), eps_dried(x,y), fit_var );
% calculate the absolute value between the difference of the
% current sample data and of the theoretical values.
loss_fx = @(fit_var) abs(eps_current_sample(x, y) - eps_theory(fit_var) );
%finding the smallest difference for each 2D matrix, for each
%fit_var value
perc_water(x, y) = fmincon(loss_fx, 0.5, [], [] , [], [], 0, 1);
end
end
The FORMULA function is shown below (this is simple multiplication and divisions resulting in a 75 x 75 matrix with complex numbers.
function eps_eff = FORMULA(eps_water, eps_dried, perc_water)
eps_eff = eps_dried./2.0-eps_water./4.0-eps_dried.*perc_water.*(3.0./4.0)+eps_water.*perc_water.*(3.0./4.0)+sqrt(eps_dried.*eps_water.*4.0-eps_dried.^2.*perc_water.*1.2e+1-eps_water.^2.*perc_water.*6.0+eps_dried.^2.*4.0+eps_water.^2+eps_dried.^2.*perc_water.^2.*9.0+eps_water.^2.*perc_water.^2.*9.0+eps_dried.*eps_water.*perc_water.*1.8e+1-eps_dried.*eps_water.*perc_water.^2.*1.8e+1)./4.0;
end
Whenever I try to run it I get the following error message.
Operator '-' is not supported for operands of type 'struct'.
Error in @(fit_var)abs(eps_current_latex(x,y)-perc_water_fx(fit_var))
Error in fmincon (line 563)
initVals.f = feval(funfcn{3},X,varargin{:});
I have never used fmincon before, is there anything incorrect with my approach? I know the operator is not really the problem, but I don't see what is.

Star Strider on 1 Dec 2023
Edited: Star Strider on 1 Dec 2023
There is one typo (. where _ should be) in:
eps_dried = eps_dried.I3.epsilon;
so change that to:
eps_dried = eps_dried.I3_epsilon;
and the displayed error is corrected by changing the current ‘loss_fx’ line to:
loss_fx = @(fit_var) abs(eps_current_sample.I3_epsilon(x, y) - eps_theory(fit_var) );
Consider suppressing the fmincon outputs as well, in an options structure:
opts = optimoptions('fmincon', 'Display','off');
perc_water(x, y) = fmincon(loss_fx, 0.5, [], [] , [], [], 0, 1, [], opts);
Then run it —
% the size of the data arrays are 75 x 75 matrices.
num_x = 75;
num_y = 75;
% perc_water = zeros(num_latex_measurements, num_x, num_y); % Missing Variable
% loading a 75 x 75 matrix of the current sample to analyse, of pure water
% and of dried sample.
%relabelling the data (as it had been saved with the variable name of
%I3.epsilon)
eps_water = eps_water.I3_epsilon;
eps_dried = eps_dried.I3_epsilon;
opts = optimoptions('fmincon', 'Display','off');
for x=1:num_x
for y=1:num_y
% calculating the theoretical values for eps over a range of
% fit_var, from 0 to 1
eps_theory = @(fit_var) FORMULA( eps_water(x, y), eps_dried(x,y), fit_var );
% calculate the absolute value between the difference of the
% current sample data and of the theoretical values.
loss_fx = @(fit_var) abs(eps_current_sample.I3_epsilon(x, y) - eps_theory(fit_var) );
%finding the smallest difference for each 2D matrix, for each
%fit_var value
perc_water(x, y) = fmincon(loss_fx, 0.5, [], [] , [], [], 0, 1, [], opts);
end
end
Output = perc_water
Output = 75×75
1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.9754 0.7861 0.6034 0.4423 0.3177 0.2418 0.2217 0.2507 0.3124 0.3900 0.4749 0.5611 0.6415 0.7118 0.7701 0.8194 0.8621 0.8970 0.9241 0.9438 0.9580 0.9682 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.9999 0.8517 0.6600 0.4878 0.3511 0.2622 0.2275 0.2450 0.3012 0.3784 0.4620 0.5465 0.6284 0.7022 0.7653 0.8168 0.8598 0.8966 0.9264 0.9494 0.9660 0.9778 0.9861 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.9999 0.8280 0.6297 0.4578 0.3306 0.2576 0.2394 0.2692 0.3339 0.4165 0.5029 0.5847 0.6609 0.7308 0.7916 0.8423 0.8828 0.9161 0.9440 0.9663 0.9833 0.9953 0.9998 0.9999 1.0000 1.0000 1.0000 1.0000 1.0000 0.9964 0.7581 0.5477 0.3909 0.2933 0.2569 0.2723 0.3252 0.4019 0.4887 0.5744 0.6525 0.7205 0.7807 0.8340 0.8791 0.9159 0.9448 0.9681 0.9873 0.9997 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.9384 0.6950 0.4767 0.3374 0.2778 0.2806 0.3270 0.3981 0.4804 0.5653 0.6458 0.7173 0.7784 0.8295 0.8735 0.9117 0.9435 0.9691 0.9888 0.9999 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.9999 0.8725 0.6552 0.4434 0.3141 0.2816 0.3130 0.3797 0.4610 0.5447 0.6247 0.6985 0.7636 0.8187 0.8645 0.9020 0.9338 0.9612 0.9837 0.9996 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.9186 0.8737 0.7798 0.6208 0.4324 0.3073 0.2862 0.3362 0.4156 0.5034 0.5880 0.6648 0.7328 0.7925 0.8433 0.8855 0.9198 0.9477 0.9711 0.9910 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.7031 0.6551 0.5608 0.4233 0.3056 0.2817 0.3406 0.4315 0.5250 0.6118 0.6879 0.7532 0.8089 0.8565 0.8964 0.9290 0.9553 0.9764 0.9940 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.5150 0.4708 0.3919 0.3018 0.2686 0.3238 0.4247 0.5278 0.6191 0.6973 0.7627 0.8171 0.8626 0.9009 0.9326 0.9582 0.9787 0.9949 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 0.3659 0.3325 0.2822 0.2509 0.2913 0.3945 0.5108 0.6119 0.6951 0.7633 0.8188 0.8641 0.9015 0.9326 0.9581 0.9785 0.9947 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000 1.0000
figure
surfc(Output)
xlabel('X')
ylabel('Y')
zlabel('perc\_water')
title('Output')
colormap(turbo)
function eps_eff = FORMULA(eps_water, eps_dried, perc_water)
eps_eff = eps_dried./2.0-eps_water./4.0-eps_dried.*perc_water.*(3.0./4.0)+eps_water.*perc_water.*(3.0./4.0)+sqrt(eps_dried.*eps_water.*4.0-eps_dried.^2.*perc_water.*1.2e+1-eps_water.^2.*perc_water.*6.0+eps_dried.^2.*4.0+eps_water.^2+eps_dried.^2.*perc_water.^2.*9.0+eps_water.^2.*perc_water.^2.*9.0+eps_dried.*eps_water.*perc_water.*1.8e+1-eps_dried.*eps_water.*perc_water.^2.*1.8e+1)./4.0;
end
EDIT — (1 Dec 2023 at 13:28)
.
Goncalo Costa on 1 Dec 2023
Of course, thanks, that is because I wanted to do a for loop over several data sets to be analysed.
Thank you so much, and I apologise for the silly mistakes.
Star Strider on 1 Dec 2023
@Goncalo Costa — I removed the preallocation:
% perc_water = zeros(num_latex_measurements, num_x, num_y); % Missing Variable
because ‘num_latex_measurements’ was missing. The preallocation defines a 3D matrix, however since I didn’t know what the missing variable was, I just removed (commented-out) the entire preallocation. If you want to do a loop over a number of data sets, a 3D matrix is one option. A cell array with each 2D matrix being in a different cell is another option. It all depends on how you choose to index them.