writing multiple data calculated from a function in the same file - python

I am trying to write a data calculated from this function in a file. But the function is called number of times. Say there are 9 numbers in another file and this function will calculate the root for each of those 9 numbers. These 9 roots from this function should be written in the same file. But the way I have done it here will write calculated root in the file but the next one will replace this in the file. There are other mathematical functions that are carried out for each of those 9 numbers before this function is called therefore the functions are called again and again separately.Is it possible to write them all in the same file? Thank you.
def Newton(poly, start):
""" Newton's method for finding the roots of a polynomial."""
x = start
poly_diff = poly_differentiate(poly)
n = 1
counter = 0
r_i = 0
cFile = open("curve.dat", "w")
while True:
if (n >= 0) and (n < 1):
break
x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
if x_n == x:
break
x = x_n # this is the u value corresponding to the given time
n -= 1
counter += 1
x = str(x)
cFile.write('\n' + x + '\n')
if r_i:
print "t(u) = ", (x, counter)
else:
print "t(u) = ", x
cFile.close
After following the suggestions I got I changed the code to the following:
def Newton(poly, start):
""" Newton's method for finding the roots of a polynomial."""
x = start
poly_diff = poly_differentiate(poly)
n = 1
counter = 0
while True:
if (n >= 0) and (n < 1):
break
x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
if x_n == x:
break
x = x_n # this is the u value corresponding to the given time
n -= 1
counter += 1
yield x
Bezier(x)
def Bezier(u_value) :
""" Calculating sampling points using rational bezier curve equation"""
u = u_value
p_u = math.pow(1 - u, 3) * 0.7 + 3 * u * math.pow(1 - u, 2) * 0.23 \
+ 3 * (1 - u) * math.pow(u, 2) * 0.1 + math.pow(u, 3) * 0.52
p_u = p_u * w
d = math.pow(1 - u, 3) * w + 3 * u * w * math.pow(1 - u, 2) + 3 * (1 - u) *\
w * math.pow(u, 2) + math.pow(u, 3) * w
p_u = p_u / d
yield p_u
plist = list (p_u)
print plist
I followed the same thing in the Bezier() function but plist is not created as it doesn't print anything. Please help. Thank you.

