I'm defining a function in python in this way:
def calculate(y1,y2,y):
l=np.log(3)
ya=np.array(y1)/(np.array(y)*np.array(l))
yb=np.array(y2)/(np.array(y)*np.array(l))
return (ya,yb)
but when I run my script (even if everything works) I get the following error:
RuntimeWarning: invalid value encountered in divide
ya = np.array(y1)/((np.array(y))*(l))
RuntimeWarning: invalid value encountered in divide
yb = np.array(y2)/((np.array(y))*(l))
How can I solve the problem?
You're getting that error because there is either a 0 or a np.inf value in the denominator array.
There's not a lot you can do other than clean up y before it gets to calculcate
def calculate(y1, y2, y):
if not isinstance(y, np.ndarray):
y = np.array(y)
if not np.isfinite(y):
print 'bad y array values'
return
elif np.sum(y == 0) > 0:
print 'zero values in y'
return
# the rest of your code
Note this will stop the RunTimeWarning but will return nothing so the function that calls calculate will have to deal with that.
Related
In the package sympy.physics.quantum.spin there is a function m_values which is called by a lot of the other functions in the package. It takes as input an integer or half-integer, and returns a tuple. Here is the source code, obtained from Github:
def m_values(j):
j = sympify(j)
size = 2*j + 1
if not size.is_Integer or not size > 0:
raise ValueError(
'Only integer or half-integer values allowed for j, got: : %r' % j
)
return size, [j - i for i in range(int(2*j + 1))]
This functions works as I expect it to for integer values. However, if I put in a half-integer value, this function returns an error. Here is an example:
from sympy.physics.quantum.spin import m_values
m_values(0.5) #can also try m_values(3/2)
This code produces the error
ValueError: Only integer or half-integer values allowed for j, got: : 0.500000000000000
So clearly the issue is that size.is_Integer is returning False. How should I input j into m_values so that the function works for half-integers?
def f(x):
f='exp(x)-x-2'
y=eval(f)
print(y)
return y
def bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2):
x=a
result_a=f(a)
x=b
result_b=f(b)
if (f.evalf(a)*f.evalf(b)>=0):
print("Interval [a,b] does not contain a zero ")
exit()
zeta=min(epsilon1,epsilon2)/10
x=a
while(f_line(x)>0):
if(x<b or x>-b):
x=x+zeta
else:
stop
ak=a
bk=b
xk=(ak+bk)/2
k=0
if (f(xk)*f(ak)<0):
ak=ak
bk=xk
if (f(xk)*f(bk)<0):
ak=xk
bk=bk
k=k+1
from sympy import *
import math
x=Symbol('x')
f=exp(x)-x-2
f_line=f.diff(x)
f_2lines=f_line.diff(x)
print("Derivative of f:", f_line)
print("2nd Derivative of f:", f_2lines)
a=int(input('Beginning of interval: '))
b=int(input('End of interval: '))
epsilon1=input('1st tolerance: ')
epsilon2=input('2nd tolerance: ')
bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2)
This program is an attempt to implement the Bissection Method. I've tried writing two functions:
The first one, f, is supposed to receive the extremes of the interval that may or may not contain a root (a and b) and return the value of the function evaluated in this point.
The second one, bissection, should receive the function, the function's first and second derivatives, the extremes of the interval (a,b) and two tolerances (epsilon1,epsilon2).
What I want to do is pass each value a and b, one at a time, as arguments to the function f, that is supposed to return f(a) and f(b); that is, the values of the function in each of the points a and b.
Then, it should test two conditions:
1) If the function values in the extremes of the intervals have opposite signs. If they don't, the method won't converge for this interval, then the program should terminate.
if(f.evalf(a)*f.evalf(b)>=0)
exit()
2)
while(f_line(x)>0): #while the first derivative of the function evaluated in x is positive
if(x<b or x>-b): #This should test whether x belongs to the interval [a,b]
x=x+zeta #If it does, x should receive x plus zeta
else:
stop
At the end of this loop, my objective was to determine whether the first derivative was strictly positive (I didn't do the negative case yet).
The problem: I'm getting the error
Traceback (most recent call last):
File "bissec.py", line 96, in <module>
bissection(f,f_line,f_2lines,a,b,epsilon1,epsilon2)
File "bissec.py", line 41, in bissection
result_a=f(a)
TypeError: 'Add' object is not callable
How can I properly call the function so that it returns the value of the function (in this case, f(x)=exp(x)-x-2), for every x needed? That is, how can I evaluate f(a) and f(b)?
Ok, so I've figured it out where your program was failing and I've got 4 reasons why.
First of all, and the main topic of your question, if you want to evaluate a function f for a determined x value, let's say a, you need to use f.subs(x, a).evalf(), as it is described in SymPy documentation. You used in 2 different ways: f.evalf(2) and f_line(a); both were wrong and need to be substituted by the correct syntax.
Second, if you want to stop a while loop you should use the keyword break, not "stop", as written in your code.
Third, avoid using the same name for variables and functions. In your f function, you also used f as the name of a variable. In bissection function, you passed f as a parameter and tried to call the f function. That'll fail too. Instead, I've changed the f function to f_calc, and applied the correct syntax of my first point in it.
Fourth, your epsilon1 and epsilon2 inputs were missing a float() conversion. I've added that.
Now, I've also edited your code to use good practices and applied PEP8.
This code should fix this error that you're getting and a few others:
from sympy import *
def func_calc(func, x, val):
"""Evaluate a given function func, whose varible is x, with value val"""
return func.subs(x, val).evalf()
def bissection(x, f, f_line, f_2lines, a, b, epsilon1, epsilon2):
"""Applies the Bissection Method"""
result_a = func_calc(f, x, a)
result_b = func_calc(f, x, b)
if (result_a * result_b >= 0):
print("Interval [a,b] does not contain a zero")
exit()
zeta = min(epsilon1, epsilon2) / 10
x_val = a
while(func_calc(f_line, x, a) > 0):
if(-b < x_val or x_val < b):
x_val = x_val + zeta
else:
break # the keyword you're looking for is break, instead of "stop"
print(x_val)
ak = a
bk = b
xk = (ak + bk) / 2
k = 0
if (func_calc(f, x, xk) * func_calc(f, x, ak) < 0):
ak = ak
bk = xk
if (func_calc(f, x, xk) * func_calc(f, x, bk) < 0):
ak = xk
bk = bk
k = k + 1
def main():
x = Symbol('x')
f = exp(x) - x - 2
f_line = f.diff(x)
f_2lines = f_line.diff(x)
print("Derivative of f:", f_line)
print("2nd Derivative of f:", f_2lines)
a = int(input('Beginning of interval: '))
b = int(input('End of interval: '))
epsilon1 = float(input('1st tolerance: '))
epsilon2 = float(input('2nd tolerance: '))
bissection(x, f, f_line, f_2lines, a, b, epsilon1, epsilon2)
if __name__ == '__main__':
main()
I was able to find several implementations of Newton's methods, for example, this link or maybe this one.
However, most of the time the examples are with simple functions such as:
x^2−9=0 or x^3-x^2-1=0. I am looking for something that would work for:
My question for that I am lost in how to use this code to solve my problem. For example, I am not sure how I would apply the derivative (dfdx) on my F(x) that contain matrices. Also, if I should direct input the matrices on my "def f(x)"
The code that I am using:
def Newton(f, dfdx, x, eps):
f_value = f(x)
iteration_counter = 0
while abs(f_value) > eps and iteration_counter < 100:
try:
x = x - float(f_value)/dfdx(x)
except ZeroDivisionError:
print "Error! - derivative zero for x = ", x
sys.exit(1) # Abort with error
f_value = f(x)
iteration_counter += 1
# Here, either a solution is found, or too many iterations
if abs(f_value) > eps:
iteration_counter = -1
return x, iteration_counter
def f(x):
return x**2 - 9
def dfdx(x):
return 2*x
solution, no_iterations = Newton(f, dfdx, x=1000, eps=1.0e-6)
if no_iterations > 0: # Solution found
print "Number of function calls: %d" % (1 + 2*no_iterations)
print "A solution is: %f" % (solution)
else:
print "Solution not found!"
There aren't any special rules for deriving matrices - the derivative is just calculated for each element separately. I would suggest evaluating the $[x1,x2]' * M * [x1,x2]$ expression on paper to get a matrix of polynomials, and then calculating the derivative of each one.
My former problem (which is solved now) was:
As an input, I have a list of nonnegative whole numbers which are supposed to be the coefficients of a polynomial. But I also want to evaluate the polynomial for a certain number x.
For example:
If we have L=[2,3,1] as an input and x=42 we get 2x^2+3x+1=3655
What I want is for example:
>>>p=polynomial([2,3,1])
>>>p(O)
1
>>>p(42)
>>>3655
The code is
def polynomial(coef):
def poly(x):
result = 0
x_n = 1
for a in reversed(coef):
result += a * x_n
x_n *= x
return result
return poly
What I wanted to do now is to find the inverse , that means the input the is a monotone polynomial and the positive whole number y and I want to find a whole number x such that p(x)=y, and x should be only in [1,10**10], for example:
>>>p=polynomial([2,3,1])
>>>p(O)
1
>>>p(42)
>>>3655
>>>invert(3655,p)
42
This is what I have so far, but what I get is a runtime error:
def polynomial(coef):
def poly(x):
result = 0
xn = 1
for c in reversed(coef):
result += c * xn
xn *= x
return result
return poly
def invert(y,p):
test=10**10
if p(2)>p(1):
if p(test)>y:
test=test//2 +(test%2)
return invert(y,p)
elif p(test)<y:
test=test+(test//2)
return invert(y,p)
else:
return test
if p(2)<p(1):
if p(test)<y:
test=test//2 +(test%2)
return invert(y,p)
elif p(test)>y:
test=test+(test//2)
return invert(y,p)
else:
return test
The error that occurs is
...
File "poly.py", line 17, in invert
return invert(y,p)
File "poly.py", line 14, in invert
if p(2)>p(1):
File "poly.py", line 5, in poly
for c in reversed(coef):
RuntimeError: maximum recursion depth exceeded while calling a Python object
What am I doing wrong?
Your invert function recurses forever because you never modify the arguments that you pass to the next call. You do modify test, but that doesn't do you any good, since the inner call will have its own copy of test.
There are a few ways you could fix the issue. You could pass test as an argument to the invert function, with your initial value a default that will be used the first time:
def invert(y, p, test=10**10):
# ...
# later, when you recurse:
test = test // 2 # or whatever
return invert(y, p, test) # pass on the modified test value
Another (probably better) approach would be to abandon recursion, and use a loop instead. A while loop seems like it would be appropriate here:
def invert(y, p):
test = 10**10
sign = (-1)**(p(2) < p(1))
while True:
if p(test) > y:
test -= sign * (test // 2)
elif p(test) < y:
test += sign * (test // 2)
else:
return test # this is the only case that returns
I've left the overall algorithm the same as what your original code does (just streamlined a bit). That algorithm may not be correct if your polynomial isn't strictly increasing or strictly decreasing. You should really compute the derivative of the polynomial at test to determine which direction to adjust in, but I'll leave that to you to figure out.
I took the liberty to fix the indention of the code you posted. Please verify that the below code is actually what you have, regarding indentions The following code does return your desired output..
def polynomial(coef):
def poly(x):
result = 0
x_n = 1
for a in reversed(coef):
result += a * x_n
x_n *= x
return result
return poly
def invert(y,p,test): # updated
# test=10**10 # This was the problem
# You reset 'test' for every recursive call
# which means you will stand still without
# any progress until the max num of allowed
# recursive calls are reached.
if p(2)>p(1):
if p(test)>y:
test=test//2 +(test%2)
return invert(y,p,test) # updated
elif p(test)<y:
test=test+(test//2)
return invert(y,p,test) # updated
else:
return test
if p(2)<p(1):
if p(test)<y:
test=test//2 +(test%2)
return invert(y,p,test) # updated
elif p(test)>y:
test=test+(test//2)
return invert(y,p,test) # updated
else:
return test
p = polynomial([2,3,1])
t = 10**10
print(invert(3655,p,t))
I wrote the code myself now, limiting everything to the knowledge/skill I only have so far, and it works:
def polynomial(coef):
def poly(x):
result = 0
x_n = 1
for a in reversed(coef):
result += a * x_n
x_n *= x
return result
return poly
def invert(y,p):
x=10**10
while p(x)!=y:
if p(x)>y:
w=x
x=x//2
elif p(x)<y:
x=(x+w)//2
return x
When I use this random generator: numpy.random.multinomial, I keep getting:
ValueError: sum(pvals[:-1]) > 1.0
I am always passing the output of this softmax function:
def softmax(w, t = 1.0):
e = numpy.exp(numpy.array(w) / t)
dist = e / np.sum(e)
return dist
except now that I am getting this error, I also added this for the parameter (pvals):
while numpy.sum(pvals) > 1:
pvals /= (1+1e-5)
but that didn't solve it. What is the right way to make sure I avoid this error?
EDIT: here is function that includes this code
def get_MDN_prediction(vec):
coeffs = vec[::3]
means = vec[1::3]
stds = np.log(1+np.exp(vec[2::3]))
stds = np.maximum(stds, min_std)
coe = softmax(coeffs)
while np.sum(coe) > 1-1e-9:
coe /= (1+1e-5)
coeff = unhot(np.random.multinomial(1, coe))
return np.random.normal(means[coeff], stds[coeff])
I also encountered this problem during my language modelling work.
The root of this problem rises from numpy's implicit data casting: the output of my sorfmax() is in float32 type, however, numpy.random.multinomial() will cast the pval into float64 type IMPLICITLY. This data type casting would cause pval.sum() exceed 1.0 sometimes due to numerical rounding.
This issue is recognized and posted here
I know the question is old but since I faced the same problem just now, it seems to me it's still valid. Here's the solution I've found for it:
a = np.asarray(a).astype('float64')
a = a / np.sum(a)
b = np.random.multinomial(1, a, 1)
I've made the important part bold. If you omit that part the problem you've mentioned will happen from time to time. But if you change the type of array into float64, it will never happen.
Something that few people noticed: a robust version of the softmax can be easily obtained by removing the logsumexp from the values:
from scipy.misc import logsumexp
def log_softmax(vec):
return vec - logsumexp(vec)
def softmax(vec):
return np.exp(log_softmax(vec))
Just check it:
print(softmax(np.array([1.0, 0.0, -1.0, 1.1])))
Simple, isn't it?
The softmax implementation I was using is not stable enough for the values I was using it with. As a result, sometimes the output has a sum greater than 1 (e.g. 1.0000024...).
This case should be handled by the while loop. But sometimes the output contains NaNs, in which case the loop is never triggered, and the error persists.
Also, numpy.random.multinomial doesn't raise an error if it sees a NaN.
Here is what I'm using right now, instead:
def softmax(vec):
vec -= min(A(vec))
if max(vec) > 700:
a = np.argsort(vec)
aa = np.argsort(a)
vec = vec[a]
i = 0
while max(vec) > 700:
i += 1
vec -= vec[i]
vec = vec[aa]
e = np.exp(vec)
return e/np.sum(e)
def sample_multinomial(w):
"""
Sample multinomial distribution with parameters given by softmax of w
Returns an int
"""
p = softmax(w)
x = np.random.uniform(0,1)
for i,v in enumerate(np.cumsum(p)):
if x < v: return i
return len(p)-1 # shouldn't happen...