Is it possible to set an upper limit on the step size used by fsolve?

26 views (last 30 days)
I'm trying to use fsolve to solve a small nonlinear system (3 equations) for which I have constraints on the unknowns. I know I can't explicitely enforce constraints using fsolve, but I always have access to a good initial guess, which generally allows the solver to find the solution I need without looking outside the constraints boundaries.
However, changing the equation parameters (which I need to be able to do) sometimes results in fsolve trying to find a solution outside the boundaries, which is not acceptable.
I've tried using fmincon with the same initial guesses as fsolve without success: without applying constraints, it tends to search outside the constraints boundaries and make the solution crash faster than fsolve. With the constraints, it's unable to find the solution because it gets stuck on a boundary.
I'm thinking that if I could add some kind of relaxation in the fsolve algorithm, it could help me stay inside my constraints (without guarantees, of course). In other words, I'm trying to find if there's a way to limit the step size taken by fsolve from one iteration to another. I've found the following options in the documentation, but they do not do what I need:
- FiniteDifferenceStepSize: this allows to set the step size used to estimate the gradient inside a given fsolve iteration, but offers no control on the step taken on the solution vector from one iteration to another
- StepTolerance: this is a lower bound on the step size from one iteration to another (what I'm looking is an upper bound on that value)
Basically, I'd like fsolve to estimate the gradient, but let me decide how far along that gradient I want to go. Is there any other option, or even other solver I didn't think of that could do something like that?
Thank you

Accepted Answer

Matt J
Matt J on 9 Sep 2021
Edited: Matt J on 9 Sep 2021
I've tried using fmincon with the same initial guesses as fsolve without success:
A simpler option than fmincon would be to use lsqnonlin, which is quite similar to fsolve except that it allows you to stipulate simple upper and lower bounds.
With the constraints, it's unable to find the solution because it gets stuck on a boundary.
Based on your description, I'm skeptical that the solver is "getting stuck". It sounds to me like the unconstrained solution really is outside the boundaries, and the constrained solution really is at the boundary. If I'm correct, tweaking the search mechanism will not help. Your equations themselves are the problem. There is some error or physical information lacking in the equations that would lead to a solution in the expected region.
One way to verify this would be to sample your equation function on a grid covering the bounded region. This is something that should be computationally tractable since you have only 3 unknowns. This will let you inspect directly where the solution lies (to within the resolution of the sampling grid).
  3 Comments
Matt J
Matt J on 10 Sep 2021
Edited: Matt J on 10 Sep 2021
But at some point, when everything is converging smoothly, it starts to take very large steps and searches for a solution where the film thickness becomes locally negatives.
Sounds like some discontinuous change occurred in the capture regions of your optimization problem. In other words, you are hoping that the solution to the previous optimization will give you an initial point lying in the capture region of the global solution to the new problem. This may be true much of the time, but there really is no gaurantee.
One solution may be to come up with a more independent way to generate an initial guess. For your toy problem, it is very simple to do so, as below. I don't know if something analogous is possible in your true problem.
% Initial guess and bounds
x1=linspace(0,1,1000);
x2=sin(1.5*pi*x1);
loc=abs(x1.^2.*x2 - 0.1)<=1e-4 & x1>=0 & x2>=0 & x1+x2<=1;
x0=[x1(loc), x2(loc)]
x0 = 1×2
0.6086 0.2702
% fsolve solution
opts = optimoptions(@fsolve,'FunctionTolerance',1e-12,'Display','off');
x_fsolve = fsolve(@fbnd,x0,opts)
x_fsolve = 1×2
0.6087 0.2699
% fmincon solution
A = [1,1];
b = 1;
lb = [0,0];
opts = optimoptions(@fmincon,'Algorithm','interior-point','Display','off',...
'OptimalityTolerance',1e-12);
x_fmincon = fmincon(@(x)norm(fbnd(x)).^2,x0,A,b,[],[],lb,[],[],opts)
x_fmincon = 1×2
0.6087 0.2699
% Objective functions
function F = fbnd(x)
F(1) = x(1)^2*x(2) - 0.1;
F(2) = sin(1.5*pi*x(1)) - x(2);
end
% Objectives functions as nonlinear equality constraints for fmincon
if I always reset the initial guess for fsolve at the values used on iteration 0, fsolve never tries to take large steps and always remain inside the constraints, and the global simulation converges. Of course this requires more solutions of the pressure PDE as fsolve always start further from the desired solution.
Maybe you can use this as a fallback initialization strategy only in the case where the optimization fails. Maybe it will be necessary only in rare instances, when discontinuous changes in the capture regions occur.
Jean-Philippe Gauthier
Jean-Philippe Gauthier on 13 Sep 2021
One solution may be to come up with a more independent way to generate an initial guess. For your toy problem, it is very simple to do so, as below. I don't know if something analogous is possible in your true problem.
I've tried doing something similar by evaluating a few points inside the constrained parameter space and keeping the best point as the initial guess for fsolve, but it's not very robust. I don't have explicit expressions for my equations, which also change between global iteration as other parts of the solution evolve. The best option I've found so far really is to use the same initial guess every time.
Maybe you can use this as a fallback initialization strategy only in the case where the optimization fails. Maybe it will be necessary only in rare instances, when discontinuous changes in the capture regions occur.
I think this is the best approach right now. The code performs very well for most cases as it is, so I'll just include special treatment when this problem, which should indeed be rare, arises.

Sign in to comment.

More Answers (1)

Matt J
Matt J on 13 Sep 2021
Edited: Matt J on 13 Sep 2021
You could try playing with the InitDampling option parameter used by the Levenberg-Marquardt method.

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!