Ask Your Question
1

Generic Symbolic function as input in actual funciton

asked 2019-01-07 14:40:18 +0200

Fjolfrin gravatar image

updated 2019-01-07 19:33:56 +0200

tmonteil gravatar image

So I have this assignment for university, and I'm trying to write a generic Newton's method which will take any symbolic function as input. I just don't know how to declare this on the function's inputs. Here's the function I want as input:

f(x) = 14 * x * exp(x-2) - 12 * exp(x-2) - 7 * x^3 + 20 * x^2 - 26 * x + 12

and here's the function I want to create:

def Newton_Raphson(foo, start):
    dfoo = diff(foo)
    ddfoo = diff(dfoo)
    t0 = time.time()

    while foo(start) * ddfoo(start) <= 0:
        start += 10^-6

    NR = start - foo(start) / dfoo(start)
    noNR = 1

    while abs(foo(NR)) > 10^-6:
        NR = start - foo(start)/dfoo(start)
        start = NR
        error = (NR - start)
        noNR += 1

    t1 = time.time()
    tNR = t1 - t0
    return NR, noNR, error, tNR

Any ideas on this? Also do you have any other suggestions on this code?

edit retag flag offensive close merge delete

Comments

Side suggestion: semicolons are not needed. Removing them makes code more readable.

slelievre gravatar imageslelievre ( 2019-01-07 14:48:03 +0200 )edit

Old habits don't change ๐Ÿ˜›๐Ÿ˜› Yes I will remove them.

Fjolfrin gravatar imageFjolfrin ( 2019-01-07 14:49:54 +0200 )edit

Replacing a = a + b by a += b also increases readability.

slelievre gravatar imageslelievre ( 2019-01-07 14:59:59 +0200 )edit

Body of the def needs indenting.

slelievre gravatar imageslelievre ( 2019-01-07 15:00:23 +0200 )edit

If using time, add import time as first line of the function or before the function.

slelievre gravatar imageslelievre ( 2019-01-07 15:01:39 +0200 )edit

1 Answer

Sort by ยป oldest newest most voted
2

answered 2019-01-07 19:32:29 +0200

tmonteil gravatar image

updated 2019-01-08 11:00:08 +0200

Here are some remarks:

First, remove any time-related lines and variables from your function. You can later time it with:

sage: %time Newton_Raphson(f, 0.2)

or even:

sage: %timeit Newton_Raphson(f, 0.2)

so that you get a race between many executions.

Then, you might want to run something like:

sage: %time Newton_Raphson(f,1)

and see that your code is lagging.

To understand what happens, let me suggest to add some debug information just after the while statement:

print start

As you can see, the value of the start real number is expressed as a huge symbolic expression involving exponentials. So you can imagine that handling such expression and testing inequalities with them is very slow (and more and more slow since the size of the expression increases a lot at each iteration).

Since you the Newton Raphson will never reach the zero of the function exactly, wht you are looking for is an approximation, so you don not care to have a long expression for such a point whose only virtue is to be close to the zero. So, yo may want a numerical approximation. For this, you can transform each of foo, dfoo and ddfoo as functions tranforming floating-point numbers into floating-point numbers, which you can do by using the fast_float function.

So just after defining dfoo and ddfoo, it suffice to add the lines:

foo = fast_float(foo)  
dfoo = fast_float(dfoo)                        
ddfoo = fast_float(ddfoo)

Of course, you should not re-define foo before defining dfoo as Sage is not able to compute the derivative of a such numerical function, you prefer exact symbolic computations for such a computation of derivatives.

With such improvement, you can now get:

sage: %time Newton_Raphson(f,0)
CPU times: user 4 ms, sys: 0 ns, total: 4 ms
Wall time: 3.25 ms
(0.8571428346650166, 7, 0.0)

Hmm, apparently the error is zero. The reason is that in your code there is:

start = NR
error = (NR - start)

so of course the error is zero ! perhaps should you permute those two lines.

edit flag offensive delete link more

Comments

Thanks a lot! I have the exact same results. After I fixed the error thing I also get a logical result on this scope too:

0

(0.8571428346650166, 7, 9.64919707358014e-05)

Just to clarify, because I can't get the "%time" function you mentioned, what is the syntax of it? I tried to even copy an example from Sage's documentation, however I can't seem to get it to work. I have the "time" library imported. Meaning what I type exactly to get it to work? This is what I get for typing this: %time Newton_Raphson(f, 0)

Error in lines 48-48
Traceback (most recent call last):
File "/cocalc/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 1188, in execute flags=compile_flags) in namespace, locals
File "", line 1, in <module
File "/cocalc/lib/py
Fjolfrin gravatar imageFjolfrin ( 2019-01-08 11:06:01 +0200 )edit

%time is not a function, it is a "ipython magic", you can use it within the command line or a notebook.

tmonteil gravatar imagetmonteil ( 2019-01-08 11:33:01 +0200 )edit

Ok got it. Again many thanks!

Fjolfrin gravatar imageFjolfrin ( 2019-01-08 11:42:16 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2019-01-07 14:40:18 +0200

Seen: 429 times

Last updated: Jan 08 '19