Your function does two things: It calculates the roots of a polynomial, and it writes the result to an output file. Functions should ideally do one thing.
So, try breaking this up into a function that receives a polynomial and returns a list containing the roots, and then just write that list to a file in one step.
The simplest way to modify your function would be to replace the lines
x = str(x)
cFile.write('\n' + x + '\n')
with
yield x
Then you can call your function like this:
roots = list(Newton(polynomial, start))
To understand this, read about generators. To write the resulting list to a file, you can use this code:
with open("curve.dat", "w") as output_file:
output_file.write("\n".join(str(x) for x in roots)

While I'm not completely understanding what you are asking I think the answer can be boiled down to:
Open the file in append mode, not in write mode. So instead of
cFile = open("curve.dat", "w")
do
cFile = open("curve.dat", "a")

why use yield in Bezier, it doesn't return multiple values, so you can change:
yield p_u
plist = list (p_u)
print plist
to:
print list(p_u)
return p_u

Related

How to calculate sum of terms of Taylor series of sin(x) without using inner loops or if-else?

I can't use inner loops
I can't use if-else
I need to compute the following series:
x - x^3/3! + x^5/5! - x^7/7! + x^9/9! ...
I am thinking something like the following:
n =1
x =0.3
one=1
fact1=1
fact2=1
term =0
sum =0
for i in range(1, n+1, 2):
one = one * (-1)
fact1 = fact1*i
fact2 = fact2*i+1
fact = fact1*fact2
x = x * x
term = x/fact
sum = sum + term
But, I am finding hard times in keeping the multiplications of both fact and x.
You want to compute a sum of terms. Each term is the previous term mutiplied by -1 * x * x and divided by n * (n+1). Just write it:
def func(x):
eps = 1e-6 # the expected precision order
term = x
sum = term
n = 1
while True:
term *= -x * x
term /= (n+1) * (n+2)
if abs(term) < eps: break
sum += term
n += 2
return sum
Demo:
>>> func(math.pi / 6)
0.4999999918690232
giving as expected 0.5 with a precision of 10e-6
Note: the series is the well known development of the sin function...
Isn't that a Taylor series for sin(x)? And can you use list comprehension? With list comprehension that could be something like
x = 0.3
sum([ (-1)**(n+1) * x**(2n-1) / fact(2n-1) for n in range(1, numOfTerms)])
If you can't use list comprehension you could simply loop that like this
x=0.3
terms = []
for n in range(1, numberOfTerms):
term = (-1)**(n+1)*x**(2n-1)/fact(2n-1)
terms.append(term)
sumOfTerms = sum(terms)
Then calculating the factorial by recursion:
def fact(k):
if (k == 1):
return n
else:
return fact(k-1)*k
Calcualting the factorial using Striling's approximation:
fact(k) = sqrt(2*pi*k)*k**k*e**(-k)
No if-else here nor inner loops. But then there will be precision errors and need to use math lib to get the constants or get even more precision error and use hard coded values for pi and e.
Hope this can help!
n = NUMBER_OF_TERMS
x = VALUE_OF_X
m = -1
sum = x # Final sum
def fact(i):
f = 1
while i >= 1:
f = f * i
i = i - 1
return f
for i in range(1, n):
r = 2 * i + 1
a = pow (x , r)
term = a * m / fact(r);
sum = sum + term;
m = m * (-1)

Why doesn't SymPy simplify the expression?

I am just looking at the Python module SymPy and try, as a simple (useless) example the fit of a function f(x) by a function set g_i(x) in a given interval.
import sympy as sym
def functionFit(f, funcset, interval):
N = len(funcset) - 1
A = sym.zeros(N+1, N+1)
b = sym.zeros(N+1, 1)
x = sym.Symbol('x')
for i in range(N+1):
for j in range(i, N+1):
A[i,j] = sym.integrate(funcset[i]*funcset[j],
(x, interval[0], interval[1]))
A[j,i] = A[i,j]
b[i,0] = sym.integrate(funcset[i]*f, (x, interval[0], interval[1]))
c = A.LUsolve(b)
u = 0
for i in range(len(funcset)):
u += c[i,0]*funcset[i]
return u, c
x = sym.Symbol('x')
f = 10*sym.cos(x)+3*sym.sin(x)
fooset=(sym.sin(x), sym.cos(x))
interval = (1,2)
print("function to approximate:", f)
print("Basic functions:")
for foo in fooset:
print(" - ", foo)
u,c = functionFit(f, fooset, interval)
print()
print("simplified u:")
print(sym.simplify(u))
print()
print("simplified c:")
print(sym.simplify(c))
The result is the fit function u(x), to be returned, together with the coefficients by functionFit.
In my case
f(x) = 10 * sym.cos(x) + 3 * sym.sin(x)
and I want to fit it according to a linear combination of sin(x), cos(x).
So the coefficients should be 3 and 10.
The result is OK, but for u(x) I get
u(x) = (12*sin(2)**2*sin(4)*sin(x) + 3*sin(8)*sin(x) + 12*sin(2)*sin(x) + 40*sin(2)**2*sin(4)*cos(x) + 10*sin(8)*cos(x) + 40*sin(2)*cos(x))/(2*(sin(4) + 2*sin(2))) :
Function to approximate: 3*sin(x) + 10*cos(x)
Basic functions:
- sin(x)
- cos(x)
Simplified u: (12*sin(2)**2*sin(4)*sin(x) + 3*sin(8)*sin(x) + 12*sin(2)*sin(x) + 40*sin(2)**2*sin(4)*cos(x) + 10*sin(8)*cos(x) + 40*sin(2)*cos(x))/(2*(sin(4) + 2*sin(2)))
Simplified c: Matrix([[3], [10]])
which is indeed the same as 10 * cos(x) + 3 * sin(x).
However I wonder why it is not simplified to that expression. I tried several simplifying function available, but none of it gives the expected result.
Is there something wrong in my code or are my expectations to high?
Don't know if this is a solution for you, but I'd simply use the .evalf method of every Sympy expression
In [26]: u.simplify()
Out[26]: (12*sin(2)**2*sin(4)*sin(x) + 3*sin(8)*sin(x) + 12*sin(2)*sin(x) + 40*sin(2)**2*sin(4)*cos(x) + 10*sin(8)*cos(x) + 40*sin(2)*cos(x))/(2*(sin(4) + 2*sin(2)))
In [27]: u.evalf()
Out[27]: 3.0*sin(x) + 10.0*cos(x)
In [28]:

Simpson's Rule Takes Forever to Run in Python

I've written the following function for estimating the definite integral of a function with Simpson's Rule:
def fnInt(func, a, b):
if callable(func) and type(a) in [float] and type(b) in [float]:
if a > b:
return -1 * fnInt(func, b, a)
else:
y1 = nDeriv(func)
y2 = nDeriv(y1)
y3 = nDeriv(y2)
y4 = nDeriv(y3)
f = lambda t: abs(y4(t))
k = f(max(f, a, b))
n = ((1 / 0.00001) * k * (b - a) ** 5 / 180) ** 0.25
if n > 0:
n = math.ceil(n) if math.ceil(n) % 2 == 0 else math.ceil(n) + 1
else:
n = 2
x = (b - a) / n
ans = 0
for i in range(int((n - 4) / 2 + 1)):
ans += (x / 3) * (4 * func(a + x * (2 * i + 1)) + 2 * func(a + x * (2 * i + 2)))
ans += (x / 3) * (func(a) + 4 * func(a + x * (n - 1)) + func(b))
return ans
else:
raise TypeError('Data Type Error')
It seems, however, that whenever I try to use this function, it takes forever to produce an output. Is there a way that I can rewrite this code in order to take up less time?
As one of the comments mentioned, profiling the code will show you the slowdowns. Perhaps nDeriv is slow. If you don't have a profiling tool, you can put time() calls around each section of code and print the results. More info here: Measure time elapsed in Python?
So, if the slowdown ends up being in your for loop, here are a few things you can try:
Python might be computing the loop condition every iteration:
for i in range(int((n - 4) / 2 + 1)):
calculate int((n - 4) / 2 + 1) once before the loop.
Don't recalculate stuff inside the loops that doesn't change. For example, x / 3 is going to be recalculated every loop iteration, but it never changes. Do it before the loop starts.
Likewise, you're doing 2 * i twice every loop iteration.
Addition is faster than multiplication. The func arguments could be re-written as:
xi = x * i
a1 = a + xi + xi + x
a2 = a1 + x
and then taking it a step further, you could also re-do xi as an accumulator. That is, start with x = 0, then every iteration simply x += x
This is probably obvious, but if func() is difficult to calculate, this function will be exponentially slow.
Python may be doing a lot of simpler optimizations for you, so these may not help, but just wanted to share some ideas.

(NameError: global name is not defined) error over passing a list to a function

I am sorry to post a long code. I have extracted the parts of my code where the list lower_lip_under_upper_list_plist is generated and used. There is an error of linking the functions where this list has been used. Thegenerate_t_u() function is called inside time() function but time() function wouldn't recognize this list as its not been passed there. But if I pass it in this function then I have to make changes in the main as well. And again I will get the same error.
def time(transcriptionFile) :
""" This function changes the time values in secs from the transcription file and keeps a list of start time for each phoneme. """
with open("transcriptions.txt", "r") as tFile :
timeList = []
t_u = 0.0
for line in tFile :
li = line.split()
if li :
start_time = (int(li[0]) / 10000000.)
timeList.append(start_time)
#print timeList
generate_t_u(timeList, lower_lip_under_upper_list_plist)
def generate_t_u(timeList, lower_lip_under_upper_list_plist)
""" It generates the regular time intervals t(u) values for sampling. """
i = 0
while i < len(timeList) - 1 :
# if the number is in the range
# do the calculations and move to the next number
if t_u > timeList[i] and t_u < timeList[i + 1] :
#print "\n The t_u value:", t_u, 'is between',
#print "start:", timeList[i], " and end: ", timeList[i+1]
poly = poly_coeff(timeList[i], timeList[i + 1], t_u)
Newton(poly, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
t_u = t_u + 0.04 # regular time interval
# if the number is at the lower boundary of the range, no need of calculation as u = 0
elif t_u == timeList[i] :
#print "\n The t_u value:", t_u, 'is on the boundary of',
#print "start:", timeList[i], " and end: ", timeList[i+1]
#print "u : 0"
lower_lip_under_upper_list_bezier(0, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
t_u = t_u + 0.04 # regular time interval
# if the number is at the upper boundary of the range, no need of calculation as u = 1
elif t_u == timeList[i + 1] :
#print "\n The t_u value:", t_u, 'is on the boundary of',
#print "start:", timeList[i], " and end: ", timeList[i+1]
#print " u : 1"
lower_lip_under_upper_list_bezier(1, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
t_u = t_u + 0.04 # regular time interval
# if the number isn't in the range, move to the next range
else :
i += 1
def Newton(poly, p0, p3) :
""" Newton's method for finding the root of a polynomial. Here the root is the 'u' value"""
poly_diff = poly_differentiate(poly)
counter = 0
epsilon = 0.000000000001
x = 0.5 # initial guess value
while True:
x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
counter += 1
if abs(x_n - x) < epsilon :
break
x = x_n
#print "\tIteration " , counter , " : ", x_n
print "u:", (x_n)
lower_lip_under_upper_list_bezier(x_n, p0, p3)
def param_lists_separate(pList) :
""" Separating the parameter values of each feature into individual lists """
v = [[inner[1][i] for outer in pList for inner in outer]
for i in range(len(pList[0][0][1]))]
lower_lip_under_upper_list_plist = v[0]
lips_part_plist = v[1]
lips_spread_plist = v[2]
jaw_open_plist = v[3]
lips_round_plist = v[4]
return lower_lip_under_upper_list_plist
def lower_lip_under_upper_list_bezier(x_n, p0, p3) :
""" Calculating sampling points using rational bezier curve equation"""
u = x_n
p1 = p0
p2 = p3
lower_lip_under_upper_list_p_u = math.pow(1 - u, 3) * p0 + 3 * u * math.pow(1 - u, 2) * p1 \
+ 3 * (1 - u) * math.pow(u, 2) * p2 + math.pow(u, 3) * p3
lower_lip_under_upper_list_p_u = lower_lip_under_upper_list_p_u * w
d = math.pow(1 - u, 3) * w + 3 * u * w * math.pow(1 - u, 2) + 3 * (1 - u) * w * math.pow(u, 2) + math.pow(u, 3) * w
lower_lip_under_upper_list_p_u = lower_lip_under_upper_list_p_u / d
print "\n p(u) values for the feature lower lip under upper list \n"
print "p(u): ", lower_lip_under_upper_list_p_u
return lower_lip_under_upper_list_p_u
if __name__ == "__main__" :
time("transcriptions.txt")
The error is:
NameError: global name 'lower_lip_under_upper_list_plist' is not defined.
This error is on the line lower_lip_under_upper_list_bezier(0, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1]) from the time() function.
Consider this line in the time function:
def time(transcriptionFile) :
...
generate_t_u(timeList, lower_lip_under_upper_list_plist)
lower_lip_under_upper_list_plist is not defined in the time function, so Python looks for it in the global scope. It is not defined there either, so Python raises a NameError, saying the variable lower_lip_under_upper_list_plist is not defined.
By the way, the traceback error message includes a line number indicating what line caused the NameError. It will help you (and us) zero in on the problem to include the line number.
Should lower_lip_under_upper_list_plist be a return value of generate_t_u? Try changing generate_t_u to:
def generate_t_u(time_list):
lower_lip_under_upper_list_plist = []
# ... the function remains the same
return lower_lip_upper_list_plist
I'm not sure where param_lists_separate is called but it looks like the bindings in it are expected to be global as well. A similar problem exists in generate_t_u since t_u is not bound there -- if this refers to the t_u in time, then it should probably be passed in as a parameter. If you have a number of related bindings and methods that act upon the data, then you should probably consider creating a class that ties the data and the operations together.
Consider doing something like the following instead:
class NewtonsMethod(object):
def __init__(self, file_name):
# change global names into properties of ``self``
self.lower_lip_under_upper_list_plist = []
self.lips_part_plist = []
self.lips_spread_plist = []
self.jaw_open_plist = []
self.lips_round_plist = []
self.t_u = 0.0
self.time_list = []
# initialize from the data file
with open(file_name) as file_ref:
for line in file_ref:
data = line.split()
if data:
start_time = (int(data[0]) / 10000000.0)
self.time_list.append(start_time)
def _lower_lip_under_upper_list_bezier(self, x_n, point):
(u, p1, p2) = (x_n, self.lower_lip_under_upper_list_plist[point],
self.lower_lip_under_upper_list_plist[point + 1])
# if lower_lip_under_upper_list_p_u is used elsewhere, then it
# might make sense to change it to a property
lower_lip_under_upper_list_p_u = ...
return lower_lip_under_upper_list_p_u
def _generate_t_u(self):
(i, t_u) = (0, 0.0)
while i < len(self.time_list) - 1:
if t_u > self.time_list[i] and t_u < time_list[i + 1]:
poly = poly_coeff(self.time_list[i], self.time_list[i + 1], t_u)
self._apply_newton(poly, i)
elif t_u == self.time_list[i]:
self._lower_lip_under_upper_list_bezier(0, i)
t_u += 0.04
elif t_u == self.time_list[i + 1]:
self._lower_lip_under_upper_list_bezier(1, i)
t_u += 0.04
else:
i += 1
def _apply_newton(self, poly, point):
poly_diff = poly_differentiate(poly)
(epsilon, x) = (0.0000000001, 0.5)
while True:
x_n = x - (...)
if abs(x_n - x) < epsilon:
break
x = x_n
self._lower_lip_under_upper_list_bezier(x_n, point)
One of the most basic precepts of object-oriented programming is bundling algorithms with the data that they process and/or require. You can apply this idea here. Your global bindings will become properties of the object so they are always available as properties of self within instance methods. As you may have noticed, passing the values from lower_lip_under_upper_list_plist and the like is no longer necessary. All that you need to do is pass the index into the list since the list itself is a property of the object.
Refactoring your algorithm into a class should remove the need for globals everywhere. It will also minimize the number of parameters and let you concentrate on implementing the algorithm in a clean and modular way.

passing a value calculated from one function to another

I have been doing python programming for my project and I have just started. This might be another trivial question. I have this code in which I need to use a value calculated in the function poly_root() which is x. That value should be used as u in the bezier() function. After poly_root() function it should go to bezier() function with its calculated value. I dont know if I am doing it in the correct way. There is no error but it doesnt print t from the bezier() function. Thank you very much.
import copy
import math
poly = [[-0.8,3], [0.75,2], [-0.75,1], [0.1,0]]
def poly_diff(poly):
""" Differentiate a polynomial. """
newlist = copy.deepcopy(poly)
for term in newlist:
term[0] *= term[1]
term[1] -= 1
return newlist
def poly_apply(poly, x):
""" Apply values to the polynomial. """
sum = 0.0 # force float
for term in poly:
sum += term[0] * (x ** term[1])
return sum
def poly_root(poly, start, n, r_i):
""" Returns a root of the polynomial, with a starting value."""
poly_d = poly_diff(poly)
x = start # starting guess value
counter = 0
while True:
if (n >= 0) and (n < 1):
break
x_n = x - (float(poly_apply(poly, x)) / poly_apply(poly_d, x))
if x_n == x:
break
x = x_n # this is the u value corresponding to the given time which will be used in bezier equation
n -= 1
counter += 1
if r_i:
#print [x, counter])
return [x, counter]
else:
#print x
return x
bezier(x)
def bezier(value) :
""" Calculates control points using rational bezier curve equation"""
u = value
w = 5
t = math.pow(1-u,3) * points[0][0] + 3 * u * math.pow(1-u,2) * points[1][0] \
+ 3 * (1-u) * math.pow(u,2) * points[2][0] + math.pow(u,3) * points[3][0]
t = t * w
d = math.pow(1-u,3) * w + 3 * u * w * math.pow(1-u,2) + 3 * (1-u) * w \
* math.pow(u,2) + math.pow(u,3) * w
t = t / d
print t
if __name__ == "__main__" :
poly_root(poly, 0.42, 1, 0)
In this part of code:
if r_i:
#print [x, counter])
return [x, counter]
else:
#print x
return x
bezier(x)
bezier(x) is unreachable. You need to rewrite it.
It would be better for poly_root to return the same type of thing in both situations (i.e. a list with two elements) ...
if r_i:
return [x, counter]
else:
return [x, None]
Then at the bottom, you can have ...
if __name__ == "__main__" :
x, counter = poly_root(poly, 0.42, 1, 0)
if counter is None: # I don't know if this is what you intended with your code.
bezier(x)

Categories