Last active
May 31, 2019 19:06
-
-
Save TwoDollarsEsq/d5dfc47c4324dc3d7d84ce1b112a1369 to your computer and use it in GitHub Desktop.
In mathematics, Monte Carlo integration is a technique for numerical integration using random numbers. It is a particular Monte Carlo method that numerically computes a definite integral. While other algorithms usually evaluate the integrand at a regular grid, Monte Carlo randomly choose points at which the integrand is evaluated.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
/// Approximates integral using Monte-Carlo method. | |
/// | |
/// - parameter bounds: N-dimensional array of boundary limits. | |
/// - parameter f: integrand function. | |
/// - parameter N: number of points randomly picked to approximate. | |
/// | |
/// - Returns: Approximated value of integral. | |
public func mcr(in bounds: NBounds, f: FuncND, N: Double) -> Double { | |
let ps = (0..<Int(N)).map { _ -> NPoint in .random(in: bounds) } | |
return bounds.map(-).reduce(1, *) * ps.map(f).reduce(0, +) / N | |
} | |
/// Approximates integral using Monte-Carlo method. | |
/// | |
/// - parameter bounds: N-dimensional array of boundary limits. | |
/// - parameter f: integrand function. | |
/// - parameter N: number of points randomly picked to approximate. | |
/// | |
/// - Returns: Approximated value of integral and estimated error. | |
public func mc(in bounds: NBounds, f: FuncND, N: Double) -> MCResult { | |
let length = bounds.map(-).reduce(1, *) | |
let ps = (0..<Int(N)).map { _ -> NPoint in .random(in: bounds) } | |
let fAverage = ps.map(f).reduce(0, +) / N | |
let result = length * fAverage | |
let eAverage = ps.map { pow(f($0), 2) }.reduce(0, +) / N | |
let error = length * sqrt((eAverage - pow(fAverage, 2)) / N) | |
return (result, error) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Approximates integral using Monte-Carlo method. | |
/// | |
/// - parameter bounds: 1-dimensional array of boundary limits. | |
/// - parameter f: integrand function. | |
/// - parameter N: number of points randomly picked to approximate. | |
/// | |
/// - Returns: Approximated value of integral. | |
public func mc(in bounds: Bounds, f: Func1D, N: Double) -> MCResult { | |
return mc(in: [bounds], f: { f($0[0]) }, N: N) | |
} | |
/// Approximates integral using Monte-Carlo method. | |
/// | |
/// - parameter bounds: 2-dimensional array of boundary limits. | |
/// - parameter f: integrand function. | |
/// - parameter N: number of points randomly picked to approximate. | |
/// | |
/// - Returns: Approximated value of integral. | |
public func mc(in rect: Rect, f: Func2D, N: Double) -> MCResult { | |
return mc(in: [(rect.a, rect.b), (rect.c, rect.d)], f: { f($0[0], $0[1]) }, N: N) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Double { static var e: Double { return 2.72 } } | |
let function: Func1D = sqrt | |
let bounds: Bounds = (0, 4) | |
// Using compact 1D interfaces | |
// 1D | |
mc(in: bounds, f: function, N: 1000) | |
mc(in: (0, 1), f: { 4 / (1 + pow($0, 2)) }, N: 100) | |
// 2D | |
mc(in: (1, 2, 0, 2), f: { sin($0) + cos($1) }, N: 1000) | |
// Using N-dimensional interface | |
// 1D case | |
mc(in: [(-.pi / 4, 0)], f: { pow(tan($0[0]), 2) }, N: 1000) | |
// 2D case | |
mc(in: [(1.0 / 6, 1.0 / 3), (log(3), log(4))], | |
f: { 12 * $0[1] * pow(.e, 6 * $0[0] * $0[1]) }, | |
N: 1000 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 1-dimensional bounds | |
public typealias Bounds = (a: Double, b: Double) | |
/// 2-dimensional bounds | |
public typealias Rect = (a: Double, b: Double, c: Double, d: Double) | |
/// MCPair - result and error approximation | |
public typealias MCResult = (result: Double, error: Double) | |
/// 1-dimensonal integrand function | |
public typealias Func1D = (Double) -> Double | |
/// 2-dimensonal integrand function | |
public typealias Func2D = (Double, Double) -> Double | |
/// N-dimensional bounds | |
public typealias NBounds = [Bounds] | |
/// N-dimensional point | |
public typealias NPoint = [Double] | |
/// N-dimensonal integrand function | |
public typealias FuncND = (NPoint) -> Double | |
public extension NPoint { | |
/// Random N-dimensional point generator. | |
/// | |
/// - parameter bounds: array of bounds for each dimension. | |
/// - Returns: Random point in **bounds**. | |
static func random(in bounds: NBounds) -> NPoint { | |
return (0..<bounds.count).map { Double.random(in: bounds[$0].a...bounds[$0].b) } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment