Improving Newton's Method Recursion - python

I have solved a previous problem and now I am stuck with this one.
It is asking for an improvement of the previous solution which I posted below, but can't quite understand what the problem is asking. (Also, can't really figure out how to solve it.)
Please help
thanks.
Problem:
Elena complains that the recursive newton function in Project 2 includes
an extra argument for the estimate. The function’s users should not have to
provide this value, which is always the same, when they call this function.
Modify the definition of the function so that it uses a keyword parameter
with the appropriate default value for this argument, and call the function
without a second argument to demonstrate that it solves this problem.
Here is my code:
def newtonSquare(x, estimate):
if abs(x-estimate ** 2) <= 0.000001:
return estimate
else:
return newtonSquare(x, (estimate + x / estimate) / 2)
def main():
num = int(raw_input('Enter a positive number >> '))
print newtonSquare(num, 1.0)
main()

The problem is a complaint that when somebody calls newtonSquare, they always do so with an initial estimate of 1.0. To set it as the default value, unless you explicitly provide it, you only have to modify the definition of the function to:
def newtonSquare(x, estimate = 1.0):

An alternative to the default value solution of Michael's is defining the recursive function local to the newtonSquare function:
def newtonSquare(x):
def f(x, estimate):
if abs(x-estimate ** 2) <= 0.000001:
return estimate
else:
return f(x, (estimate + x / estimate) / 2)
return f(x, 1.0)
def main():
num = int(raw_input('Enter a positive number >> '))
print newtonSquare(num)
main()
In this case having the default value is nicer and more flexible though, but this can still be a useful pattern.

Related

Is there a way to do something only in non-recursive function?

If I have some function like that:
def function(some number, steps):
if steps == 1: return 1
result = some calculation + function(some number, steps - 1)
return round(result, 2)
which returns some float number.
My question is: Is there a way to return rounded result only when I return result from whole function but not from recursive call (to save precision to calculation).
I hope you understand my question.
Thanks in advance.
Generally speaking, if you want to detect that you are inside a recursive call in Python, you can add a default parameter to the function like so:
def my_func(arg1, arg2, _inside_recursion=False):
# Default calls will have _inside_recursion as False
# Make sure that your recursive calls set the parameter
recursive_result = my_func(arg1, arg2, _inside_recursion=True)
Yes! You can provide a flag that will get triggered for consecutive calls:
def function(some number, steps, do_rounding=True):
if steps == 1:
return 1
result = some calculation + function(some number, steps - 1, False)
if do_rounding:
return round(result, 2)
else:
return result
There's no way you can distinguish whether your current function is being invoked as part of the recursion or as it's first step. You can, however, just introduce a new function which will call the existing one and do any extra rounding.
def internal_function(some number, steps):
if steps == 1: return 1
return some calculation + function(some number, steps - 1)
def function(some_number, steps):
return round(internal_function(some_number, steps), 2)
Edit: while true that the approach with adding an optional argument to the function can serve as well it has two downsides:
pollutes the public interface of the function - your users are now wondering whether they should give the argument a value and what value should they give exactly
makes the computational part longer to read and can also potentially destroy tail-call optimizations.
Maybe you want something like this? This is not equivalent to OP code, but makes sense. It applies some_calculation recursively steps times and rounds the final value.
def function(x, steps):
if steps == 1: return round(x, 2)
return function(some_calculation(x), steps - 1)

Python recursion evaluate only if necessary

Say I have these two functions:
def s(x,y,z):
if x <= 0:
return y
return z
def f(a,b):
return s(b, a+1, f(a,b-1)+1)
If I were to try and find f(5,2) in my head, it would go like this:
f(5,2) = s(2,6,f(5,1)+1)
f(5,1) = s(1,6,f(5,0)+1)
f(5,0) = s(0,6,f(5,-1)+1) = 6
f(5,1) = 7
f(5,2) = 8
I never evaluate f(5,-1) because it is not needed. The s function is going to return 6, since argument x is zero, thus evaluation of argument z is unnecessary.
If I were however to try and run this in python, it would keep recursing forever or or until I get a maximum recursion depth error, presumably because python wants to evaluate all the arguments before executing the s function.
My question is, how would I go about implementing these functions, or any similar scenario, in such a way that the recursion stops when it is no longer needed? Would it be possible to delay the evaluation of each argument until it is used in the function?
Your mind is working with 'insider knowledge' of how s() works. Python can't, so it can only follow the strict rules that all argument expressions to a call will have to be evaluated before the call can be made.
Python is a highly dynamic language, and at every step of execution, both s and f can be rebound to point to a different object. This means Python can't optimise recursion or inline function logic. It can't hoist the if x <= 0 test out of s() to avoid evaluating the value for z first.
If you as a programmer know the third expression needs to be avoided in certain circumstances, you need to make this optimisation yourself. Either merge the logic in s into f manually:
def f(a, b):
if b <= 0:
return a + 1
return f(a, b - 1) + 1
or postpone evaluating of the third expression until s() has determined if it needs to be calculated at all, by passing in a callable and make s responsible for evaluating it:
def s(x, y, z):
if x <= 0:
return y
return z() # evaluate the value for z late
def f(a, b):
# make the third argument a function so it is not evaluated until called
return s(b, a+1, lambda: f(a, b - 1) + 1)
When a function is called, all arguments are fully evaluated before they're passed to the function. In other words, f(5,-1) is being executed before s is even started.
Fortunately there's an easy way to evaluate expressions on demand: functions. Instead of passing the result of f(a,b-1) to z, pass it a function that computes that result:
def s(x,y,z):
if x <= 0:
return y
return z() # z is a function now
def f(a,b):
return s(b, a+1, lambda:f(a,b-1)+1)
print(f(5,2)) # output: 8

