Is there a faster way than repeating this calculation manually?

I have a function file with 6 equations and 6 unknowns:
function F = TEST6lijn300(x)
F = [(x(1)^2 + x(2)^2 -753233.1);
((1447.5-x(3))^2 + (876.3-x(4))^2-966977.2);
((-72.4-x(5))^2 + (1723.1-x(6))^2-957129.6);
(x(5)^2 - 2*(x(5)*x(1)) + x(1)^2 + x(6)^2 - 2*(x(6)*x(2)) + x(2)^2 - 20449);
(x(3)^2 - 2*(x(3)*x(1)) + x(1)^2 + x(4)^2 - 2*(x(4)*x(2)) + x(2)^2 - 20449);
(x(3)^2 - 2*(x(3)*x(5)) + x(5)^2 + x(4)^2 - 2*(x(4)*x(6)) + x(6)^2 - 20449)];
end
I have managed to solve it using:
x0 = [5; 10; 5; 10; 5; 10]; % Make a starting guess at the solution options=optimset('Display','iter','MaxFunEvals',1000); % Option to display output [x,fval] = fsolve(@TEST6lijn300,x0,options) % Call solver
However I need to do this calculation hundreds of times, only changing the numbers 753233.1, 966977.2, and 957129.6. I have hundreds of sets of these three numbers which need to be pasted into the function file. So far, I have been doing it manually, but there must be a better way..

 Accepted Answer

function F = TEST6lijn300(x, p)
F = [(x(1)^2 + x(2)^2 - p(1));
((1447.5-x(3))^2 + (876.3-x(4))^2-p(2));
((-72.4-x(5))^2 + (1723.1-x(6))^2-p(3));
(x(5)^2 - 2*(x(5)*x(1)) + x(1)^2 + x(6)^2 - 2*(x(6)*x(2)) + x(2)^2 - 20449);
(x(3)^2 - 2*(x(3)*x(1)) + x(1)^2 + x(4)^2 - 2*(x(4)*x(2)) + x(2)^2 - 20449);
(x(3)^2 - 2*(x(3)*x(5)) + x(5)^2 + x(4)^2 - 2*(x(4)*x(6)) + x(6)^2 - 20449)];
end
The call would be
...
p = [753233.1, 966977.2, 957129.6] ;
[x,fval] = fsolve(@(x)TEST6lijn300(x,p),x0,options) ;
EDIT2: if all your sets of p values are in an Excel file, you can do the following (that you could make more concise by eliminating temporary variables):
x0 = ...
options = ...
filename = 'myFile.xlsx' ;
sheet = 'mySheet' ;
P = xlsread(filename, sheet) ; % Assuming that there is no numerical
% header in your spreadsheet.
n = size(P, 1) ; % Number of rows (sets of p values).
X = zeros(n, length(x0)) ; % Prealloc for storing x's.
for ii = 1 : n
fh = @(x) TEST6lijn300(x, P(ii,:)) ; % See note below.
X(ii,:) = fsolve(fh, x0, options) ;
end
Note: fh is a function handle on an anonymous function that takes 1 input parameter, x, and calls your function TEST6lijn300 with the two arguments that it requires, here x and ii-th row of P that is the ii-th set of p values. Jan's comment refers to a post explaining that using an anonymous function is the proper way to manage this type of situations where you have to match interfaces between your function and some solver requirements.
Cedric

12 Comments

