Update integration to use Attributes
This commit is contained in:
parent
eff70eb690
commit
5196322b7a
@ -59,6 +59,14 @@ public fun <T : Any, A : Attribute<T>> Attributes.withAttribute(
|
|||||||
public fun <A : Attribute<Unit>> Attributes.withAttribute(attribute: A): Attributes =
|
public fun <A : Attribute<Unit>> Attributes.withAttribute(attribute: A): Attributes =
|
||||||
withAttribute(attribute, Unit)
|
withAttribute(attribute, Unit)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new [Attributes] by modifying the current one
|
||||||
|
*/
|
||||||
|
public fun Attributes.modify(block: AttributesBuilder.() -> Unit): Attributes = Attributes {
|
||||||
|
from(this@modify)
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new [Attributes] by removing [attribute] key
|
* Create new [Attributes] by removing [attribute] key
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,9 @@ package space.kscience.attributes
|
|||||||
/**
|
/**
|
||||||
* A safe builder for [Attributes]
|
* A safe builder for [Attributes]
|
||||||
*/
|
*/
|
||||||
public class AttributesBuilder internal constructor(private val map: MutableMap<Attribute<*>, Any> = mutableMapOf()) {
|
public class AttributesBuilder internal constructor(private val map: MutableMap<Attribute<*>, Any>) {
|
||||||
|
|
||||||
|
public constructor() : this(mutableMapOf())
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public operator fun <T> get(attribute: Attribute<T>): T? = map[attribute] as? T
|
public operator fun <T> get(attribute: Attribute<T>): T? = map[attribute] as? T
|
||||||
@ -49,4 +51,5 @@ public fun AttributesBuilder(
|
|||||||
attributes: Attributes,
|
attributes: Attributes,
|
||||||
): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap())
|
): AttributesBuilder = AttributesBuilder(attributes.content.toMutableMap())
|
||||||
|
|
||||||
public fun Attributes(builder: AttributesBuilder.() -> Unit): Attributes = AttributesBuilder().apply(builder).build()
|
public inline fun Attributes(builder: AttributesBuilder.() -> Unit): Attributes =
|
||||||
|
AttributesBuilder().apply(builder).build()
|
@ -20,10 +20,9 @@ public class CMIntegrator(
|
|||||||
|
|
||||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||||
val integrator = integratorBuilder(integrand)
|
val integrator = integratorBuilder(integrand)
|
||||||
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
|
val maxCalls = integrand[IntegrandMaxCalls] ?: defaultMaxCalls
|
||||||
val remainingCalls = maxCalls - integrand.calls
|
val remainingCalls = maxCalls - integrand.calls
|
||||||
val range = integrand.getFeature<IntegrationRange>()?.range
|
val range = integrand[IntegrationRange] ?: error("Integration range is not provided")
|
||||||
?: 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 +
|
||||||
@ -39,11 +38,9 @@ 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<IntegrandAbsoluteAccuracy>()?.accuracy
|
val absoluteAccuracy = integrand[IntegrandAbsoluteAccuracy] ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||||
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
val relativeAccuracy = integrand[IntegrandRelativeAccuracy] ?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||||
val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
|
val iterations = integrand[IntegrandIterationsRange]
|
||||||
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
|
||||||
val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
|
|
||||||
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
|
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
|
||||||
|
|
||||||
|
|
||||||
@ -55,11 +52,11 @@ 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<IntegrandAbsoluteAccuracy>()?.accuracy
|
val absoluteAccuracy = integrand[IntegrandAbsoluteAccuracy]
|
||||||
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||||
val relativeAccuracy = integrand.getFeature<IntegrandRelativeAccuracy>()?.accuracy
|
val relativeAccuracy = integrand[IntegrandRelativeAccuracy]
|
||||||
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
|
||||||
val iterations = integrand.getFeature<IntegrandIterationsRange>()?.range
|
val iterations = integrand[IntegrandIterationsRange]
|
||||||
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
|
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT..IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
|
||||||
|
|
||||||
IterativeLegendreGaussIntegrator(
|
IterativeLegendreGaussIntegrator(
|
||||||
|
@ -135,7 +135,7 @@ public object CMLinearSpace : LinearSpace<Double, Float64Field> {
|
|||||||
override val r: Matrix<Double> by lazy<Matrix<Double>> { CMMatrix(qr.r).withAttribute(UpperTriangular) }
|
override val r: Matrix<Double> by lazy<Matrix<Double>> { CMMatrix(qr.r).withAttribute(UpperTriangular) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SingularValueDecompositionAttribute::class -> object : SingularValueDecompositionAttribute<Double> {
|
SVDAttribute::class -> object : SVDAttribute<Double> {
|
||||||
private val sv by lazy { SingularValueDecomposition(origin) }
|
private val sv by lazy { SingularValueDecomposition(origin) }
|
||||||
override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
|
override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
|
||||||
override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
|
override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
|
||||||
|
@ -13,10 +13,6 @@ import space.kscience.attributes.safeTypeOf
|
|||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.structures.*
|
import space.kscience.kmath.structures.*
|
||||||
import space.kscience.kmath.structures.BufferAccessor2D
|
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
|
||||||
import space.kscience.kmath.structures.MutableBuffer
|
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where
|
* Matrices with this feature support LU factorization with partial pivoting: *[p] · a = [l] · [u]* where
|
||||||
@ -197,8 +193,7 @@ public fun <T : Comparable<T>> LinearSpace<T, Field<T>>.lup(
|
|||||||
public fun LinearSpace<Double, Float64Field>.lup(
|
public fun LinearSpace<Double, Float64Field>.lup(
|
||||||
matrix: Matrix<Double>,
|
matrix: Matrix<Double>,
|
||||||
singularityThreshold: Double = 1e-11,
|
singularityThreshold: Double = 1e-11,
|
||||||
): LupDecomposition<Double> =
|
): LupDecomposition<Double> = lup(matrix) { it < singularityThreshold }
|
||||||
lup(::Float64Buffer, matrix) { it < singularityThreshold }
|
|
||||||
|
|
||||||
internal fun <T : Any, A : Field<T>> LinearSpace<T, A>.solve(
|
internal fun <T : Any, A : Field<T>> LinearSpace<T, A>.solve(
|
||||||
lup: LupDecomposition<T>,
|
lup: LupDecomposition<T>,
|
||||||
@ -265,4 +260,4 @@ public fun <T : Comparable<T>, F : Field<T>> LinearSpace<T, F>.lupSolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun LinearSpace<Double, Float64Field>.lupSolver(singularityThreshold: Double = 1e-11): LinearSolver<Double> =
|
public fun LinearSpace<Double, Float64Field>.lupSolver(singularityThreshold: Double = 1e-11): LinearSolver<Double> =
|
||||||
lupSolver(::Float64Buffer) { it < singularityThreshold }
|
lupSolver { it < singularityThreshold }
|
||||||
|
@ -163,12 +163,12 @@ public interface SingularValueDecomposition<T> {
|
|||||||
*
|
*
|
||||||
* @param T the type of matrices' items.
|
* @param T the type of matrices' items.
|
||||||
*/
|
*/
|
||||||
public class SingularValueDecompositionAttribute<T>(type: SafeType<SingularValueDecomposition<T>>) :
|
public class SVDAttribute<T>(type: SafeType<SingularValueDecomposition<T>>) :
|
||||||
PolymorphicAttribute<SingularValueDecomposition<T>>(type),
|
PolymorphicAttribute<SingularValueDecomposition<T>>(type),
|
||||||
MatrixAttribute<SingularValueDecomposition<T>>
|
MatrixAttribute<SingularValueDecomposition<T>>
|
||||||
|
|
||||||
public val <T> MatrixOperations<T>.SVD: SingularValueDecompositionAttribute<T>
|
public val <T> MatrixOperations<T>.SVD: SVDAttribute<T>
|
||||||
get() = SingularValueDecompositionAttribute(safeTypeOf())
|
get() = SVDAttribute(safeTypeOf())
|
||||||
|
|
||||||
|
|
||||||
//TODO add sparse matrix feature
|
//TODO add sparse matrix feature
|
@ -240,7 +240,6 @@ public interface MutableStructureND<T> : StructureND<T> {
|
|||||||
* Set value at specified indices
|
* Set value at specified indices
|
||||||
*/
|
*/
|
||||||
@PerformancePitfall
|
@PerformancePitfall
|
||||||
@Deprecated("")
|
|
||||||
public operator fun <T> MutableStructureND<T>.set(vararg index: Int, value: T) {
|
public operator fun <T> MutableStructureND<T>.set(vararg index: Int, value: T) {
|
||||||
set(index, value)
|
set(index, value)
|
||||||
}
|
}
|
@ -20,9 +20,4 @@ public fun <C> Polynomial(coefficients: List<C>, reverse: Boolean = false): Poly
|
|||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <C> Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial<C> =
|
public fun <C> Polynomial(vararg coefficients: C, reverse: Boolean = false): Polynomial<C> =
|
||||||
Polynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
Polynomial(with(coefficients) { if (reverse) reversed() else toList() })
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents [this] constant as a [Polynomial].
|
|
||||||
*/
|
|
||||||
public fun <C> C.asPolynomial() : Polynomial<C> = Polynomial(listOf(this))
|
|
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
package space.kscience.kmath.integration
|
package space.kscience.kmath.integration
|
||||||
|
|
||||||
|
import space.kscience.attributes.AttributesBuilder
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
@ -11,14 +12,14 @@ import space.kscience.kmath.structures.asBuffer
|
|||||||
import space.kscience.kmath.structures.indices
|
import space.kscience.kmath.structures.indices
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple one-pass integrator based on Gauss rule
|
* A simple one-pass integrator based on Gauss rule.
|
||||||
* Following integrand features are accepted:
|
* The following integrand features are accepted:
|
||||||
*
|
*
|
||||||
* * [GaussIntegratorRuleFactory]—a factory for computing the Gauss integration rule. By default, uses
|
* * [GaussIntegratorRuleFactory]—a factory for computing the Gauss integration rule. By default, uses
|
||||||
* [GaussLegendreRuleFactory].
|
* [GaussLegendreRuleFactory].
|
||||||
* * [IntegrationRange]—the univariate range of integration. By default, uses `0..1` interval.
|
* * [IntegrationRange]—the univariate range of integration. By default, uses `0..1` interval.
|
||||||
* * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always
|
* * [IntegrandMaxCalls]—the maximum number of function calls during integration. For non-iterative rules, always
|
||||||
* uses the maximum number of points. By default, uses 10 points.
|
* use the maximum number of points. By default, uses 10 points.
|
||||||
* * [UnivariateIntegrandRanges]—set of ranges and number of points per range. Defaults to given
|
* * [UnivariateIntegrandRanges]—set of ranges and number of points per range. Defaults to given
|
||||||
* [IntegrationRange] and [IntegrandMaxCalls].
|
* [IntegrationRange] and [IntegrandMaxCalls].
|
||||||
*/
|
*/
|
||||||
@ -27,11 +28,11 @@ public class GaussIntegrator<T : Any>(
|
|||||||
) : UnivariateIntegrator<T> {
|
) : UnivariateIntegrator<T> {
|
||||||
|
|
||||||
private fun buildRule(integrand: UnivariateIntegrand<T>): Pair<Buffer<Double>, Buffer<Double>> {
|
private fun buildRule(integrand: UnivariateIntegrand<T>): Pair<Buffer<Double>, Buffer<Double>> {
|
||||||
val factory = integrand.getFeature<GaussIntegratorRuleFactory>() ?: GaussLegendreRuleFactory
|
val factory = integrand[GaussIntegratorRuleFactory] ?: GaussLegendreRuleFactory
|
||||||
val predefinedRanges = integrand.getFeature<UnivariateIntegrandRanges>()
|
val predefinedRanges = integrand[UnivariateIntegrandRanges]
|
||||||
if (predefinedRanges == null || predefinedRanges.ranges.isEmpty()) {
|
if (predefinedRanges == null || predefinedRanges.ranges.isEmpty()) {
|
||||||
val numPoints = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: 100
|
val numPoints = integrand[IntegrandMaxCalls] ?: 100
|
||||||
val range = integrand.getFeature<IntegrationRange>()?.range ?: 0.0..1.0
|
val range = integrand[IntegrationRange] ?: 0.0..1.0
|
||||||
return factory.build(numPoints, range)
|
return factory.build(numPoints, range)
|
||||||
} else {
|
} else {
|
||||||
val ranges = predefinedRanges.ranges
|
val ranges = predefinedRanges.ranges
|
||||||
@ -66,7 +67,10 @@ public class GaussIntegrator<T : Any>(
|
|||||||
c = t - res - y
|
c = t - res - y
|
||||||
res = t
|
res = t
|
||||||
}
|
}
|
||||||
return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + points.size)
|
return integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + points.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
@ -88,7 +92,7 @@ public fun <T : Any> GaussIntegrator<T>.integrate(
|
|||||||
range: ClosedRange<Double>,
|
range: ClosedRange<Double>,
|
||||||
order: Int = 10,
|
order: Int = 10,
|
||||||
intervals: Int = 10,
|
intervals: Int = 10,
|
||||||
vararg features: IntegrandFeature,
|
attributesBuilder: AttributesBuilder.() -> Unit,
|
||||||
function: (Double) -> T,
|
function: (Double) -> T,
|
||||||
): UnivariateIntegrand<T> {
|
): UnivariateIntegrand<T> {
|
||||||
require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" }
|
require(range.endInclusive > range.start) { "The range upper bound should be higher than lower bound" }
|
||||||
@ -100,11 +104,13 @@ public fun <T : Any> GaussIntegrator<T>.integrate(
|
|||||||
)
|
)
|
||||||
return process(
|
return process(
|
||||||
UnivariateIntegrand(
|
UnivariateIntegrand(
|
||||||
function,
|
attributeBuilder = {
|
||||||
IntegrationRange(range),
|
IntegrationRange(range)
|
||||||
GaussLegendreRuleFactory,
|
GaussIntegratorRuleFactory(GaussLegendreRuleFactory)
|
||||||
ranges,
|
UnivariateIntegrandRanges(ranges)
|
||||||
*features
|
attributesBuilder()
|
||||||
|
},
|
||||||
|
function = function,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -12,10 +12,10 @@ import space.kscience.kmath.structures.asBuffer
|
|||||||
import kotlin.math.ulp
|
import kotlin.math.ulp
|
||||||
import kotlin.native.concurrent.ThreadLocal
|
import kotlin.native.concurrent.ThreadLocal
|
||||||
|
|
||||||
public interface GaussIntegratorRuleFactory : IntegrandFeature {
|
public interface GaussIntegratorRuleFactory {
|
||||||
public fun build(numPoints: Int): Pair<Buffer<Double>, Buffer<Double>>
|
public fun build(numPoints: Int): Pair<Buffer<Double>, Buffer<Double>>
|
||||||
|
|
||||||
public companion object {
|
public companion object: IntegrandAttribute<GaussIntegratorRuleFactory>{
|
||||||
public fun double(numPoints: Int, range: ClosedRange<Double>): Pair<Buffer<Double>, Buffer<Double>> =
|
public fun double(numPoints: Int, range: ClosedRange<Double>): Pair<Buffer<Double>, Buffer<Double>> =
|
||||||
GaussLegendreRuleFactory.build(numPoints, range)
|
GaussLegendreRuleFactory.build(numPoints, range)
|
||||||
}
|
}
|
||||||
|
@ -5,44 +5,49 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.integration
|
package space.kscience.kmath.integration
|
||||||
|
|
||||||
import space.kscience.kmath.misc.Feature
|
import space.kscience.attributes.*
|
||||||
import space.kscience.kmath.misc.FeatureSet
|
import kotlin.reflect.typeOf
|
||||||
import space.kscience.kmath.misc.Featured
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
public interface IntegrandFeature : Feature<IntegrandFeature> {
|
public interface IntegrandAttribute<T> : Attribute<T>
|
||||||
override fun toString(): String
|
|
||||||
|
public interface Integrand<T> : AttributeContainer {
|
||||||
|
|
||||||
|
public fun modify(block: AttributesBuilder.() -> Unit): Integrand<T>
|
||||||
|
|
||||||
|
public fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): Integrand<T>
|
||||||
|
|
||||||
|
public companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Integrand : Featured<IntegrandFeature> {
|
public operator fun <T> Integrand<*>.get(attribute: Attribute<T>): T? = attributes[attribute]
|
||||||
public val features: FeatureSet<IntegrandFeature>
|
|
||||||
override fun <T : IntegrandFeature> getFeature(type: KClass<out T>): T? = features.getFeature(type)
|
public class IntegrandValue<T>(type: SafeType<T>) : PolymorphicAttribute<T>(type), IntegrandAttribute<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 inline fun <reified T : IntegrandFeature> Integrand.getFeature(): T? = getFeature(T::class)
|
/**
|
||||||
|
* Value of the integrand if it is present or null
|
||||||
|
*/
|
||||||
|
public inline val <reified T : Any> Integrand<T>.valueOrNull: T? get() = attributes[Value]
|
||||||
|
|
||||||
public class IntegrandValue<out T : Any>(public val value: T) : IntegrandFeature {
|
/**
|
||||||
override fun toString(): String = "Value($value)"
|
* Value of the integrand or error
|
||||||
}
|
*/
|
||||||
|
public inline val <reified T : Any> Integrand<T>.value: T get() = valueOrNull ?: error("No value in the integrand")
|
||||||
|
|
||||||
public class IntegrandRelativeAccuracy(public val accuracy: Double) : IntegrandFeature {
|
public object IntegrandRelativeAccuracy : IntegrandAttribute<Double>
|
||||||
override fun toString(): String = "TargetRelativeAccuracy($accuracy)"
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IntegrandAbsoluteAccuracy(public val accuracy: Double) : IntegrandFeature {
|
public object IntegrandAbsoluteAccuracy : IntegrandAttribute<Double>
|
||||||
override fun toString(): String = "TargetAbsoluteAccuracy($accuracy)"
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IntegrandCallsPerformed(public val calls: Int) : IntegrandFeature {
|
public object IntegrandCallsPerformed : IntegrandAttribute<Int>
|
||||||
override fun toString(): String = "Calls($calls)"
|
|
||||||
}
|
|
||||||
|
|
||||||
public val Integrand.calls: Int get() = getFeature<IntegrandCallsPerformed>()?.calls ?: 0
|
public val Integrand<*>.calls: Int get() = attributes[IntegrandCallsPerformed] ?: 0
|
||||||
|
|
||||||
public class IntegrandMaxCalls(public val maxCalls: Int) : IntegrandFeature {
|
public object IntegrandMaxCalls : IntegrandAttribute<Int>
|
||||||
override fun toString(): String = "MaxCalls($maxCalls)"
|
|
||||||
}
|
|
||||||
|
|
||||||
public class IntegrandIterationsRange(public val range: IntRange) : IntegrandFeature {
|
public object IntegrandIterationsRange : IntegrandAttribute<IntRange>
|
||||||
override fun toString(): String = "Iterations(${range.first}..${range.last})"
|
|
||||||
}
|
|
||||||
|
@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.integration
|
package space.kscience.kmath.integration
|
||||||
|
|
||||||
|
import space.kscience.attributes.*
|
||||||
import space.kscience.kmath.linear.Point
|
import space.kscience.kmath.linear.Point
|
||||||
import space.kscience.kmath.misc.FeatureSet
|
|
||||||
|
|
||||||
public class MultivariateIntegrand<T : Any> internal constructor(
|
public class MultivariateIntegrand<T> internal constructor(
|
||||||
override val features: FeatureSet<IntegrandFeature>,
|
override val attributes: Attributes,
|
||||||
public val function: (Point<T>) -> T,
|
public val function: (Point<T>) -> T,
|
||||||
) : Integrand {
|
) : Integrand<T> {
|
||||||
|
|
||||||
public operator fun <F : IntegrandFeature> plus(feature: F): MultivariateIntegrand<T> =
|
override fun modify(block: AttributesBuilder.() -> Unit): MultivariateIntegrand<T> =
|
||||||
MultivariateIntegrand(features.with(feature), function)
|
MultivariateIntegrand(attributes.modify(block), function)
|
||||||
|
|
||||||
|
override fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): MultivariateIntegrand<T> =
|
||||||
|
MultivariateIntegrand(attributes.withAttribute(attribute, value), function)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <T : Any> MultivariateIntegrand(
|
public fun <T : Any> MultivariateIntegrand(
|
||||||
vararg features: IntegrandFeature,
|
attributeBuilder: AttributesBuilder.() -> Unit,
|
||||||
function: (Point<T>) -> T,
|
function: (Point<T>) -> T,
|
||||||
): MultivariateIntegrand<T> = MultivariateIntegrand(FeatureSet.of(*features), function)
|
): MultivariateIntegrand<T> = MultivariateIntegrand(Attributes(attributeBuilder), function)
|
||||||
|
|
||||||
public val <T : Any> MultivariateIntegrand<T>.value: T? get() = getFeature<IntegrandValue<T>>()?.value
|
|
||||||
|
@ -45,16 +45,22 @@ public class SimpsonIntegrator<T : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> {
|
override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> {
|
||||||
val ranges = integrand.getFeature<UnivariateIntegrandRanges>()
|
val ranges = integrand[UnivariateIntegrandRanges]
|
||||||
return if (ranges != null) {
|
return if (ranges != null) {
|
||||||
val res = algebra.sum(ranges.ranges.map { integrateRange(integrand, it.first, it.second) })
|
val res = algebra.sum(ranges.ranges.map { integrateRange(integrand, it.first, it.second) })
|
||||||
integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second })
|
integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second })
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val numPoints = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: 100
|
val numPoints = integrand[IntegrandMaxCalls] ?: 100
|
||||||
require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" }
|
require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" }
|
||||||
val range = integrand.getFeature<IntegrationRange>()?.range ?: 0.0..1.0
|
val range = integrand[IntegrationRange] ?: 0.0..1.0
|
||||||
val res = integrateRange(integrand, range, numPoints)
|
val res = integrateRange(integrand, range, numPoints)
|
||||||
integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + numPoints)
|
integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + numPoints)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,16 +97,22 @@ public object DoubleSimpsonIntegrator : UnivariateIntegrator<Double> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||||
val ranges = integrand.getFeature<UnivariateIntegrandRanges>()
|
val ranges = integrand[UnivariateIntegrandRanges]
|
||||||
return if (ranges != null) {
|
return if (ranges != null) {
|
||||||
val res = ranges.ranges.sumOf { integrateRange(integrand, it.first, it.second) }
|
val res = ranges.ranges.sumOf { integrateRange(integrand, it.first, it.second) }
|
||||||
integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second })
|
integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + ranges.ranges.sumOf { it.second })
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val numPoints = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: 100
|
val numPoints = integrand[IntegrandMaxCalls] ?: 100
|
||||||
require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" }
|
require(numPoints >= 4) { "Simpson integrator requires at least 4 nodes" }
|
||||||
val range = integrand.getFeature<IntegrationRange>()?.range ?: 0.0..1.0
|
val range = integrand[IntegrationRange] ?: 0.0..1.0
|
||||||
val res = integrateRange(integrand, range, numPoints)
|
val res = integrateRange(integrand, range, numPoints)
|
||||||
integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + numPoints)
|
integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + numPoints)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,12 @@ public class SplineIntegrator<T : Comparable<T>>(
|
|||||||
public val bufferFactory: MutableBufferFactory<T>,
|
public val bufferFactory: MutableBufferFactory<T>,
|
||||||
) : UnivariateIntegrator<T> {
|
) : UnivariateIntegrator<T> {
|
||||||
override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> = algebra {
|
override fun process(integrand: UnivariateIntegrand<T>): UnivariateIntegrand<T> = algebra {
|
||||||
val range = integrand.getFeature<IntegrationRange>()?.range ?: 0.0..1.0
|
val range = integrand[IntegrationRange] ?: 0.0..1.0
|
||||||
|
|
||||||
val interpolator: PolynomialInterpolator<T> = SplineInterpolator(algebra, bufferFactory)
|
val interpolator: PolynomialInterpolator<T> = SplineInterpolator(algebra, bufferFactory)
|
||||||
|
|
||||||
val nodes: Buffer<Double> = integrand.getFeature<UnivariateIntegrationNodes>()?.nodes ?: run {
|
val nodes: Buffer<Double> = integrand[UnivariateIntegrationNodes] ?: run {
|
||||||
val numPoints = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: 100
|
val numPoints = integrand[IntegrandMaxCalls] ?: 100
|
||||||
val step = (range.endInclusive - range.start) / (numPoints - 1)
|
val step = (range.endInclusive - range.start) / (numPoints - 1)
|
||||||
Float64Buffer(numPoints) { i -> range.start + i * step }
|
Float64Buffer(numPoints) { i -> range.start + i * step }
|
||||||
}
|
}
|
||||||
@ -71,7 +71,10 @@ public class SplineIntegrator<T : Comparable<T>>(
|
|||||||
values
|
values
|
||||||
)
|
)
|
||||||
val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive))
|
val res = polynomials.integrate(algebra, number(range.start)..number(range.endInclusive))
|
||||||
integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size)
|
integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + nodes.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,11 +87,11 @@ public class SplineIntegrator<T : Comparable<T>>(
|
|||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
|
public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
|
||||||
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
override fun process(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
|
||||||
val range = integrand.getFeature<IntegrationRange>()?.range ?: 0.0..1.0
|
val range = integrand[IntegrationRange] ?: 0.0..1.0
|
||||||
val interpolator: PolynomialInterpolator<Double> = SplineInterpolator(Float64Field, ::Float64Buffer)
|
val interpolator: PolynomialInterpolator<Double> = SplineInterpolator(Float64Field, ::Float64Buffer)
|
||||||
|
|
||||||
val nodes: Buffer<Double> = integrand.getFeature<UnivariateIntegrationNodes>()?.nodes ?: run {
|
val nodes: Buffer<Double> = integrand[UnivariateIntegrationNodes] ?: run {
|
||||||
val numPoints = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: 100
|
val numPoints = integrand[IntegrandMaxCalls] ?: 100
|
||||||
val step = (range.endInclusive - range.start) / (numPoints - 1)
|
val step = (range.endInclusive - range.start) / (numPoints - 1)
|
||||||
Float64Buffer(numPoints) { i -> range.start + i * step }
|
Float64Buffer(numPoints) { i -> range.start + i * step }
|
||||||
}
|
}
|
||||||
@ -96,7 +99,10 @@ public object DoubleSplineIntegrator : UnivariateIntegrator<Double> {
|
|||||||
val values = nodes.mapToBuffer(::Float64Buffer) { integrand.function(it) }
|
val values = nodes.mapToBuffer(::Float64Buffer) { integrand.function(it) }
|
||||||
val polynomials = interpolator.interpolatePolynomials(nodes, values)
|
val polynomials = interpolator.interpolatePolynomials(nodes, values)
|
||||||
val res = polynomials.integrate(Float64Field, range)
|
val res = polynomials.integrate(Float64Field, range)
|
||||||
return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + nodes.size)
|
return integrand.modify {
|
||||||
|
value(res)
|
||||||
|
IntegrandCallsPerformed(integrand.calls + nodes.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,36 +5,38 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.integration
|
package space.kscience.kmath.integration
|
||||||
|
|
||||||
|
import space.kscience.attributes.*
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.misc.FeatureSet
|
|
||||||
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> internal constructor(
|
||||||
override val features: FeatureSet<IntegrandFeature>,
|
override val attributes: Attributes,
|
||||||
public val function: (Double) -> T,
|
public val function: (Double) -> T,
|
||||||
) : Integrand {
|
) : Integrand<T> {
|
||||||
public operator fun <F : IntegrandFeature> plus(feature: F): UnivariateIntegrand<T> =
|
|
||||||
UnivariateIntegrand(features.with(feature), function)
|
override fun <A : Any> withAttribute(attribute: Attribute<A>, value: A): UnivariateIntegrand<T> =
|
||||||
|
UnivariateIntegrand(attributes.withAttribute(attribute, value), function)
|
||||||
|
|
||||||
|
override fun modify(block: AttributesBuilder.() -> Unit): UnivariateIntegrand<T> =
|
||||||
|
UnivariateIntegrand(attributes.modify(block), function)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
public fun <T : Any> UnivariateIntegrand(
|
public fun <T : Any> UnivariateIntegrand(
|
||||||
|
attributeBuilder: AttributesBuilder.() -> Unit,
|
||||||
function: (Double) -> T,
|
function: (Double) -> T,
|
||||||
vararg features: IntegrandFeature,
|
): UnivariateIntegrand<T> = UnivariateIntegrand(Attributes(attributeBuilder), function)
|
||||||
): UnivariateIntegrand<T> = UnivariateIntegrand(FeatureSet.of(*features), function)
|
|
||||||
|
|
||||||
public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
|
public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
|
||||||
|
|
||||||
public class IntegrationRange(public val range: ClosedRange<Double>) : IntegrandFeature {
|
public object IntegrationRange : IntegrandAttribute<ClosedRange<Double>>
|
||||||
override fun toString(): String = "Range(${range.start}..${range.endInclusive})"
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of univariate integration ranges. First components correspond to the ranges themselves, second components to
|
* Set of univariate integration ranges. First components correspond to the ranges themselves, second components to
|
||||||
* number of integration nodes per range.
|
* the number of integration nodes per range.
|
||||||
*/
|
*/
|
||||||
public class UnivariateIntegrandRanges(public val ranges: List<Pair<ClosedRange<Double>, Int>>) : IntegrandFeature {
|
public class UnivariateIntegrandRanges(public val ranges: List<Pair<ClosedRange<Double>, Int>>) {
|
||||||
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 {
|
override fun toString(): String {
|
||||||
@ -43,45 +45,25 @@ public class UnivariateIntegrandRanges(public val ranges: List<Pair<ClosedRange<
|
|||||||
}
|
}
|
||||||
return "UnivariateRanges($rangesString)"
|
return "UnivariateRanges($rangesString)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public companion object : IntegrandAttribute<UnivariateIntegrandRanges>
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UnivariateIntegrationNodes(public val nodes: Buffer<Double>) : IntegrandFeature {
|
public object UnivariateIntegrationNodes : IntegrandAttribute<Buffer<Double>>
|
||||||
public constructor(vararg nodes: Double) : this(Float64Buffer(nodes))
|
|
||||||
|
|
||||||
override fun toString(): String = "UnivariateNodes($nodes)"
|
public fun AttributesBuilder.integrationNodes(vararg nodes: Double) {
|
||||||
|
UnivariateIntegrationNodes(Float64Buffer(nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value of the integrand if it is present or null
|
|
||||||
*/
|
|
||||||
public val <T : Any> UnivariateIntegrand<T>.valueOrNull: T? get() = getFeature<IntegrandValue<T>>()?.value
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value of the integrand or error
|
|
||||||
*/
|
|
||||||
public val <T : Any> UnivariateIntegrand<T>.value: T get() = valueOrNull ?: error("No value in the integrand")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A shortcut method to integrate a [function] with additional [features]. Range must be provided in features.
|
* A shortcut method to integrate a [function] with additional [features]. Range must be provided in features.
|
||||||
* 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,
|
attributesBuilder: AttributesBuilder.() -> Unit,
|
||||||
function: (Double) -> T,
|
function: (Double) -> T,
|
||||||
): UnivariateIntegrand<T> = process(UnivariateIntegrand(function, *features))
|
): UnivariateIntegrand<T> = process(UnivariateIntegrand(attributesBuilder, function))
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut method to integrate a [function] in [range] with additional [features].
|
|
||||||
* The [function] is placed in the end position to allow passing a lambda.
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public fun <T : Any> UnivariateIntegrator<T>.integrate(
|
|
||||||
range: ClosedRange<Double>,
|
|
||||||
vararg features: IntegrandFeature,
|
|
||||||
function: (Double) -> T,
|
|
||||||
): UnivariateIntegrand<T> = process(UnivariateIntegrand(function, IntegrationRange(range), *features))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A shortcut method to integrate a [function] in [range] with additional features.
|
* A shortcut method to integrate a [function] in [range] with additional features.
|
||||||
@ -90,13 +72,12 @@ public fun <T : Any> UnivariateIntegrator<T>.integrate(
|
|||||||
@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 = {},
|
attributeBuilder: AttributesBuilder.() -> Unit = {},
|
||||||
function: (Double) -> T,
|
function: (Double) -> T,
|
||||||
): UnivariateIntegrand<T> {
|
): UnivariateIntegrand<T> {
|
||||||
//TODO use dedicated feature builder class instead or add extensions to MutableList<IntegrandFeature>
|
val attributes = Attributes {
|
||||||
val features = buildList {
|
IntegrationRange(range)
|
||||||
featureBuilder()
|
attributeBuilder()
|
||||||
add(IntegrationRange(range))
|
|
||||||
}
|
}
|
||||||
return process(UnivariateIntegrand(function, *features.toTypedArray()))
|
return process(UnivariateIntegrand(attributes, function))
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,10 @@ import kotlin.test.assertEquals
|
|||||||
class SimpsonIntegralTest {
|
class SimpsonIntegralTest {
|
||||||
@Test
|
@Test
|
||||||
fun gaussSin() {
|
fun gaussSin() {
|
||||||
val res = Float64Field.simpsonIntegrator.integrate(0.0..2 * PI, IntegrandMaxCalls(5)) { x ->
|
val res = Float64Field.simpsonIntegrator.integrate(
|
||||||
|
0.0..2 * PI,
|
||||||
|
{ IntegrandMaxCalls(5) }
|
||||||
|
) { x ->
|
||||||
sin(x)
|
sin(x)
|
||||||
}
|
}
|
||||||
assertEquals(0.0, res.value, 1e-2)
|
assertEquals(0.0, res.value, 1e-2)
|
||||||
@ -24,7 +27,10 @@ class SimpsonIntegralTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun gaussUniform() {
|
fun gaussUniform() {
|
||||||
val res = Float64Field.simpsonIntegrator.integrate(35.0..100.0, IntegrandMaxCalls(20)) { x ->
|
val res = Float64Field.simpsonIntegrator.integrate(
|
||||||
|
35.0..100.0,
|
||||||
|
{ IntegrandMaxCalls(20) }
|
||||||
|
) { x ->
|
||||||
if (x in 30.0..50.0) {
|
if (x in 30.0..50.0) {
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,7 +27,7 @@ fun grid(
|
|||||||
return xs.flatMap { x -> ys.map { y -> x to y } }
|
return xs.flatMap { x -> ys.map { y -> x to y } }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertVectorEquals(expected: DoubleVector2D, actual: DoubleVector2D, absoluteTolerance: Double = 1e-6) {
|
fun assertVectorEquals(expected: DoubleVector2D, actual: DoubleVector2D, absoluteTolerance: Double = 1e-3) {
|
||||||
assertEquals(expected.x, actual.x, absoluteTolerance)
|
assertEquals(expected.x, actual.x, absoluteTolerance)
|
||||||
assertEquals(expected.y, actual.y, absoluteTolerance)
|
assertEquals(expected.y, actual.y, absoluteTolerance)
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class OptimizationPrior<T>(type: SafeType<T>):
|
|||||||
PolymorphicAttribute<DifferentiableExpression<T>>(safeTypeOf()),
|
PolymorphicAttribute<DifferentiableExpression<T>>(safeTypeOf()),
|
||||||
Attribute<DifferentiableExpression<T>>
|
Attribute<DifferentiableExpression<T>>
|
||||||
|
|
||||||
public val <T> FunctionOptimization.Companion.Optimization get() =
|
//public val <T> FunctionOptimization.Companion.Optimization get() =
|
||||||
|
|
||||||
|
|
||||||
public fun <T> FunctionOptimization<T>.withFeatures(
|
public fun <T> FunctionOptimization<T>.withFeatures(
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
import space.kscience.kmath.PerformancePitfall
|
import space.kscience.kmath.PerformancePitfall
|
||||||
import space.kscience.kmath.linear.transpose
|
import space.kscience.kmath.linear.transposed
|
||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
@ -139,7 +139,7 @@ public fun DoubleTensorAlgebra.levenbergMarquardt(inputData: LMInput): LMResultI
|
|||||||
if (inputData.nargin < 5) {
|
if (inputData.nargin < 5) {
|
||||||
weight = fromArray(
|
weight = fromArray(
|
||||||
ShapeND(intArrayOf(1, 1)),
|
ShapeND(intArrayOf(1, 1)),
|
||||||
doubleArrayOf((inputData.realValues.transpose().dot(inputData.realValues)).as1D()[0])
|
doubleArrayOf((inputData.realValues.transposed dot inputData.realValues).as1D()[0])
|
||||||
).as2D()
|
).as2D()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,12 +266,12 @@ public fun DoubleTensorAlgebra.levenbergMarquardt(inputData: LMInput): LMResultI
|
|||||||
settings.funcCalls += 1
|
settings.funcCalls += 1
|
||||||
|
|
||||||
// val tmp = deltaY.times(weight)
|
// val tmp = deltaY.times(weight)
|
||||||
var X2Try = deltaY.as2D().transpose().dot(deltaY.times(weight)) // Chi-squared error criteria
|
var X2Try = deltaY.as2D().transposed dot deltaY.times(weight) // Chi-squared error criteria
|
||||||
|
|
||||||
val alpha = 1.0
|
val alpha = 1.0
|
||||||
if (updateType == 2) { // Quadratic
|
if (updateType == 2) { // Quadratic
|
||||||
// One step of quadratic line update in the h direction for minimum X2
|
// One step of quadratic line update in the h direction for minimum X2
|
||||||
val alphaTensor = (jtWdy.transpose() dot h) / ((X2Try - x2) / 2.0 + 2 * (jtWdy.transpose() dot h))
|
val alphaTensor = (jtWdy.transposed dot h) / ((X2Try - x2) / 2.0 + 2 * (jtWdy.transposed dot h))
|
||||||
h = h dot alphaTensor
|
h = h dot alphaTensor
|
||||||
pTry = (p + h).as2D() // update only [idx] elements
|
pTry = (p + h).as2D() // update only [idx] elements
|
||||||
pTry = smallestElementComparison(
|
pTry = smallestElementComparison(
|
||||||
@ -289,7 +289,7 @@ public fun DoubleTensorAlgebra.levenbergMarquardt(inputData: LMInput): LMResultI
|
|||||||
) // residual error using p_try
|
) // residual error using p_try
|
||||||
settings.funcCalls += 1
|
settings.funcCalls += 1
|
||||||
|
|
||||||
X2Try = deltaY.as2D().transpose() dot deltaY * weight // Chi-squared error criteria
|
X2Try = deltaY.as2D().transposed dot deltaY * weight // Chi-squared error criteria
|
||||||
}
|
}
|
||||||
|
|
||||||
val rho = when (updateType) { // Nielsen
|
val rho = when (updateType) { // Nielsen
|
||||||
|
Loading…
Reference in New Issue
Block a user