# NSolve not returning anything

I am trying to manipulate the function $f(x)=a-b\exp(-xc)$, where $a,b$ and $c$ are parameters and $x$ my variable. I want to fix the value and gradient at $f(x=1400)$ and the value at $f(x>4000)$. Here's how I am doing it:

NSolve[{
((a - b*Exp[-c*x]) /. x -> 1400) == 0.129417,
((a - b*Exp[-c*x]) /. x -> 4000) == 0.26304,
(D[(a - b*Exp[-c*x]), x] /. x -> 1400) == 0.0002219136
}, {a, b, c}]


However, NSolve isn't returning anything and eventually fails. Is there a different function in Mathematica appropriate for this problem?

• If you have some initial guess, you can use FindRoot. Commented Oct 27, 2017 at 17:29

The following works (The initial values were found by trials.).

FindRoot[{((a-b*Exp[-c*x]) /. x -> 1400)==0.129417,((a - b*Exp[-c*x])/.x -> 4000)==0.26304,
(D[(a - b*Exp[-c*x]), x] /. x -> 1400) == 0.0002219136}, {a,0.2}, {b, .03}, {c, .00009},
WorkingPrecision -> 20,AccuracyGoal -> 3]


{a->0.26496040221501131952,b->1.3412964939715005005,c->0.0016372143267284541222}

Verification confirms it.

{((a - b*Exp[-c*x]) /. x -> 1400), ((a - b*Exp[-c*x]) /.
x -> 4000), (D[(a - b*Exp[-c*x]), x] /. x -> 1400)} /.
{a -> 0.26496040221501131952, b -> 1.3412964939715005005, c -> 0.0016372143267284541222}


0.1294169999999148617, 0.2630399999999959833, 0.0002219136000000732043}

Addition. The FindRoot also works with the initial values {a, 1.}, {b, 1.}, {c, .0001}. The initial values of a and b are taken $1$ as usually, the initial value of c is chosen in such awy that $1000c \approx 1$.

If you don't have any initial guess that works, but it seems reasonable that a solution should exist, then rewriting the problem to solve for one fit variable at a time may also work. If there isn't a solution, this process is a fair bit more likely to show that than FindRoot is as well.

f[a_,b_,c_] := a-b Exp[-# c]& (* this defines the family of functions of f *)


Solve for b by implementing the gradient constraint at the first x point.

solb = First@Solve[f[a,b,c]'[x1]==g,b]


Solve for a by implementing the y value constraint at the first x point and the b constraint.

sola = First@Solve[f[a,b,c][x1]==y1/.solb,a]


Solve for c by implementing the y value constraint at the second x point and the previous 2 solutions.

solc = First@Solve[f[a,b,c][x2]==y2/.solb/.sola,c]


Now insert the numerical parameters:

params = {x1->1400,x2->4000,y1->0.129417,y2->0.26304,g->0.0002219136};


And expand the previous solutions:

nc = solc/.params;
nb = solb/.params/.nc;
na = sola/.params/.nc/.nb;
nsol = Flatten[{na,nb,nc}]


nsol should contain {a->0.26496,b->1.3413,c->0.00163721}.

(f[a,b,c]/.nsol)[x] will generate the final function in terms of x.

In my experience normally if this process would work, then Solve is probably able to solve a symbolic version of this problem as well, but that doesn't appear to be true in this case.

\$Version

(* "11.2.0 for Mac OS X x86 (64-bit) (September 11, 2017)" *)


Rationalize and Simplify the equations

eqns = {((a - b*Exp[-c*x]) /. x -> 1400) == 0.129417,
((a - b*Exp[-c*x]) /. x -> 4000) == 0.26304,
(D[(a - b*Exp[-c*x]), x] /. x -> 1400) == 0.0002219136} //
Rationalize[#, 0] & // Simplify;


Restrict NSolve to the real domain

(sol = NSolve[eqns, {a, b, c}, Reals][[1]]) // AbsoluteTiming

(* {16.7754, {a -> 0.26496, b -> 1.3413, c -> 0.00163721}} *)


Verifying the solutions

And @@ (eqns /. sol)

(* True *)

• The Simplify command may be omitted. Commented Oct 27, 2017 at 19:20
• @user64494 - while it is not necessary, it makes the equations "cleaner". It is just a matter of personal preference. Commented Oct 27, 2017 at 19:23