That's definitely a step in the right direction, thank you!
But now p is only one set of 3 numbers. I have hundreds of sets of 3, which all have to go through the same calculation. Is there a way to calculate them all at once, saving me hours of doing it manually? :)
I have the values in a nx3 matrix in excel. Where and how do I put these numbers into Matlab?
That's a totally different question. Please search the forum as it has already been asked many times.
doc xlsread
Also, please accept an answer if it helped you.
And I understand that getting the data from excel into Matlab is a totally different question. But a question that is still on topic: where do I put the matrix in Matlab so that the command knows where to find it?
Updated my answer according to your last comment.
Thank you, once again :)
if true
% >> filename = 'resultatentest6.xls' ;
sheet = 'Sheet1' ;
P = xlsread(filename, sheet) ; % Assuming that there is no numerical
% header in your spreadsheet.
n = size(P, 3) ; % Number of rows (sets of p values).
X = zeros(n, 1263) ; % Prealloc for storing x's.
for ii = 1 : n
fh = @(x) template_p(x, P(ii,:)) ; % See note below.
X(ii,:) = fsolve(fh, x0, options) ;
end
after using this command, the excel file was imported successfully. However, Matlab tells me to 'continue entering statement'. What am I forgetting, or what did I do wrong?
It seems to be because there is no closing end corresponding to the if true at the beginning. But why are you using this test if you type the code in the command window?
Also, n = size(P,3) is likely not to be correct, as the second arg. is the dimension from which you want the size. I wrote n = size(P,1) because I want n to be the number of rows (dimension 1) in matrix P (meaning the number of rows in your Excel file, which is the number of sets of p).
The line after was X = zeros(n, length(x0)) because I wanted to create X with n rows, and as many columns as there are components in x0 (assuming that you have a vector x0 defined somewhere before). This way the code would work for any size of x0. If you hard-code 1263, you make it specific to a unique size of x0.
Well, the uploaded excel file has 3 columns (which should correspond to p(1), p(2) and p(3), and 1263 rows (number of sets of p).
now I have in my function file 'template_p':
function F = template_p(x)
F = [(x(1)^2 + x(2)^2 -P(1));
((1447.5-x(3))^2 + (876.3-x(4))^2-P(2));
((-72.4-x(5))^2 + (1723.1-x(6))^2-P(3));
(x(5)^2 - 2*(x(5)*x(1)) + x(1)^2 + x(6)^2 - 2*(x(6)*x(2)) + x(2)^2 - 20449);
(x(3)^2 - 2*(x(3)*x(1)) + x(1)^2 + x(4)^2 - 2*(x(4)*x(2)) + x(2)^2 - 20449);
(x(3)^2 - 2*(x(3)*x(5)) + x(5)^2 + x(4)^2 - 2*(x(4)*x(6)) + x(6)^2 - 20449)];
filename = 'resultatentest6.xls' ;
sheet = 'Sheet1' ;
P = xlsread(filename, sheet) ; % Assuming that there is no numerical
% header in your spreadsheet.
n = size(P, 1) ; % Number of rows (sets of p values).
X = zeros(n, length(x0)) ; % Prealloc for storing x's.
for ii = 1 : n
fh = @(x) template_p(x, P(ii,:)) ; % See note below.
X(ii,:) = fsolve(fh, x0, options) ;
end
In the command window I am using the same command as I was before:
x0 = [5; 10; 5; 10; 5; 10]; % Make a starting guess at the solution
options=optimset('Display','iter'); % Option to display output
[x,fval] = fsolve(@template_p,x0,options) % Call solver
and now I am getting these errors:
Undefined function or variable "P".
Error in template_p (line 3)
F = [(x(1)^2 + x(2)^2 -P(1));
Error in fsolve (line 241)
fuser = feval(funfcn{3},x,varargin{:});
Maybe it's easier to see what's going wrong now..
Ah yes, you should have something like that:
The m-file template_p.m that contains:
function F = template_p(x, p)
F = [(x(1)^2 + x(2)^2 - p(1)); ...
((1447.5-x(3))^2 + (876.3-x(4))^2 - p(2)); ...
((-72.4-x(5))^2 + (1723.1-x(6))^2 - p(3)); ...
(x(5)^2 - 2*(x(5)*x(1)) + x(1)^2 + x(6)^2 - ...
2*(x(6)*x(2)) + x(2)^2 - 20449); ...
(x(3)^2 - 2*(x(3)*x(1)) + x(1)^2 + x(4)^2 - ...
2*(x(4)*x(2)) + x(2)^2 - 20449); ...
(x(3)^2 - 2*(x(3)*x(5)) + x(5)^2 + x(4)^2 - ...
2*(x(4)*x(6)) + x(6)^2 - 20449)];
end
A script m-file that contains what you were previously typing in the command window, so you don't have to type all that again each time. Let's call it myRun.m, and it should contain:
x0 = [5; 10; 5; 10; 5; 10]; % Make a starting guess at the
% solution
options = optimset('Display','iter'); % Option to display output
filename = 'resultatentest6.xls' ;
sheet = 'Sheet1' ;
P = xlsread(filename, sheet) ; % Assuming that there is no num.
% header in your spreadsheet.
n = size(P, 1) ; % Number of rows (sets of p
% values).
X = zeros(length(x0), n) ; % Prealloc for storing x's.
for ii = 1 : n
fh = @(x) template_p(x, P(ii,:)) ;
X(:,ii) = fsolve(fh, x0, options) ;
end
Then you run your script either by typing myRun in the command window, or by clicking on the "Run" green arrow in the editor when the top panel is the content of myRun.m.
Note that I permuted a few things to make dimensions work with your x0 that is a column vector.
That worked like a charm! It solves them all one by one. Only problem is... I can't find the solution :) Matlab makes me feel like an idiot sometimes. Anyway, not only would I like to check the answers, I would also like these exported back into excel. Is this possible?
Each system has 6 answers. I would like the answers for each system to be next to each other in one row. So the result would be a 6x1263 matrix in excel.
Here is a myRun.m with export
x0 = [5; 10; 5; 10; 5; 10]; % Make a starting guess at the
% solution
options = optimset('Display','iter'); % Option to display output
filename = 'resultatentest6.xls' ;
sheet = 'Sheet1' ;
P = xlsread(filename, sheet) ; % Assuming that there is no num.
% header in your spreadsheet.
n = size(P, 1) ; % Number of rows (sets of p
% values).
X = zeros(length(x0), n) ; % Prealloc for storing x's.
for ii = 1 : n
fh = @(x) template_p(x, P(ii,:)) ;
X(:,ii) = fsolve(fh, x0, options) ;
end
sheet = 'Results' ;
xlswrite(filename, X.', sheet) ;
As you can see, I just added 2 lines, and it exports in the same file where your parameters are, but in a sheet called Results. Results are in the X matrix after execution of the for loop. It is a 6 rows * 1263 columns matrix, that we transpose when exporting to xls (with the .'), so you get 1263 rows * 6 columns in your spreadsheet.
If you are starting with MATLAB, I highly encourage you to run your script on a dataset with 2 or 3 sets of parameters, and observe each object in this script (size, content, etc), so you understand what happens, because the very first thing to understand in MATLAB is certainly how to manipulate data.
Cheers,
Cedric

Sign in to comment.

More Answers (1)

Read this about using anonymous functions to define parameters:

2 Comments

OK, so it's best to use ode45? As I'm new to Matlab, the above explanation is a bit difficult for me. I have three columns of numbers (results from an experiment) in excel. How do I get this into Matlab and into the functions?
No, ODE45 is not sufficient. The thread matters only the method for defining parameters efficiently in the the function passed to fsolve.

Sign in to comment.

Tags

Asked:

on 16 Jan 2013

Community Treasure Hunt

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

Start Hunting!