# A very nonlinear system of three equations

Here's a fun little problem: determine the exponential curve f(x) = c + ba^x defined by three points, (2,10), (4,6), and (5,5).

The system of three equations and three unknowns is

10 = c + ba^2

6 = c + ba^4

5 = c + ba^5

It's not that hard to solve numerically. With a little algebraic substitution and iteration, the answer turns out to be

a = 0.640388203

b = 16.53456516

c = 3.219223594

But is there a more elegant way to use Sage to arrive at this result? I'm stumped.

edit retag close merge delete

Sort by ยป oldest newest most voted

If you just want to have a numerical solution to a small set of (nonlinear) equations, why not simply 'fsolve' them?

from scipy.optimize import fsolve

def equations(p):
a, b, c = p
return (c + b*abs(a)**2 - 10, c + b*abs(a)**4 - 6, c + b*abs(a)**5 - 5)

a,b,c = fsolve(equations, (1, 1, 1))

print a,b,c
print equations((a,b,c))
0.640388203202 16.5345651552 3.2192235936
(-2.5757174171303632e-13, -2.3625545964023331e-13,-1.9895196601282805e-13)


The 'abs()' is there to provide at least some additional constraining on a,b,c

I don't know if this is elegant - but it is straightforward.

more

Thanks. I suspect that some or all of this is Python code, and I know absolutely nothing about Python. (I'm a decent Perl coder, though.) The Sage Reference Manual has information about maple.fsolve and qfsolve, but nothing about plain old fsolve.

( 2013-09-05 17:34:02 -0500 )edit

Have you tried find_fit? Presumably with an exact fit this would work very nicely. (Let me know if you need more details or if that doesn't work.)

That said, this isn't "elegant".

more

1

Thanks! That works well enough. My first attempt gave an unexpected answer: model(x) = c+b*a^x find_fit([(2,10), (4,6), (5,5)], model) [a == -0.39038820320220763, b == 30.965434844830888, c == 5.2807764064044145] which is correct as far as it goes, but raising -0.39 to non-integer values of x results in a complex number. Giving it a non-default initial guess sussed out the expected answer: model(x) = c+b*a^x find_fit([(2,10), (4,6), (5,5)], model, initial_guess=(1,1,3)) [a == 0.6403882032022076, b == 16.534565155169098, c == 3.219223593595585] and I'm pleased with the accuracy of the result. Since this can be done with only two lines of code, I consider it more elegant than the fsolve approach (above).

( 2013-09-05 17:27:39 -0500 )edit

Yes, sometimes you do need to give it a little help! That's typical of such numerical routines.

( 2013-09-06 04:49:23 -0500 )edit

## Stats

Seen: 2,987 times

Last updated: Sep 05 '13