Integrand toString

This commit is contained in:
Alexander Nozik 2021-05-24 14:30:51 +03:00
parent 380c76fe40
commit 12805712d3
5 changed files with 66 additions and 43 deletions

View File

@ -18,12 +18,6 @@ public class CMIntegrator(
public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator, public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator,
) : UnivariateIntegrator<Double> { ) : UnivariateIntegrator<Double> {
public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature
public class TargetAbsoluteAccuracy(public val value: Double) : IntegrandFeature
public class MinIterations(public val value: Int) : IntegrandFeature
public class MaxIterations(public val value: Int) : IntegrandFeature
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> { override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
val integrator = integratorBuilder(integrand) val integrator = integratorBuilder(integrand)
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
@ -45,16 +39,15 @@ public class CMIntegrator(
* Create a Simpson integrator based on [SimpsonIntegrator] * Create a Simpson integrator based on [SimpsonIntegrator]
*/ */
public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand -> public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand ->
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value val absoluteAccuracy = integrand.getFeature<IntegrandAbsoluteAccuracy>()?.accuracy
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val minIterations = integrand.getFeature<MinIterations>()?.value val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT ?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
val maxIterations = integrand.getFeature<MaxIterations>()?.value
?: SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, minIterations, maxIterations)
SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, iterations.first, iterations.last)
} }
/** /**
@ -62,21 +55,19 @@ public class CMIntegrator(
*/ */
public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator = public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator =
CMIntegrator(defaultMaxCalls) { integrand -> CMIntegrator(defaultMaxCalls) { integrand ->
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value val absoluteAccuracy = integrand.getFeature<IntegrandAbsoluteAccuracy>()?.accuracy
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY ?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val minIterations = integrand.getFeature<MinIterations>()?.value val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT ?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
val maxIterations = integrand.getFeature<MaxIterations>()?.value
?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
IterativeLegendreGaussIntegrator( IterativeLegendreGaussIntegrator(
numPoints, numPoints,
relativeAccuracy, relativeAccuracy,
absoluteAccuracy, absoluteAccuracy,
minIterations, iterations.first,
maxIterations iterations.last
) )
} }
} }
@ -84,14 +75,14 @@ public class CMIntegrator(
@UnstableKMathAPI @UnstableKMathAPI
public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double? public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double?
get() = filterIsInstance<CMIntegrator.TargetAbsoluteAccuracy>().lastOrNull()?.value get() = filterIsInstance<IntegrandAbsoluteAccuracy>().lastOrNull()?.accuracy
set(value) { set(value) {
value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) } value?.let { add(IntegrandAbsoluteAccuracy(value)) }
} }
@UnstableKMathAPI @UnstableKMathAPI
public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double? public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double?
get() = filterIsInstance<CMIntegrator.TargetRelativeAccuracy>().lastOrNull()?.value get() = filterIsInstance<IntegrandRelativeAccuracy>().lastOrNull()?.accuracy
set(value) { set(value) {
value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) } value?.let { add(IntegrandRelativeAccuracy(value)) }
} }

View File

@ -164,4 +164,6 @@ public object GaussLegendreRuleFactory : GaussIntegratorRuleFactory {
} }
override fun build(numPoints: Int): Pair<Buffer<Double>, Buffer<Double>> = getOrBuildRule(numPoints) override fun build(numPoints: Int): Pair<Buffer<Double>, Buffer<Double>> = getOrBuildRule(numPoints)
override fun toString(): String = "GaussLegendreRule"
} }

View File

@ -7,22 +7,39 @@ package space.kscience.kmath.integration
import kotlin.reflect.KClass import kotlin.reflect.KClass
public interface IntegrandFeature public interface IntegrandFeature {
override fun toString(): String
}
public interface Integrand { public interface Integrand {
public val features: Set<IntegrandFeature>
public fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? public fun <T : IntegrandFeature> getFeature(type: KClass<T>): T?
} }
public inline fun <reified T : IntegrandFeature> Integrand.getFeature(): T? = getFeature(T::class) public inline fun <reified T : IntegrandFeature> Integrand.getFeature(): T? = getFeature(T::class)
public class IntegrandValue<T : Any>(public val value: T) : IntegrandFeature public class IntegrandValue<T : Any>(public val value: T) : IntegrandFeature {
override fun toString(): String = "Value($value)"
}
public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature {
override fun toString(): String = "TargetRelativeAccuracy($accuracy)"
}
public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature {
override fun toString(): String = "TargetAbsoluteAccuracy($accuracy)"
}
public class IntegrandCallsPerformed(public val calls: Int) : IntegrandFeature public class IntegrandCallsPerformed(public val calls: Int) : IntegrandFeature {
override fun toString(): String = "Calls($calls)"
}
public val Integrand.calls: Int get() = getFeature<IntegrandCallsPerformed>()?.calls ?: 0 public val Integrand.calls: Int get() = getFeature<IntegrandCallsPerformed>()?.calls ?: 0
public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature {
override fun toString(): String = "MaxCalls($maxCalls)"
}
public class IntegrandIterationsRange(public val range: IntRange) : IntegrandFeature {
override fun toString(): String = "Iterations(${range.first}..${range.last})"
}

View File

