A minor change to XYfit arguments

This commit is contained in:
Alexander Nozik 2023-01-24 11:36:53 +03:00
parent 3f4fe9e43b
commit 2e4be2aa3a

View File

@ -30,7 +30,7 @@ public interface PointToCurveDistance : OptimizationFeature {
return object : DifferentiableExpression<Double> { return object : DifferentiableExpression<Double> {
override fun derivativeOrNull( override fun derivativeOrNull(
symbols: List<Symbol> symbols: List<Symbol>,
): Expression<Double>? = problem.model.derivativeOrNull(symbols)?.let { derivExpression -> ): Expression<Double>? = problem.model.derivativeOrNull(symbols)?.let { derivExpression ->
Expression { arguments -> Expression { arguments ->
derivExpression.invoke(arguments + (Symbol.x to x)) derivExpression.invoke(arguments + (Symbol.x to x))
@ -93,24 +93,15 @@ public fun XYFit.withFeature(vararg features: OptimizationFeature): XYFit {
return XYFit(data, model, this.features.with(*features), pointToCurveDistance, pointWeight) return XYFit(data, model, this.features.with(*features), pointToCurveDistance, pointWeight)
} }
/** public suspend fun XYColumnarData<Double, Double, Double>.fitWith(
* Fit given dta with
*/
public suspend fun <I : Any, A> XYColumnarData<Double, Double, Double>.fitWith(
optimizer: Optimizer<Double, XYFit>, optimizer: Optimizer<Double, XYFit>,
processor: AutoDiffProcessor<Double, I, A>, modelExpression: DifferentiableExpression<Double>,
startingPoint: Map<Symbol, Double>, startingPoint: Map<Symbol, Double>,
vararg features: OptimizationFeature = emptyArray(), vararg features: OptimizationFeature = emptyArray(),
xSymbol: Symbol = Symbol.x, xSymbol: Symbol = Symbol.x,
pointToCurveDistance: PointToCurveDistance = PointToCurveDistance.byY, pointToCurveDistance: PointToCurveDistance = PointToCurveDistance.byY,
pointWeight: PointWeight = PointWeight.byYSigma, pointWeight: PointWeight = PointWeight.byYSigma,
model: A.(I) -> I ): XYFit {
): XYFit where A : ExtendedField<I>, A : ExpressionAlgebra<Double, I> {
val modelExpression = processor.differentiate {
val x = bindSymbol(xSymbol)
model(x)
}
var actualFeatures = FeatureSet.of(*features, OptimizationStartPoint(startingPoint)) var actualFeatures = FeatureSet.of(*features, OptimizationStartPoint(startingPoint))
if (actualFeatures.getFeature<OptimizationLog>() == null) { if (actualFeatures.getFeature<OptimizationLog>() == null) {
@ -127,20 +118,50 @@ public suspend fun <I : Any, A> XYColumnarData<Double, Double, Double>.fitWith(
return optimizer.optimize(problem) return optimizer.optimize(problem)
} }
/**
* Fit given data with a model provided as an expression
*/
public suspend fun <I : Any, A> XYColumnarData<Double, Double, Double>.fitWith(
optimizer: Optimizer<Double, XYFit>,
processor: AutoDiffProcessor<Double, I, A>,
startingPoint: Map<Symbol, Double>,
vararg features: OptimizationFeature = emptyArray(),
xSymbol: Symbol = Symbol.x,
pointToCurveDistance: PointToCurveDistance = PointToCurveDistance.byY,
pointWeight: PointWeight = PointWeight.byYSigma,
model: A.(I) -> I,
): XYFit where A : ExtendedField<I>, A : ExpressionAlgebra<Double, I> {
val modelExpression: DifferentiableExpression<Double> = processor.differentiate {
val x = bindSymbol(xSymbol)
model(x)
}
return fitWith(
optimizer = optimizer,
modelExpression = modelExpression,
startingPoint = startingPoint,
features = features,
xSymbol = xSymbol,
pointToCurveDistance = pointToCurveDistance,
pointWeight = pointWeight
)
}
/** /**
* Compute chi squared value for completed fit. Return null for incomplete fit * Compute chi squared value for completed fit. Return null for incomplete fit
*/ */
public val XYFit.chiSquaredOrNull: Double? get() { public val XYFit.chiSquaredOrNull: Double?
val result = resultPointOrNull ?: return null get() {
val result = resultPointOrNull ?: return null
return data.indices.sumOf { index-> return data.indices.sumOf { index ->
val x = data.x[index] val x = data.x[index]
val y = data.y[index] val y = data.y[index]
val yErr = data[Symbol.yError]?.get(index) ?: 1.0 val yErr = data[Symbol.yError]?.get(index) ?: 1.0
val mu = model.invoke(result + (xSymbol to x) ) val mu = model.invoke(result + (xSymbol to x))
((y - mu)/yErr).pow(2) ((y - mu) / yErr).pow(2)
}
} }
}