While using integrate in the scipy module, I notice that the values of the integral do not match with the expected value (which I computed by hand).
I have a simple function as follows:
import math
def integrand(x, L):
return (math.cos(sc.pi * x / L))**2
L=10
I = quad(integrand, 0, 1, args=(L))
I = 0.9677446418943196 # from scipy
But theoretically, the result should be 0.5519233944327677. I am quite confused as to why discrepancy exists.
The integral I am trying to find is as follows:
The scipy is correct. Your calculation is incorrect:
Note that the Decimal given matches the one obtained by scipy. This question is best suited for stackexchange.
Related
I want to evaluate the exponential integral function numerically using trapezoidal rule.This function is defined as:
The reference is available here.
This function is already available in some libraries for example scipy.special. For some reasons I do not want to use these libraries. Instead, I need to evaluate this function directly by the trapezoidal rule. I wrote the trapezoidal rule and checked it to make sure it works fine.
Then I used it for numerical evaluation of the Ei function. Unfortunately the results is not correct for example I want to evaluate Ei(1) which is equal to 1.89511 but the code I have written returns infinity which is wrong. Here is the code:
import numpy as np
# Integration using Trapezoidal rule
def trapezoidal(f, a, b, n):
h = float(b - a) / n
s = 0.0
s += f(a)/2.0
for i in range(1, n):
s += f(a + i*h)
s += f(b)/2.0
return s * h
# Define integrand
def Ei(t):
return - np.exp(-t) / t
# Define Ei(1)
A = trapezoidal(Ei, -1, np.inf, 20)
print (A)
# Checking Ei(1)
from scipy.special import expi
print (expi(1))
Do you know how I can modify the above code so I can get correct results?
Thanks!
1) You cannot define range ending woth +inf and divide it onto 20 parts.
Instead you can choose arbitrary right limit and increase it until difference abs(integral(limit(i+1))-integral(limit(i))) becomes negligible
2) Consider function evaluation in zero point (if occurs). It causes division by zero
If argument is too close to zero, try to shift it a bit.
I am trying to create a Fibonacci number with high n by using matrix exponential but it gives me negative result. I have tried to change the integer objects but failed.
import numpy as np
def matrixmul(a,n):
a=np.array([[1,1],[1,0]])
return ((np.array([1,1],[1,0], dtype=np.object))**n)
matrixMul(a,100)
my output is
array([[-1869596475, -980107325],
[ -980107325, -889489150]])
but it was wrong. there should not be any negative number.
It's hard to answer on your question. Your code have some bugs:
You haven't initialize a
Also name of defined function is different than used (python is case-sensitive)
Then in function you are not using a (because it is not in return)
And most important thing is that you can not use **n too get exponential of matrix. Instead you can try to find right function in scipy library. Probably expm() function can be right for this perpuse.
Hello I have a problem using Scipy's fsolve function when I have an equation system.
My code only let's me have as much variables as there are equations in my system, but we all know that in practice, you can have more equations than variables, especially when the solution is not a concrete number but a range of numbers, an additional equation can help narrow down the "haystack" so to speak.
How to insert more equations than variables is my question?
Suppose I have the following non-linear system:
A/B=0.4583(3)
A/C=0.25
A/D=0.72(2)
B/C=0.54(54)
So I have the following code for this:
from scipy.optimize import *
from numpy import *
def FUNC(arg):
A,B,C,D=arg
UNK=empty((4))
UNK[0]= A/B-0.458333333333333
UNK[1]= A/C-0.25
UNK[2]= A/D-0.722222222222222
UNK[3]= B/C-0.545454545454546
return UNK
SOLVED= fsolve(FUNC, [1.0]*4)
print (SOLVED)
The problem is that I also know the following information:
B/D=1.57(57)
C/D=2.8(8)
How can I insert these 2 additional equations into my equation system?
Also how can I display the range of solutions instead of just 1 solution, it seems like fsolve only displays the 1st solution it encounters, not the entire range of possible solutions.
Note that scipy's fsolve is just a Wrapper for the MINPACK's hybrd routine:
The purpose of HYBRD is to find a zero of a system of N non-linear functions in N variables by a modification of the Powell hybrid method. The user must provide a subroutine which calculates the functions. The Jacobian is then calculated by a forward-difference approximation.
If you want to solve a system of 6 equations, your function FUNC needs to be a function of 6 variables. We could do it like this:
import numpy as np
from scipy.optimize import fsolve
def FUNC(arg):
A, B, C, D, E, F = arg
UNK=np.empty((6))
UNK[0]= A/B-0.458333333333333
UNK[1]= A/C-0.25
UNK[2]= A/D-0.722222222222222
UNK[3]= B/C-0.545454545454546
UNK[4]= B/D-1.575757575757575
UNK[5]= C/D-2.888888888888888
return UNK
fsolve(FUNC, x0=[1.0]*6)
It isn't possible to get all solutions with fsolve. But you could try different initial points x0 with the hope to get different solutions.
I'm trying to define a complex custom likelihood function using pymc3. The likelihood function involves a lot of iteration, and therefore I'm trying to use theano's scan method to define iteration directly within theano. Here's a greatly simplified example that illustrates the challenge that I'm facing. The (fake) likelihood function I'm trying to define is simply the sum of two pymc3 random variables, p and theta. Of course, I could simply return p+theta, but the actual likelihood function I'm trying to write is more complicated, and I believe I need to use theano.scan since it involves a lot of iteration.
import pymc3 as pm
from pymc3 import Model, Uniform, DensityDist
import theano.tensor as T
import theano
import numpy as np
### theano test
theano.config.compute_test_value = 'raise'
X = np.asarray([[1.0,2.0,3.0],[1.0,2.0,3.0]])
### pymc3 implementation
with Model() as bg_model:
p = pm.Uniform('p', lower = 0, upper = 1)
theta = pm.Uniform('theta', lower = 0, upper = .2)
def logp(X):
f = p+theta
print("f",f)
get_ll = theano.function(name='get_ll',inputs = [p, theta], outputs = f)
print("p keys ",p.__dict__.keys())
print("theta keys ",theta.__dict__.keys())
print("p name ",p.name,"p.type ",p.type,"type(p)",type(p),"p.tag",p.tag)
result=get_ll(p, theta)
print("result",result)
return result
y = pm.DensityDist('y', logp, observed = X) # Nx4 y = f(f,x,tx,n | p, theta)
When I run this, I get the error:
TypeError: ('Bad input argument to theano function with name "get_ll" at index 0(0-based)', 'Expected an array-like object, but found a Variable: maybe you are trying to call a function on a (possibly shared) variable instead of a numeric array?')
I understand that the issue occurs in line
result=get_ll(p, theta)
because p and theta are of type pymc3.TransformedRV, and that the input to a theano function needs to be a scalar number of a simple numpy array. However, a pymc3 TransformedRV does not seem to have any obvious way of obtaining the current value of the random variable itself.
Is it possible to define a log likelihood function that involves the use of a theano function that takes as input a pymc3 random variable?
The problem is that your th.function get_ll is a compiled theano function, which takes as input numerical arrays. Instead, pymc3 is sending it a symbolic variable (theano tensor). That's why you're getting the error.
As to your solution, you're right in saying that just returning p+theta is the way to go. If you have scans and whatnot in your logp, then you would return the scan variable of interest; there is no need to compile a theano function here. For example, if you wanted to add 1 to each element of a vector (as an impractical toy example), you would do:
def logp(X):
the_sum, the_sum_upd = th.scan(lambda x: x+1, sequences=[X])
return the_sum
That being said, if you need gradients, you would need to calculate your the_sum variable in a theano Op and provide a grad() method along with it (you can see a toy example of that on the answer here). If you do not need gradients, you might be better off doing everything in python (or C, numba, cython, for performance) and using the as_op decorator.
If I have a cost that is the imaginary part of a complex number, trying to obtain the gradient with theano I get the following error:
TypeError: Elemwise{imag,no_inplace}.grad illegally returned an integer-valued variable. (Input index 0, dtype complex128)
Is it not possible to use the imaginary part as cost despite it being a real-valued cost?
Edit. Minimal working example
import theano.tensor as T
from theano import function
a = T.zscalar('a')
f = function([a], T.grad(T.imag(a),a))
I would expect this to work as T.imag(a) is a real scalar cost..