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