Update integration to use Attributes
This commit is contained in:
parent
5196322b7a
commit
9da14089e0
@ -13,26 +13,29 @@ import space.kscience.kmath.integration.*
|
||||
*/
|
||||
public class CMGaussRuleIntegrator(
|
||||
private val numpoints: Int,
|
||||
private var type: GaussRule = GaussRule.LEGANDRE,
|
||||
private var type: GaussRule = GaussRule.LEGENDRE,
|
||||
) : UnivariateIntegrator<Double> {
|
||||
|
||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
val range = integrand.getFeature<IntegrationRange>()?.range
|
||||
val range = integrand[IntegrationRange]
|
||||
?: error("Integration range is not provided")
|
||||
val integrator: GaussIntegrator = getIntegrator(range)
|
||||
//TODO check performance
|
||||
val res: Double = integrator.integrate(integrand.function)
|
||||
return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + numpoints)
|
||||
return integrand.modify {
|
||||
IntegrandValue(res)
|
||||
IntegrandCallsPerformed(integrand.calls + numpoints)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIntegrator(range: ClosedRange<Double>): GaussIntegrator {
|
||||
return when (type) {
|
||||
GaussRule.LEGANDRE -> factory.legendre(
|
||||
GaussRule.LEGENDRE -> factory.legendre(
|
||||
numpoints,
|
||||
range.start,
|
||||
range.endInclusive
|
||||
)
|
||||
GaussRule.LEGANDREHP -> factory.legendreHighPrecision(
|
||||
GaussRule.LEGENDREHP -> factory.legendreHighPrecision(
|
||||
numpoints,
|
||||
range.start,
|
||||
range.endInclusive
|
||||
@ -65,7 +68,7 @@ public class CMGaussRuleIntegrator(
|
||||
}
|
||||
|
||||
public enum class GaussRule {
|
||||
UNIFORM, LEGANDRE, LEGANDREHP
|
||||
UNIFORM, LEGENDRE, LEGENDREHP
|
||||
}
|
||||
|
||||
public companion object {
|
||||
@ -74,10 +77,10 @@ public class CMGaussRuleIntegrator(
|
||||
public fun integrate(
|
||||
range: ClosedRange<Double>,
|
||||
numPoints: Int = 100,
|
||||
type: GaussRule = GaussRule.LEGANDRE,
|
||||
type: GaussRule = GaussRule.LEGENDRE,
|
||||
function: (Double) -> Double,
|
||||
): Double = CMGaussRuleIntegrator(numPoints, type).process(
|
||||
UnivariateIntegrand(function, IntegrationRange(range))
|
||||
UnivariateIntegrand({IntegrationRange(range)},function)
|
||||
).value
|
||||
}
|
||||
}
|
@ -9,13 +9,14 @@ import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussInteg
|
||||
import org.apache.commons.math3.analysis.integration.SimpsonIntegrator
|
||||
import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.integration.*
|
||||
import org.apache.commons.math3.analysis.integration.UnivariateIntegrator as CMUnivariateIntegrator
|
||||
|
||||
/**
|
||||
* Integration wrapper for Common-maths UnivariateIntegrator
|
||||
*/
|
||||
public class CMIntegrator(
|
||||
private val defaultMaxCalls: Int = 200,
|
||||
public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator,
|
||||
public val integratorBuilder: (Integrand<Double>) -> CMUnivariateIntegrator,
|
||||
) : UnivariateIntegrator<Double> {
|
||||
|
||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||
@ -25,12 +26,13 @@ public class CMIntegrator(
|
||||
val range = integrand[IntegrationRange] ?: error("Integration range is not provided")
|
||||
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
|
||||
|
||||
return integrand +
|
||||
IntegrandValue(res) +
|
||||
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) +
|
||||
IntegrandRelativeAccuracy(integrator.relativeAccuracy) +
|
||||
return integrand.modify {
|
||||
value(res)
|
||||
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy)
|
||||
IntegrandRelativeAccuracy(integrator.relativeAccuracy)
|
||||
IntegrandCallsPerformed(integrator.evaluations + integrand.calls)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public companion object {
|
||||
|
@ -5,13 +5,17 @@
|
||||
|
||||
package space.kscience.kmath.integration
|
||||
|
||||
import space.kscience.attributes.*
|
||||
import kotlin.reflect.typeOf
|
||||
import space.kscience.attributes.Attribute
|
||||
import space.kscience.attributes.AttributeContainer
|
||||
import space.kscience.attributes.AttributesBuilder
|
||||
import space.kscience.attributes.SafeType
|
||||
|
||||
public interface IntegrandAttribute<T> : Attribute<T>
|
||||
|
||||
public interface Integrand<T> : AttributeContainer {
|
||||
|
||||
public val type: SafeType<T>
|
||||
|
||||
public fun modify(block: AttributesBuilder.() -> Unit): Integrand<T>
|
||||
|
||||
public fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): Integrand<T>
|
||||
@ -21,19 +25,21 @@ public interface Integrand<T> : AttributeContainer {
|
||||
|
||||
public operator fun <T> Integrand<*>.get(attribute: Attribute<T>): T? = attributes[attribute]
|
||||
|
||||
public class IntegrandValue<T>(type: SafeType<T>) : PolymorphicAttribute<T>(type), IntegrandAttribute<T>
|
||||
public sealed class IntegrandValue<T> private constructor(): IntegrandAttribute<T>{
|
||||
public companion object: IntegrandValue<Any?>(){
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <T> forType(): IntegrandValue<T> = this as IntegrandValue<T>
|
||||
}
|
||||
}
|
||||
|
||||
public inline val <reified T : Any> Integrand<T>.Value: IntegrandValue<T> get() = IntegrandValue(safeTypeOf())
|
||||
|
||||
public fun <T> AttributesBuilder.value(value: T){
|
||||
val type: SafeType<T> = typeOf<T>()
|
||||
IntegrandValue(type).invoke(value)
|
||||
public fun <T> AttributesBuilder.value(value: T) {
|
||||
IntegrandValue.forType<T>().invoke(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Value of the integrand if it is present or null
|
||||
*/
|
||||
public inline val <reified T : Any> Integrand<T>.valueOrNull: T? get() = attributes[Value]
|
||||
public inline val <reified T : Any> Integrand<T>.valueOrNull: T? get() = attributes[IntegrandValue.forType<T>()]
|
||||
|
||||
/**
|
||||
* Value of the integrand or error
|
||||
|
@ -8,19 +8,20 @@ package space.kscience.kmath.integration
|
||||
import space.kscience.attributes.*
|
||||
import space.kscience.kmath.linear.Point
|
||||
|
||||
public class MultivariateIntegrand<T> internal constructor(
|
||||
public class MultivariateIntegrand<T>(
|
||||
override val type: SafeType<T>,
|
||||
override val attributes: Attributes,
|
||||
public val function: (Point<T>) -> T,
|
||||
) : Integrand<T> {
|
||||
|
||||
override fun modify(block: AttributesBuilder.() -> Unit): MultivariateIntegrand<T> =
|
||||
MultivariateIntegrand(attributes.modify(block), function)
|
||||
MultivariateIntegrand(type, attributes.modify(block), function)
|
||||
|
||||
override fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): MultivariateIntegrand<T> =
|
||||
MultivariateIntegrand(attributes.withAttribute(attribute, value), function)
|
||||
MultivariateIntegrand(type, attributes.withAttribute(attribute, value), function)
|
||||
}
|
||||
|
||||
public fun <T : Any> MultivariateIntegrand(
|
||||
public inline fun <reified T : Any> MultivariateIntegrand(
|
||||
attributeBuilder: AttributesBuilder.() -> Unit,
|
||||
function: (Point<T>) -> T,
|
||||
): MultivariateIntegrand<T> = MultivariateIntegrand(Attributes(attributeBuilder), function)
|
||||
noinline function: (Point<T>) -> T,
|
||||
): MultivariateIntegrand<T> = MultivariateIntegrand(safeTypeOf<T>(), Attributes(attributeBuilder), function)
|
||||
|
@ -10,22 +10,23 @@ import space.kscience.kmath.UnstableKMathAPI
|
||||
import space.kscience.kmath.structures.Buffer
|
||||
import space.kscience.kmath.structures.Float64Buffer
|
||||
|
||||
public class UnivariateIntegrand<T> internal constructor(
|
||||
public class UnivariateIntegrand<T>(
|
||||
override val type: SafeType<T>,
|
||||
override val attributes: Attributes,
|
||||
public val function: (Double) -> T,
|
||||
) : Integrand<T> {
|
||||
|
||||
override fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): UnivariateIntegrand<T> =
|
||||
UnivariateIntegrand(attributes.withAttribute(attribute, value), function)
|
||||
UnivariateIntegrand(type, attributes.withAttribute(attribute, value), function)
|
||||
|
||||
override fun modify(block: AttributesBuilder.() -> Unit): UnivariateIntegrand<T> =
|
||||
UnivariateIntegrand(attributes.modify(block), function)
|
||||
UnivariateIntegrand(type, attributes.modify(block), function)
|
||||
}
|
||||
|
||||
public fun <T : Any> UnivariateIntegrand(
|
||||
public inline fun <reified T : Any> UnivariateIntegrand(
|
||||
attributeBuilder: AttributesBuilder.() -> Unit,
|
||||
function: (Double) -> T,
|
||||
): UnivariateIntegrand<T> = UnivariateIntegrand(Attributes(attributeBuilder), function)
|
||||
noinline function: (Double) -> T,
|
||||
): UnivariateIntegrand<T> = UnivariateIntegrand(safeTypeOf(), Attributes(attributeBuilder), function)
|
||||
|
||||
public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
|
||||
|
||||
@ -60,9 +61,9 @@ public fun AttributesBuilder.integrationNodes(vararg nodes: Double) {
|
||||
* The [function] is placed in the end position to allow passing a lambda.
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : Any> UnivariateIntegrator<T>.integrate(
|
||||
public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate(
|
||||
attributesBuilder: AttributesBuilder.() -> Unit,
|
||||
function: (Double) -> T,
|
||||
noinline function: (Double) -> T,
|
||||
): UnivariateIntegrand<T> = process(UnivariateIntegrand(attributesBuilder, function))
|
||||
|
||||
/**
|
||||
@ -70,14 +71,19 @@ public fun <T : Any> UnivariateIntegrator<T>.integrate(
|
||||
* The [function] is placed in the end position to allow passing a lambda.
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
public fun <T : Any> UnivariateIntegrator<T>.integrate(
|
||||
public inline fun <reified T : Any> UnivariateIntegrator<T>.integrate(
|
||||
range: ClosedRange<Double>,
|
||||
attributeBuilder: AttributesBuilder.() -> Unit = {},
|
||||
function: (Double) -> T,
|
||||
noinline function: (Double) -> T,
|
||||
): UnivariateIntegrand<T> {
|
||||
val attributes = Attributes {
|
||||
|
||||
return process(
|
||||
UnivariateIntegrand(
|
||||
attributeBuilder = {
|
||||
IntegrationRange(range)
|
||||
attributeBuilder()
|
||||
}
|
||||
return process(UnivariateIntegrand(attributes, function))
|
||||
},
|
||||
function = function
|
||||
)
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user