Python fsolve tempering with object

I wrote a script in Python that finds the zero of a fairly complicated function using fsolve. The way it works is as follows. There is a class that simply stores the parameter of the function. The class has an evaluate method that returns a value based on the stored parameter and another method (inversion) that finds the parameter at which the function takes the supplied output.
The inversion method updates the parameter of the function at each iteration and it keeps on doing so until the mismatch between the value returned by the evaluate method and the supplied value is zero.
The issue that I am having is that while the value returned by the inversion method is correct, the parameter, that is part of the object, is always 0 after the inversion method terminates. Oddly enough, this issue disappears if I use root instead of fsolve. As far as I know, fsolve is just a wrapper for root with some settings on the solver algorithm and some other things enforced.
Is this a known problem with fsolve or am I doing something dumb here? The script below demonstrates the issue I am having on the sine function.
from scipy.optimize import fsolve, root
from math import sin, pi
class invertSin(object):
def __init__(self,x):
self.x = x
def evaluate(self):
return sin(self.x)
def arcsin_fsolve(self,y):
def errorfunc(xnew):
self.x = xnew
return self.evaluate() - y
soln = fsolve(errorfunc, 0.1)
return soln
def arcsin_root(self,y):
def errorfunc(xnew):
self.x = xnew
return self.evaluate() - y
soln = root(errorfunc, 0.1, method = 'anderson')
return soln
myobject = invertSin(pi/2)
x0 = myobject.arcsin_fsolve(0.5) #find x s.t. sin(x) = 0.5 using fsolve
print(x0) #this prints pi/6
x0obj = myobject.x
print(x0obj) #this always prints 0 no matter which function I invert
myobject2 = invertSin(pi/2)
x1 = myobject2.arcsin_root(0.5) #find x s.t. sin(x) = 0.5 using root
print(x1) #this prints pi/6
x1obj = myobject2.x
print(x1obj) #this prints pi/6
If you add print statements for xnew in the errorfunc then you will see that fsolve works with a list (of one element). This means that the function is re-interpreted that way, not the original function. Somehow the type information is lost after exiting the solver so that then the address/reference to that list is interpreted as floating point data, which gives the wrong value.
Setting self.x = xnew[0] there restores the desired behavior.

why is there this TypeError?

i am trying to find the square root a number through the function sqrt(a). fixedPoint(f, epsilon) is a helper function. the problem is that i get a this TypeError: 'float' object is not callable. i am new to programming, so if anybody can help and find were is the bug and explain what does this error mean ??
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
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit(a), 0.0001)
In sqrt function, the code is passing the return value of the tryit (which is a float value), not tryit itself.
Passing the function itself will solve the problem.
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit, 0.0001)

How can I pass functions or operators as arguments to a function in Python?

...while still leaving it executable within the function.
The idea behind this is I want to create a summation function. Here's what I have so far:
def summation(n, bound, operation):
if operation is None and upper != 'inf':
g = 0
for num in range(n, limit + 1):
g += num
return g
else:
pass
But summations are most often about infinite convergent series (for which I use 'inf'), with operations applied to each term. Ideally, I'd like to be able to write print summation(0, 'inf', 1 / factorial(n)) and get the mathematical constant e, or def W(x): return summation(1, 'inf', ((-n) ** (n - 1)) / factorial(n)) to get the Lambert W function.
All that comes to my mind is passing the appropriate arithmetic as a string and then using the exec statement to execute it. But I don't think that would accomplish the whole thing, and it's obviously dangerous to use exec with possibly user-entered code.
In Python, functions are first-class, which is to say they can be used and passed around like any other values, so you can take a function:
def example(f):
return f(1) + f(2)
To run it, you could define a function like this:
def square(n):
return n * n
And then pass it to your other function:
example(square) # = square(1) + square(2) = 1 + 4 = 5
You can also use lambda to avoid having to define a new function if it's a simple expression:
example(lambda n: n * n)

Categories