0

I have 16 non-linear equations which are independent of each other i.e. they are not a system of equations. One way is to create 16 separate sub-routines and use fsolve to solve which i generally do. But i need to reduce the number of sub-routines from 16 to one. Let me try to give an example of what i'm doing so far:

u01 = .001;....u016 = .001;
options=optimset('Display','notify','MaxFunEvals',10^7,'TolX',1e-,'TolFun',1e-6,'MaxIter',10^5);
u1 = fsolve(@polsim1,u01,options);
        ..
        ..
u16 = fsolve(@polsim16,u016,options);

So, in the above example i have 16 subroutines i.e. polsim1-polsim16 where each includes 1 non-linear equation to solve for u's. This method is very cumbersome and messy. I need to do that in one subroutine. I believe i need to use index n = 1 to 16. But i'm not sure how to use it and where to use it.

m7913d
  • 10,244
  • 7
  • 28
  • 56
sayan de sarkar
  • 185
  • 1
  • 10

2 Answers2

2

Just create an array of functions and initial guesses, as shown in the first example of the documentation for fsolve.

% Array of equations, nx1 in size for n equations. 
% Ensure that the input (x) is indexed in each equation, e.g. x(1) in eqn 1
polsim = @(x) [x(1).^2 - 1
               2*x(2) + 3];

% Array of initial guesses, corresponding element-wise to eqn array 
u0 = [0.01; 0.01];

% Solver options
options = optimset('Display','notify','MaxFunEvals',10^7,'TolX',1e-5,'TolFun',1e-6,'MaxIter',10^5);

% Solve
u = fsolve(F, u0, options);

>> u = [1.000; -1.500] % As expected for the equations in F and intial guesses 
Wolfie
  • 27,562
  • 7
  • 28
  • 55
  • As the functions are independent, it may be more efficient to solve them separately. – m7913d Jul 10 '17 at 13:55
  • Since the variables are kept independent (i.e. not using `x(1)` in equation 2) I don't see why it would necessarily slow down the solver doing it this way - there are still no dependencies? Would be interested if you could demonstrate there are performance advantages! This method just keeps things nice and clean :) – Wolfie Jul 10 '17 at 13:57
  • I performed the benchmark and created the following question about it: https://stackoverflow.com/questions/45018995/fastest-method-to-solve-multiple-nonlinear-independent-equations-in-matlab/45018996#45018996. For 16 equations, both methods have almost the same efficiency (because I used `fzero` instead of `fsolve`) – m7913d Jul 10 '17 at 18:21
  • Nice work putting that together @m7913d, looks like I'll stick to methods like I've written above, although nice tip about being able to explicitly set up `fsolve` to be independent. I wonder if @sayan might find your investigation useful. I also wonder if the benchmark equation is representative (no obvious reason why not) or if interesting things happen with more difficult equations. – Wolfie Jul 10 '17 at 21:29
0

You should rewrite your code to use vectors/cell arrays as follows:

% Write the initial point as a vector
u0(1) = .001;
        ..
u0(16) = .001;
% Write the equations as a cell array
polsim{1} = @polsim1;
        ..
polsim{16} = @polsim16;

options=optimset('Display','notify','MaxFunEvals',10^7,'TolX',1e-1,'TolFun',1e-6,'MaxIter',10^5);
u = zeros(u0); % Allocate output space for efficiency
% loop over all the equations
for i=1:length(u0)
    u(i) = fzero(polsim{i},u0(i),options);
end

Note that I used fzero instead of fsolve to improve the efficiency, see this post for more information.

Trick to automatically construct vector/cell array (Deprecated)

For completeness, I should mention that you can initialise u0 and polsim automatically using eval:

for i=1:16
    eval(['u0(', num2str(i), ') = u0', num2str(i),';']);
    eval(['polsim{', num2str(i), '} = polsim', num2str(i),';']);
end

Note that I do not recommend this method. It is much better to directly define them as a vector/cell array.

m7913d
  • 10,244
  • 7
  • 28
  • 56