计算积分的有效方法?
Efficient way for calculating integrals?
我知道如何使用蒙特卡洛计算积分,但我想知道是否可以使用梯形法则结合numpy提高效率得到相同的积分,我不确定哪个是最快还是后者可能?
例如积分 e**-x**2 > y
我可以使用这样的蒙特卡洛方法:
import numpy as np
import matplotlib.pyplot as plt
X = np.random.rand(500000,2)
X[:,0] = X[:,0]*4-2
J = np.where(X[:,1] < np.exp(-X[:,0]**2))[0]
Xp = X[:2000]
Ip = [i for i in range(len(Xp)) if i in J]
Inp = [i for i in range(len(Xp)) if i not in J]
plt.plot(Xp[Ip,0],Xp[Ip,1], 'bd', Xp[Inp,0],Xp[Inp,1], 'rd')
plt.show()
这很容易计算:
print len(J) / 500000.0 * 4
给出:
1.767784
在这种情况下很容易,但是如果没有像 [a,b] , n
那样指定间隔,并且我想创建一个函数,那么我认为上面的方法并不是很有效,至少我是这样认为的.
所以,我的问题是,我能否在具有梯形规则的函数中集成一个连续函数,例如 cos(x)/x
,确定间隔,例如 [a,b]
?
它比我在这里使用的方法更好吗?
欢迎大家提出建议。
只需使用scipy.integrate.quad
:
from scipy import integrate
from np import inf
from math import exp, sqrt, pi
res, errEstimate = integrate.quad(lambda x: exp(-x**2), -inf, +inf)
print(res) #output: 1.7724538509055159
print(sqrt(pi)) #output: 1.7724538509055159
最后一行简单地检查评估的积分确实是 Pi 的平方根(它是 Gaussian integral)。
你也可以使用黎曼近似。下面的代码在 Java
package math;
import java.util.Optional;
import java.util.function.*;
import java.util.stream.IntStream;
import static java.lang.Math.*;
public class IntegralJava8
{
public interface Riemann extends BiFunction<Function<Double, Double>, Integer,
BinaryOperator<Double>> { }
public static void main(String args[])
{
int N=100000;
Riemann s = (f, n) -> (a, b) ->
IntStream.range(0, n)
.mapToDouble(i -> f.apply(a + i * ((b - a) / n)) * ((b - a) / n)).sum();
Optional<Double> gaussIntegral =
Optional.of(s.apply(x -> exp(-pow(x, 2)), N).apply(-1000.0, 1000.0));
gaussIntegral.ifPresent(System.out::println);
}
}
在上面class中,它会计算从-infinity到infinity的高斯积分等于PI的平方根(1.772)
我知道如何使用蒙特卡洛计算积分,但我想知道是否可以使用梯形法则结合numpy提高效率得到相同的积分,我不确定哪个是最快还是后者可能?
例如积分 e**-x**2 > y
我可以使用这样的蒙特卡洛方法:
import numpy as np
import matplotlib.pyplot as plt
X = np.random.rand(500000,2)
X[:,0] = X[:,0]*4-2
J = np.where(X[:,1] < np.exp(-X[:,0]**2))[0]
Xp = X[:2000]
Ip = [i for i in range(len(Xp)) if i in J]
Inp = [i for i in range(len(Xp)) if i not in J]
plt.plot(Xp[Ip,0],Xp[Ip,1], 'bd', Xp[Inp,0],Xp[Inp,1], 'rd')
plt.show()
这很容易计算:
print len(J) / 500000.0 * 4
给出:
1.767784
在这种情况下很容易,但是如果没有像 [a,b] , n
那样指定间隔,并且我想创建一个函数,那么我认为上面的方法并不是很有效,至少我是这样认为的.
所以,我的问题是,我能否在具有梯形规则的函数中集成一个连续函数,例如 cos(x)/x
,确定间隔,例如 [a,b]
?
它比我在这里使用的方法更好吗?
欢迎大家提出建议。
只需使用scipy.integrate.quad
:
from scipy import integrate
from np import inf
from math import exp, sqrt, pi
res, errEstimate = integrate.quad(lambda x: exp(-x**2), -inf, +inf)
print(res) #output: 1.7724538509055159
print(sqrt(pi)) #output: 1.7724538509055159
最后一行简单地检查评估的积分确实是 Pi 的平方根(它是 Gaussian integral)。
你也可以使用黎曼近似。下面的代码在 Java
package math;
import java.util.Optional;
import java.util.function.*;
import java.util.stream.IntStream;
import static java.lang.Math.*;
public class IntegralJava8
{
public interface Riemann extends BiFunction<Function<Double, Double>, Integer,
BinaryOperator<Double>> { }
public static void main(String args[])
{
int N=100000;
Riemann s = (f, n) -> (a, b) ->
IntStream.range(0, n)
.mapToDouble(i -> f.apply(a + i * ((b - a) / n)) * ((b - a) / n)).sum();
Optional<Double> gaussIntegral =
Optional.of(s.apply(x -> exp(-pow(x, 2)), N).apply(-1000.0, 1000.0));
gaussIntegral.ifPresent(System.out::println);
}
}
在上面class中,它会计算从-infinity到infinity的高斯积分等于PI的平方根(1.772)