diff --git a/ext/IntegralsCubatureExt.jl b/ext/IntegralsCubatureExt.jl index 5bb68d7..9033291 100644 --- a/ext/IntegralsCubatureExt.jl +++ b/ext/IntegralsCubatureExt.jl @@ -2,13 +2,7 @@ module IntegralsCubatureExt using Integrals, Cubature -import Integrals: transformation_if_inf, - scale_x, scale_x!, CubatureJLh, CubatureJLp, - AbstractCubatureJLAlgorithm -import Cubature: INDIVIDUAL, PAIRED, L1, L2, LINF - -Integrals.CubatureJLh(; error_norm = Cubature.INDIVIDUAL) = CubatureJLh(error_norm) -Integrals.CubatureJLp(; error_norm = Cubature.INDIVIDUAL) = CubatureJLp(error_norm) +using Integrals: scale_x, scale_x!, CubatureJLh, CubatureJLp, AbstractCubatureJLAlgorithm function Integrals.__solvebp_call(prob::IntegralProblem, alg::AbstractCubatureJLAlgorithm, diff --git a/src/Integrals.jl b/src/Integrals.jl index 664d2ae..c503827 100644 --- a/src/Integrals.jl +++ b/src/Integrals.jl @@ -10,6 +10,8 @@ using LinearAlgebra include("common.jl") include("algorithms.jl") +include("algorithms_sampled.jl") +include("algorithms_extension.jl") include("infinity_handling.jl") include("quadrules.jl") include("sampled.jl") @@ -64,6 +66,7 @@ end # Give a layer to intercept with AD __solvebp(args...; kwargs...) = __solvebp_call(args...; kwargs...) + function quadgk_prob_types(f, lb::T, ub::T, p, nrm) where {T} DT = float(T) # we need to be careful to infer the same result as `evalrule` RT = Base.promote_op(*, DT, Base.promote_op(f, DT, typeof(p))) # kernel diff --git a/src/algorithms.jl b/src/algorithms.jl index 5a7b75a..9f1bef7 100644 --- a/src/algorithms.jl +++ b/src/algorithms.jl @@ -127,50 +127,6 @@ function GaussLegendre(; n = 250, subintervals = 1, nodes = nothing, weights = n return GaussLegendre(nodes, weights, subintervals) end -""" - TrapezoidalRule - -Struct for evaluating an integral via the trapezoidal rule. - - -Example with sampled data: - -``` -using Integrals -f = x -> x^2 -x = range(0, 1, length=20) -y = f.(x) -problem = SampledIntegralProblem(y, x) -method = TrapezoidalRule() -solve(problem, method) -``` -""" -struct TrapezoidalRule <: SciMLBase.AbstractIntegralAlgorithm -end - -""" - SimpsonsRule - -Struct for evaluating an integral via the Simpson's composite 1/3-3/8 -rule over `AbstractRange`s (evenly spaced points) and -Simpson's composite 1/3 rule for non-equidistant grids. - - -Example with equidistant data: - -``` -using Integrals -f = x -> x^2 -x = range(0, 1, length=20) -y = f.(x) -problem = SampledIntegralProblem(y, x) -method = SimpsonsRule() -solve(problem, method) -``` -""" -struct SimpsonsRule <: SciMLBase.AbstractIntegralAlgorithm -end - """ QuadratureRule(q; n=250) @@ -192,220 +148,3 @@ struct QuadratureRule{Q} <: SciMLBase.AbstractIntegralAlgorithm end end QuadratureRule(q; n = 250) = QuadratureRule(q, n) - -## Extension Algorithms - -abstract type AbstractCubaAlgorithm <: SciMLBase.AbstractIntegralAlgorithm end -""" - CubaVegas() - -Multidimensional adaptive Monte Carlo integration from Cuba.jl. -Importance sampling is used to reduce variance. - -## References - -@article{lepage1978new, -title={A new algorithm for adaptive multidimensional integration}, -author={Lepage, G Peter}, -journal={Journal of Computational Physics}, -volume={27}, -number={2}, -pages={192--203}, -year={1978}, -publisher={Elsevier} -} -""" -struct CubaVegas <: AbstractCubaAlgorithm - flags::Int - seed::Int - minevals::Int - nstart::Int - nincrease::Int - gridno::Int -end -""" - CubaSUAVE() - -Multidimensional adaptive Monte Carlo integration from Cuba.jl. -Suave stands for subregion-adaptive VEGAS. -Importance sampling and subdivision are thus used to reduce variance. - -## References - -@article{hahn2005cuba, -title={Cuba—a library for multidimensional numerical integration}, -author={Hahn, Thomas}, -journal={Computer Physics Communications}, -volume={168}, -number={2}, -pages={78--95}, -year={2005}, -publisher={Elsevier} -} -""" -struct CubaSUAVE{R} <: AbstractCubaAlgorithm where {R <: Real} - flags::Int - seed::Int - minevals::Int - nnew::Int - nmin::Int - flatness::R -end -""" - CubaDivonne() - -Multidimensional adaptive Monte Carlo integration from Cuba.jl. -Stratified sampling is used to reduce variance. - -## References - -@article{friedman1981nested, -title={A nested partitioning procedure for numerical multiple integration}, -author={Friedman, Jerome H and Wright, Margaret H}, -journal={ACM Transactions on Mathematical Software (TOMS)}, -volume={7}, -number={1}, -pages={76--92}, -year={1981}, -publisher={ACM New York, NY, USA} -} -""" -struct CubaDivonne{R1, R2, R3, R4} <: - AbstractCubaAlgorithm where {R1 <: Real, R2 <: Real, R3 <: Real, R4 <: Real} - flags::Int - seed::Int - minevals::Int - key1::Int - key2::Int - key3::Int - maxpass::Int - border::R1 - maxchisq::R2 - mindeviation::R3 - xgiven::Matrix{R4} - nextra::Int - peakfinder::Ptr{Cvoid} -end -""" - CubaCuhre() - -Multidimensional h-adaptive integration from Cuba.jl. - -## References - -@article{berntsen1991adaptive, -title={An adaptive algorithm for the approximate calculation of multiple integrals}, -author={Berntsen, Jarle and Espelid, Terje O and Genz, Alan}, -journal={ACM Transactions on Mathematical Software (TOMS)}, -volume={17}, -number={4}, -pages={437--451}, -year={1991}, -publisher={ACM New York, NY, USA} -} -""" -struct CubaCuhre <: AbstractCubaAlgorithm - flags::Int - minevals::Int - key::Int -end - -function CubaVegas(; flags = 0, seed = 0, minevals = 0, nstart = 1000, nincrease = 500, - gridno = 0) - CubaVegas(flags, seed, minevals, nstart, nincrease, gridno) -end -function CubaSUAVE(; flags = 0, seed = 0, minevals = 0, nnew = 1000, nmin = 2, - flatness = 25.0) - CubaSUAVE(flags, seed, minevals, nnew, nmin, flatness) -end -function CubaDivonne(; flags = 0, seed = 0, minevals = 0, - key1 = 47, key2 = 1, key3 = 1, maxpass = 5, border = 0.0, - maxchisq = 10.0, mindeviation = 0.25, - xgiven = zeros(Cdouble, 0, 0), - nextra = 0, peakfinder = C_NULL) - CubaDivonne(flags, seed, minevals, key1, key2, key3, maxpass, border, maxchisq, - mindeviation, xgiven, nextra, peakfinder) -end -CubaCuhre(; flags = 0, minevals = 0, key = 0) = CubaCuhre(flags, minevals, key) - -abstract type AbstractCubatureJLAlgorithm <: SciMLBase.AbstractIntegralAlgorithm end -""" - CubatureJLh() - -Multidimensional h-adaptive integration from Cubature.jl. -`error_norm` specifies the convergence criterion for vector valued integrands. -Defaults to `Cubature.INDIVIDUAL`, other options are -`Cubature.PAIRED`, `Cubature.L1`, `Cubature.L2`, or `Cubature.LINF`. - -## References - -@article{genz1980remarks, -title={Remarks on algorithm 006: An adaptive algorithm for numerical integration over an N-dimensional rectangular region}, -author={Genz, Alan C and Malik, Aftab Ahmad}, -journal={Journal of Computational and Applied mathematics}, -volume={6}, -number={4}, -pages={295--302}, -year={1980}, -publisher={Elsevier} -} -""" -struct CubatureJLh <: AbstractCubatureJLAlgorithm - error_norm::Int32 -end - -""" - CubatureJLp() - -Multidimensional p-adaptive integration from Cubature.jl. -This method is based on repeatedly doubling the degree of the cubature rules, -until convergence is achieved. -The used cubature rule is a tensor product of Clenshaw–Curtis quadrature rules. -`error_norm` specifies the convergence criterion for vector valued integrands. -Defaults to `Cubature.INDIVIDUAL`, other options are -`Cubature.PAIRED`, `Cubature.L1`, `Cubature.L2`, or `Cubature.LINF`. -""" -struct CubatureJLp <: AbstractCubatureJLAlgorithm - error_norm::Int32 -end - - -""" - ArblibJL(; check_analytic=false, take_prec=false, warn_on_no_convergence=false, opts=C_NULL) - -One-dimensional adaptive Gauss-Legendre integration using rigorous error bounds and -precision ball arithmetic. Generally this assumes the integrand is holomorphic or -meromorphic, which is the user's responsibility to verify. The result of the integral is not -guaranteed to satisfy the requested tolerances, however the result is guaranteed to be -within the error estimate. - -[Arblib.jl](https://github.com/kalmarek/Arblib.jl) only supports integration of univariate -real- and complex-valued functions with both inplace and out-of-place forms. See their -documentation for additional details the algorithm arguments and on implementing -high-precision integrands. Additionally, the error estimate is included in the return value -of the integral, representing a ball. -""" -struct ArblibJL{O} <: SciMLBase.AbstractIntegralAlgorithm - check_analytic::Bool - take_prec::Bool - warn_on_no_convergence::Bool - opts::O -end -function ArblibJL(; check_analytic=false, take_prec=false, warn_on_no_convergence=false, opts=C_NULL) - return ArblibJL(check_analytic, take_prec, warn_on_no_convergence, opts) -end - -""" - VEGASMC(; kws...) - -Markov-chain based Vegas algorithm from MCIntegration.jl - -Refer to -[`MCIntegration.integrate`](https://numericaleft.github.io/MCIntegration.jl/dev/lib/montecarlo/#MCIntegration.integrate-Tuple{Function}) -for documentation on the keywords, which are passed directly to the solver with a set of -defaults that works for conforming integrands. -""" -struct VEGASMC{K<:NamedTuple} <: SciMLBase.AbstractIntegralAlgorithm - kws::K -end -VEGASMC(; kws...) = VEGASMC(NamedTuple(kws)) diff --git a/src/algorithms_extension.jl b/src/algorithms_extension.jl new file mode 100644 index 0000000..b79eaa8 --- /dev/null +++ b/src/algorithms_extension.jl @@ -0,0 +1,245 @@ +## Extension Algorithms + +abstract type AbstractIntegralExtensionAlgorithm <: SciMLBase.AbstractIntegralAlgorithm end + +abstract type AbstractCubaAlgorithm <: AbstractIntegralExtensionAlgorithm end + +""" + CubaVegas() + +Multidimensional adaptive Monte Carlo integration from Cuba.jl. +Importance sampling is used to reduce variance. + +## References + +@article{lepage1978new, +title={A new algorithm for adaptive multidimensional integration}, +author={Lepage, G Peter}, +journal={Journal of Computational Physics}, +volume={27}, +number={2}, +pages={192--203}, +year={1978}, +publisher={Elsevier} +} +""" +struct CubaVegas <: AbstractCubaAlgorithm + flags::Int + seed::Int + minevals::Int + nstart::Int + nincrease::Int + gridno::Int +end + +""" + CubaSUAVE() + +Multidimensional adaptive Monte Carlo integration from Cuba.jl. +Suave stands for subregion-adaptive VEGAS. +Importance sampling and subdivision are thus used to reduce variance. + +## References + +@article{hahn2005cuba, +title={Cuba—a library for multidimensional numerical integration}, +author={Hahn, Thomas}, +journal={Computer Physics Communications}, +volume={168}, +number={2}, +pages={78--95}, +year={2005}, +publisher={Elsevier} +} +""" +struct CubaSUAVE{R} <: AbstractCubaAlgorithm where {R <: Real} + flags::Int + seed::Int + minevals::Int + nnew::Int + nmin::Int + flatness::R +end + +""" + CubaDivonne() + +Multidimensional adaptive Monte Carlo integration from Cuba.jl. +Stratified sampling is used to reduce variance. + +## References + +@article{friedman1981nested, +title={A nested partitioning procedure for numerical multiple integration}, +author={Friedman, Jerome H and Wright, Margaret H}, +journal={ACM Transactions on Mathematical Software (TOMS)}, +volume={7}, +number={1}, +pages={76--92}, +year={1981}, +publisher={ACM New York, NY, USA} +} +""" +struct CubaDivonne{R1, R2, R3, R4} <: + AbstractCubaAlgorithm where {R1 <: Real, R2 <: Real, R3 <: Real, R4 <: Real} + flags::Int + seed::Int + minevals::Int + key1::Int + key2::Int + key3::Int + maxpass::Int + border::R1 + maxchisq::R2 + mindeviation::R3 + xgiven::Matrix{R4} + nextra::Int + peakfinder::Ptr{Cvoid} +end + +""" + CubaCuhre() + +Multidimensional h-adaptive integration from Cuba.jl. + +## References + +@article{berntsen1991adaptive, +title={An adaptive algorithm for the approximate calculation of multiple integrals}, +author={Berntsen, Jarle and Espelid, Terje O and Genz, Alan}, +journal={ACM Transactions on Mathematical Software (TOMS)}, +volume={17}, +number={4}, +pages={437--451}, +year={1991}, +publisher={ACM New York, NY, USA} +} +""" +struct CubaCuhre <: AbstractCubaAlgorithm + flags::Int + minevals::Int + key::Int +end + +function CubaVegas(; flags = 0, seed = 0, minevals = 0, nstart = 1000, nincrease = 500, + gridno = 0) + isnothing(Base.get_extension(@__MODULE__, :IntegralsCubaExt)) && error("CubaVegas requires `using Cuba`") + return CubaVegas(flags, seed, minevals, nstart, nincrease, gridno) +end + +function CubaSUAVE(; flags = 0, seed = 0, minevals = 0, nnew = 1000, nmin = 2, + flatness = 25.0) + isnothing(Base.get_extension(@__MODULE__, :IntegralsCubaExt)) && error("CubaSUAVE requires `using Cuba`") + return CubaSUAVE(flags, seed, minevals, nnew, nmin, flatness) +end + +function CubaDivonne(; flags = 0, seed = 0, minevals = 0, + key1 = 47, key2 = 1, key3 = 1, maxpass = 5, border = 0.0, + maxchisq = 10.0, mindeviation = 0.25, + xgiven = zeros(Cdouble, 0, 0), + nextra = 0, peakfinder = C_NULL) + isnothing(Base.get_extension(@__MODULE__, :IntegralsCubaExt)) && error("CubaDivonne requires `using Cuba`") + return CubaDivonne(flags, seed, minevals, key1, key2, key3, maxpass, border, maxchisq, + mindeviation, xgiven, nextra, peakfinder) +end + +function CubaCuhre(; flags = 0, minevals = 0, key = 0) + isnothing(Base.get_extension(@__MODULE__, :IntegralsCubaExt)) && error("CubaCuhre requires `using Cuba`") + return CubaCuhre(flags, minevals, key) +end + +abstract type AbstractCubatureJLAlgorithm <: AbstractIntegralExtensionAlgorithm end + +""" + CubatureJLh(; error_norm=Cubature.INDIVIDUAL) + +Multidimensional h-adaptive integration from Cubature.jl. +`error_norm` specifies the convergence criterion for vector valued integrands. +Defaults to `Cubature.INDIVIDUAL`, other options are +`Cubature.PAIRED`, `Cubature.L1`, `Cubature.L2`, or `Cubature.LINF`. + +## References + +@article{genz1980remarks, +title={Remarks on algorithm 006: An adaptive algorithm for numerical integration over an N-dimensional rectangular region}, +author={Genz, Alan C and Malik, Aftab Ahmad}, +journal={Journal of Computational and Applied mathematics}, +volume={6}, +number={4}, +pages={295--302}, +year={1980}, +publisher={Elsevier} +} +""" +struct CubatureJLh <: AbstractCubatureJLAlgorithm + error_norm::Int32 +end +function CubatureJLh(; error_norm=0) + isnothing(Base.get_extension(@__MODULE__, :IntegralsCubatureExt)) && error("CubatureJLh requires `using Cubature`") + return CubatureJLh(error_norm) +end + +""" + CubatureJLp(; error_norm=Cubature.INDIVIDUAL) + +Multidimensional p-adaptive integration from Cubature.jl. +This method is based on repeatedly doubling the degree of the cubature rules, +until convergence is achieved. +The used cubature rule is a tensor product of Clenshaw–Curtis quadrature rules. +`error_norm` specifies the convergence criterion for vector valued integrands. +Defaults to `Cubature.INDIVIDUAL`, other options are +`Cubature.PAIRED`, `Cubature.L1`, `Cubature.L2`, or `Cubature.LINF`. +""" +struct CubatureJLp <: AbstractCubatureJLAlgorithm + error_norm::Int32 +end +function CubatureJLp(; error_norm=0) + isnothing(Base.get_extension(@__MODULE__, :IntegralsCubatureExt)) && error("CubatureJLp requires `using Cubature`") + return CubatureJLp(error_norm) +end + + + +""" + ArblibJL(; check_analytic=false, take_prec=false, warn_on_no_convergence=false, opts=C_NULL) + +One-dimensional adaptive Gauss-Legendre integration using rigorous error bounds and +precision ball arithmetic. Generally this assumes the integrand is holomorphic or +meromorphic, which is the user's responsibility to verify. The result of the integral is not +guaranteed to satisfy the requested tolerances, however the result is guaranteed to be +within the error estimate. + +[Arblib.jl](https://github.com/kalmarek/Arblib.jl) only supports integration of univariate +real- and complex-valued functions with both inplace and out-of-place forms. See their +documentation for additional details the algorithm arguments and on implementing +high-precision integrands. Additionally, the error estimate is included in the return value +of the integral, representing a ball. +""" +struct ArblibJL{O} <: AbstractIntegralExtensionAlgorithm + check_analytic::Bool + take_prec::Bool + warn_on_no_convergence::Bool + opts::O +end +function ArblibJL(; check_analytic=false, take_prec=false, warn_on_no_convergence=false, opts=C_NULL) + isnothing(Base.get_extension(@__MODULE__, :IntegralsArblibExt)) && error("ArblibJL requires `using Arblib`") + return ArblibJL(check_analytic, take_prec, warn_on_no_convergence, opts) +end + +""" + VEGASMC(; kws...) + +Markov-chain based Vegas algorithm from MCIntegration.jl + +Refer to +[`MCIntegration.integrate`](https://numericaleft.github.io/MCIntegration.jl/dev/lib/montecarlo/#MCIntegration.integrate-Tuple{Function}) +for documentation on the keywords, which are passed directly to the solver with a set of +defaults that works for conforming integrands. +""" +struct VEGASMC{K<:NamedTuple} <: AbstractIntegralExtensionAlgorithm + kws::K +end +function VEGASMC(; kws...) + isnothing(Base.get_extension(@__MODULE__, :IntegralsMCIntegrationExt)) && error("VEGASMC requires `using MCIntegration`") + return VEGASMC(NamedTuple(kws)) +end diff --git a/src/algorithms_sampled.jl b/src/algorithms_sampled.jl new file mode 100644 index 0000000..6cd5dd5 --- /dev/null +++ b/src/algorithms_sampled.jl @@ -0,0 +1,43 @@ +abstract type AbstractSampledIntegralAlgorithm <: SciMLBase.AbstractIntegralAlgorithm end + +""" + TrapezoidalRule + +Struct for evaluating an integral via the trapezoidal rule. + + +Example with sampled data: + +``` +using Integrals +f = x -> x^2 +x = range(0, 1, length=20) +y = f.(x) +problem = SampledIntegralProblem(y, x) +method = TrapezoidalRule() +solve(problem, method) +``` +""" +struct TrapezoidalRule <: AbstractSampledIntegralAlgorithm end + +""" + SimpsonsRule + +Struct for evaluating an integral via the Simpson's composite 1/3-3/8 +rule over `AbstractRange`s (evenly spaced points) and +Simpson's composite 1/3 rule for non-equidistant grids. + + +Example with equidistant data: + +``` +using Integrals +f = x -> x^2 +x = range(0, 1, length=20) +y = f.(x) +problem = SampledIntegralProblem(y, x) +method = SimpsonsRule() +solve(problem, method) +``` +""" +struct SimpsonsRule <: AbstractSampledIntegralAlgorithm end