@ -9,15 +9,17 @@ import space.kscience.kmath.linear.Point
import kotlin.reflect.KClass import kotlin.reflect.KClass
public class MultivariateIntegrand<T : Any> internal constructor( public class MultivariateIntegrand<T : Any> internal constructor(
private val features: Map<KClass<*>, IntegrandFeature>, private val featureMap: Map<KClass<*>, IntegrandFeature>,
public val function: (Point<T>) -> T, public val function: (Point<T>) -> T,
) : Integrand { ) : Integrand {
override val features: Set<IntegrandFeature> get() = featureMap.values.toSet()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? = features[type] as? T override fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? = featureMap[type] as? T
public operator fun <F : IntegrandFeature> plus(pair: Pair<KClass<out F>, F>): MultivariateIntegrand<T> = public operator fun <F : IntegrandFeature> plus(pair: Pair<KClass<out F>, F>): MultivariateIntegrand<T> =
MultivariateIntegrand(features + pair, function) MultivariateIntegrand(featureMap + pair, function)
public operator fun <F : IntegrandFeature> plus(feature: F): MultivariateIntegrand<T> = public operator fun <F : IntegrandFeature> plus(feature: F): MultivariateIntegrand<T> =
plus(feature::class to feature) plus(feature::class to feature)

View File

@ -8,19 +8,20 @@ package space.kscience.kmath.integration
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.DoubleBuffer import space.kscience.kmath.structures.DoubleBuffer
import kotlin.jvm.JvmInline
import kotlin.reflect.KClass import kotlin.reflect.KClass
public class UnivariateIntegrand<T> internal constructor( public class UnivariateIntegrand<T> internal constructor(
private val features: Map<KClass<*>, IntegrandFeature>, private val featureMap: Map<KClass<*>, IntegrandFeature>,
public val function: (Double) -> T, public val function: (Double) -> T,
) : Integrand { ) : Integrand {
override val features: Set<IntegrandFeature> get() = featureMap.values.toSet()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? = features[type] as? T override fun <T : IntegrandFeature> getFeature(type: KClass<T>): T? = featureMap[type] as? T
public operator fun <F : IntegrandFeature> plus(pair: Pair<KClass<out F>, F>): UnivariateIntegrand<T> = public operator fun <F : IntegrandFeature> plus(pair: Pair<KClass<out F>, F>): UnivariateIntegrand<T> =
UnivariateIntegrand(features + pair, function) UnivariateIntegrand(featureMap + pair, function)
public operator fun <F : IntegrandFeature> plus(feature: F): UnivariateIntegrand<T> = public operator fun <F : IntegrandFeature> plus(feature: F): UnivariateIntegrand<T> =
plus(feature::class to feature) plus(feature::class to feature)
@ -34,8 +35,9 @@ public fun <T : Any> UnivariateIntegrand(
public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>> public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
@JvmInline public class IntegrationRange(public val range: ClosedRange<Double>) : IntegrandFeature {
public value class IntegrationRange(public val range: ClosedRange<Double>) : IntegrandFeature override fun toString(): String = "Range(${range.start}..${range.endInclusive})"
}
/** /**
* Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of * Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of
@ -43,10 +45,19 @@ public value class IntegrationRange(public val range: ClosedRange<Double>) : Int
*/ */
public class UnivariateIntegrandRanges(public val ranges: List<Pair<ClosedRange<Double>, Int>>) : IntegrandFeature { public class UnivariateIntegrandRanges(public val ranges: List<Pair<ClosedRange<Double>, Int>>) : IntegrandFeature {
public constructor(vararg pairs: Pair<ClosedRange<Double>, Int>) : this(pairs.toList()) public constructor(vararg pairs: Pair<ClosedRange<Double>, Int>) : this(pairs.toList())
override fun toString(): String {
val rangesString = ranges.joinToString(separator = ",") { (range, points) ->
"${range.start}..${range.endInclusive} : $points"
}
return "UnivariateRanges($rangesString)"
}
} }
public class UnivariateIntegrationNodes(public val nodes: Buffer<Double>) : IntegrandFeature { public class UnivariateIntegrationNodes(public val nodes: Buffer<Double>) : IntegrandFeature {
public constructor(vararg nodes: Double) : this(DoubleBuffer(nodes)) public constructor(vararg nodes: Double) : this(DoubleBuffer(nodes))
override fun toString(): String = "UnivariateNodes($nodes)"
} }
@ -65,7 +76,7 @@ public val <T : Any> UnivariateIntegrand<T>.value: T get() = valueOrNull ?: erro
* 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 fun <T : Any> UnivariateIntegrator<T>.integrate(
vararg features: IntegrandFeature, vararg features: IntegrandFeature,
function: (Double) -> T, function: (Double) -> T,
): UnivariateIntegrand<T> = integrate(UnivariateIntegrand(function, *features)) ): UnivariateIntegrand<T> = integrate(UnivariateIntegrand(function, *features))
@ -75,7 +86,7 @@ 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 fun <T : Any> UnivariateIntegrator<T>.integrate(
range: ClosedRange<Double>, range: ClosedRange<Double>,
vararg features: IntegrandFeature, vararg features: IntegrandFeature,
function: (Double) -> T, function: (Double) -> T,
@ -86,7 +97,7 @@ 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 fun <T : Any> UnivariateIntegrator<T>.integrate(
range: ClosedRange<Double>, range: ClosedRange<Double>,
featureBuilder: MutableList<IntegrandFeature>.() -> Unit = {}, featureBuilder: MutableList<IntegrandFeature>.() -> Unit = {},
function: (Double) -> T, function: (Double) -> T,