As stated above I've made a newton-raphson method for finding the square root of a given number
def newton(f, fprime, eps):
x0 = 10
while True:
fx0 = f(x0)
if abs(fx0) < eps:
return x0
fpx0 = fprime(x0)
if fpx0 == 0:
return None
x0 = x0 - fx0/fpx0
I know that generally you shouldn't use a while True loop but in my case it is fine, my problem is when f(x)=logx and f'(x) = 1/x, I run the code and get a math error, I'm assuming either from logging a negative or dividing by 0. Either way some help on how to fix it would be great, as i just can't seem to find why only log is having the issue
Try changing your initial x0 guess to a value closer to the root.
x0 = 2 will give you the solution, for example.
Im setting up a while loop which should run until my value zero is equal to 0(or a very small interval near zero).
how is this written i python?
while (zero != 0 +/- k):
if zero > 0:
gamma = gamma+zero/100
if zero < 0:
gamma = gamma-zero/100
Python is a funny beast here, you can write comparisons in the "mathematical way":
while -k < zero < k:
...
You could use the built-in function abs (absolute value):
while abs(zero) > k:
gamma = gamma + abs(zero)/100
You don't need your if checks then.
So for an assignment, I'm supposed to write a function that evaluates two other functions that I previously defined in the program. How, the intricacies of this next function I must define is confusing me how I should set it up. Basically, I have determined that I have to write a while loop, but I can't decide whether to have three different conditions or if statements to evaluate this function. The thing is, the loop must end after one of the three conditions is met; I just don't know how to lay it out currently.
These are the three conditions (where only one must be met in order for the loop/function to terminate):
the absolute value of the polynomial at the current estimate is less than epsilon, in
which case the method is successful.
the absolute value of the derivative of the polynomial at the current estimate is less
than epsilon (this could lead to division by 0), in which case the method failed, or
the number of revisions of the estimate has exceeded timeout (the estimate is not
converging on a solution). This case is also a failure.
This is currently what I have as my code (and it hasn't been running obviously):
def newtonsMethod(poly, x_, epislon, timeout):
"""Calculating root of polynomial using newton's Method."""
estimate = 0
epislon = 1e-20
while (abs(evaluatePoly(poly, x_)) < epislon and \
abs(evaluatePoly(findDerivative(poly), x_)) and estimate > timeout):
estimate = x_ - (evaluatePoly(poly) / evaluatePoly(findDerivative(poly)))
x_ = estimate
print(x_)
How should I go about this? The function name is a requirement of the assignment so it cannot be changed. Also, I am a complete beginner at this stuff (just started last month) and I'm only basically required to have knowledge of data structures, loops, and if statements (and functions). So please keep your responses as simple/dumby proof as possible.
This is all the code I have before that pertains to this question:
def findDerivative(poly):
"""Find the derivative of the polynomial and return it as a list of
coefficents"""
count = 0
polyList = []
for nn in poly:
polyList += [nn * count]
count += 1
return polyList[1:]
def evaluatePoly(poly, x_):
"""Evaluates the polynomial at x = x_ and returns the result as a floating-
point number using Horner's rule"""
#http://mathworld.wolfram.com/HornersRule.html
count = 0
polyEval = []
for nn in poly:
xVal = x_**count
polyEval += [xVal * nn]
count += 1
polySum = sum(polyEval)
return float(polySum)
Edit: 10/23/2016
I should have mentioned this before or explained the assignment in more detail, but estimate is a parameter for the function because it is given as a list later on in the assignment. I have understood that timeout represents that the loop can run through so many times before it "breaks" or ends. The function is to return a two-part tuple where the first variable of the tuple is the refined x_ value and the second variable is a boolean value saying whether the method was successful or not. Using advice from both #Blckknght and #David Bowling , I was able to refine my code to the following:
def newtonsMethod(poly, x_, epsilon, timeout):
"""Calculating root of polynomial using newton's Method."""
deriv_poly = findDerivative(poly)
deriv = evaluatePoly(deriv_poly, x_)
value = evaluatePoly(poly, x_)
count = 1
while True:
x_ -= value / deriv
if abs(value) < epsilon:
boolean = abs(value) < epsilon
xTuple = (x_, boolean)
return xTuple
if abs(deriv) < epsilon or count > timeout:
boolean = abs(deriv) < epsilon or count > timeout
xTuple = (x_, boolean)
return xTuple
count += 1
However, I am still experiencing crashing problems when I run the code. I realized belatedly that I cannot have both boolean variables to equal to True (for my following code, I need boolean to equal True or False) but in order for the loop to stop, one of the if statements must equal True.
I apologize for all the confusion and specifications this code requires; I hope this explanation helps understanding what I need.
The advice given by others to break up your complicated conditional into simpler statements is very good. The logic in your original conditional was faulty, but could be adjusted to work. Yet there were other problems in your function.
There is no need to assign epsilon a value before the loop, because this value is supplied as a function parameter. estimate should be functioning as a counter, but then confusingly gets assigned the value to be used for x_ in the next iteration. I have renamed estimate as iterations in my code below.
You should have used:
abs(evaluatePoly(poly, x_)) > epsilon
since you want the loop to continue so long as the value of the polynomial evaluated at x_ is larger than epsilon. And, to avoid difficulties in the statement that updates the value of x_, you want to continue looping only if:
abs(evaluatePoly(findDerivative(poly), x_)) > epsilon
There was a missing conditional here in your original code. Finally, you want to continue looping if the number of iterations has not yet reached the timeout value. You only want to loop if all of the above conditions are met, so your conditional expression should be:
while abs(evaluatePoly(poly, x_)) > epsilon and \
abs(evaluatePoly(findDerivative(poly), x_)) > epsilon and \
iterations < timeout:
I changed your next assignment statement in two ways. First, the assignment is now made to x_ instead of the old, confusing estimate variable. Second, you were missing the second argument in both of the evaluatePoly() functions. I added a line to increment the iterations counter, and moved the print() out of the loop so that you only see the final result.
Here is the modified code:
def newtonsMethod(poly, x_, epsilon, timeout):
"""Calculating root of polynomial using newton's Method."""
iterations = 0
while abs(evaluatePoly(poly, x_)) > epsilon and \
abs(evaluatePoly(findDerivative(poly), x_)) > epsilon and \
iterations < timeout:
x_ = x_ - (evaluatePoly(poly, x_) / evaluatePoly(findDerivative(poly), x_))
iterations += 1
print(x_)
Here is a sample run using the findDerivative() and evaluatePoly() functions that you provided:
>>> xpr = [0, 0, 5]
>>> newtonsMethod(xpr, -1, 1e-20, 1000)
-2.91038304567e-11
>>> evaluatePoly(xpr, -2.91038304567e-11)
4.235164736261692e-21
Update:
I have looked at the new function definition that you posted, and found the problem. The fundamental problem in your code is that value and deriv are evaluated only once, outside the loop. You need to move these two statements inside of the loop so that they can be updated after each iteration. Also, I would move the assigment to x_ to the end of the loop so that your first guess gets tested before it is updated. You can simplify the bodies of your if statements a bit also. As it is, when you escape the function due to an unacceptably small value for deriv or a timeout, your function reports True. I assume that you want it to report False. Here is how I modified your code:
def newtonsMethod(poly, x_, epsilon, timeout):
"""Calculating root of polynomial using newton's Method."""
deriv_poly = findDerivative(poly)
count = 1
while True:
deriv = evaluatePoly(deriv_poly, x_)
value = evaluatePoly(poly, x_)
if abs(value) < epsilon:
boolean = True
return (x_, boolean)
if abs(deriv) < epsilon or count > timeout:
boolean = False
return (x_, boolean)
x_ -= value / deriv
count += 1
Here is a sample run:
>>> xpr = [0, 0, 5]
>>> newtonsMethod(xpr, -1, 1e-20, 1000)
(-2.9103830456733704e-11, True)
>>> evaluatePoly(xpr, -2.9103830456733704e-11)
4.235164736271502e-21
I am guessing that the slight difference between these results and the earlier results is due to rounding errors and the differing procedures for calculation.
As Barmar commented, using a simpler while condition (possible just while True) is almost always better than a very complicated condition that can't even fit on one line. You'd put the actual logic for ending the loop in one or more if statements inside the loop body:
while True: # no condition here
# do stuff
if failure_condition1():
break # stop looping
if success_condition():
return result() # another way to stop looping is to return a value
if failure_condition2():
raise SomeException() # you could also raise an exception on failure
# do other stuff
Any combination of return, raise or break could be correct for your function, it depends exactly what you want to do when each condition is met (and what you want the API to be).
One advantage to this style of loop is that you can check the conditions wherever it makes sense in your algorithm. The test doesn't have to be at the start of the loop (which often requires you to initialize your variables with made up values that will pass the condition the first time through).
Here's how I'd apply this kind of control flow in your specific problem:
def newtonsMethod(poly, x_, timeout):
"""Calculating root of polynomial using newton's Method."""
estimate = 0
epsilon = 1e-20
deriv_poly = findDerivative(poly)
while True:
value = evaluatePoly(poly, x_)
if abs(value) < epsilon:
return x_
deriv = evaluatePoly(deriv_poly, x_)
if abs(deriv) < epsilon or estimate > timeout:
raise ValueError("Not converging")
#print(x_, value, deriv)
x_ -= value / deriv
estimate += 1
Note that we only need to call evaluatePoly twice per pass, since we save the results rather than recomputing them.
I also fixed a few errors in your code. I use estimate as a counter, rather than an alias for x_ and no longer have epsilon as a parameter that is overwritten in the function body (you also had it misspelled as epislon).
In python, I would like to find the roots of equations of the form:
-x*log(x) + (1-x)*log(n) - (1-x)*log(1 - x) - k = 0
where n and k are parameters that will be specified.
An additional constraint on the roots is that x >= (1-x)/n. So just for what it's worth, I'll be filtering out roots that don't satisfy that.
My first attempt was to use scipy.optimize.fsolve (note that I'm just setting k and n to be 0 and 1 respectively):
def f(x):
return -x*log(x) + (1-x)*log(1) - (1-x)*log(1-x)
fsolve(f, 1)
Using math.log, I got value-errors because I was supplying bad input to log. Using numpy.log gave me some divide by zeros and invalid values in multiply.
I adjusted f as so, just to see what it would do:
def f(x):
if x <= 0:
return 1000
if x >= 1:
return 2000
return -x*log(x) + (1-x)*log(1) - (1-x)*log(1-x)
Now I get
/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py:221: RuntimeWarning: The iteration is not making good progress, as measured by the
improvement from the last ten iterations.
warnings.warn(msg, RuntimeWarning)
Using python, how can I solve for x for various n and k parameters in the original equation?
fsolve also allows guesses to be inserted for where to start. My suggestion would be to plot the equation and have the user type a initial guess either with the mouse or via text to use as an initial guess. You may also want to change the out of bounds values:
if x <= 0:
return 1000 + abs(x)
if x >= 1:
return 2000 + abs(x)
This way the function has a slope outside of the region of interest that will guide the solver back into the interesting region.
Successive approximation is a general method in which on each iteration of an algorithm, we find a closer estimate of the answer for which we are seeking. One class of successive approximation algorithms uses the idea of a fixed point. If f(x) is a mathematical function, then finding the x such that f(x) = x gives us the fixed point of f.
One way to find a fixed point is to start with some guess (e.g. guess = 1.0) and, if this is not good enough, use as a next guess the value of f(guess). We can keep repeating this process until we get a guess that is within epsilon of f(guess).
here's my code:
def fixedPoint(f, epsilon):
"""
f: a function of one argument that returns a float
epsilon: a small float
returns the best guess when that guess is less than epsilon
away from f(guess) or after 100 trials, whichever comes first.
"""
guess = 1.0
for i in range(100):
if abs(f(guess) - guess) < epsilon:
return guess
else:
guess = f(guess)
return guess
further now...
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit, 0.0001)
I want to compute square root of a number "a", is the fixed point of the function f(x) = 0.5 * (a/x + x). AND DONE.
(Above solutions are correct)
Successive approximation is a general method in which on each iteration of an algorithm, we find a closer estimate of the answer for which we are seeking. One class of successive approximation algorithms uses the idea of a fixed point. If f(x) is a mathematical function, then finding the x such that f(x) = x gives us the fixed point of f.
One way to find a fixed point is to start with some guess (e.g. guess = 1.0) and, if this is not good enough, use as a next guess the value of f(guess). We can keep repeating this process until we get a guess that is within epsilon of f(guess).
example in python:
def fixedPoint(f, epsilon):
"""
f: a function of one argument that returns a float
epsilon: a small float
returns the best guess when that guess is less than epsilon
away from f(guess) or after 100 trials, whichever comes first.
"""
guess = 1.0
for i in range(100):
if -epsilon < f(guess) - guess < epsilon:
return guess
else:
guess = f(guess)
return guess
further let function f be for finding square root using babylon method:
def sqrt(a):
def babylon(x):
def test(x):
return 0.5 * ((a / x) + x)
return test(x)
return fixedPoint(babylon, 0.0001)
You might want to take a look at the optimization and root-finding functions in scipy.
Especially scipy.optimize.fixed_point. The actual source code is here.