diff --git a/README.md b/README.md index 2df9d3246..c4e3e5374 100644 --- a/README.md +++ b/README.md @@ -211,7 +211,15 @@ Release artifacts are accessible from bintray with following configuration (see ```kotlin repositories { + jcenter() + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/kscience") + maven("https://jitpack.io") + mavenCentral() } dependencies { @@ -228,7 +236,15 @@ Development builds are uploaded to the separate repository: ```kotlin repositories { + jcenter() + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/dev") + maven("https://jitpack.io") + mavenCentral() } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 095697bc4..3514c91e6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import ru.mipt.npm.gradle.KSciencePublishPlugin + plugins { id("ru.mipt.npm.project") } @@ -17,6 +19,7 @@ allprojects { maven("https://dl.bintray.com/mipt-npm/dev") maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://jitpack.io") + maven("http://logicrunch.research.it.uu.se/maven/") mavenCentral() } @@ -25,7 +28,7 @@ allprojects { } subprojects { - if (name.startsWith("kmath")) apply() + if (name.startsWith("kmath")) apply() } readme { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 99828c621..d42627ff0 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -10,6 +10,20 @@ plugins { allOpen.annotation("org.openjdk.jmh.annotations.State") sourceSets.register("benchmarks") +repositories { + jcenter() + maven("https://clojars.org/repo") + maven("https://dl.bintray.com/egor-bogomolov/astminer/") + maven("https://dl.bintray.com/hotkeytlt/maven") + maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") + maven("https://dl.bintray.com/mipt-npm/dev") + maven("https://dl.bintray.com/mipt-npm/kscience") + maven("https://jitpack.io") + maven("http://logicrunch.research.it.uu.se/maven/") + mavenCentral() +} + dependencies { implementation(project(":kmath-ast")) implementation(project(":kmath-kotlingrad")) diff --git a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt index 5acd97e3d..b3c827503 100644 --- a/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt +++ b/examples/src/main/kotlin/kscience/kmath/ast/KotlingradSupport.kt @@ -1,9 +1,9 @@ package kscience.kmath.ast import kscience.kmath.asm.compile +import kscience.kmath.expressions.derivative import kscience.kmath.expressions.invoke import kscience.kmath.expressions.symbol -import kscience.kmath.kotlingrad.derivative import kscience.kmath.kotlingrad.differentiable import kscience.kmath.operations.RealField diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt index 13f9af7bb..d6f79529a 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/CMOptimizationProblem.kt @@ -19,9 +19,8 @@ import kotlin.reflect.KClass public operator fun PointValuePair.component1(): DoubleArray = point public operator fun PointValuePair.component2(): Double = value -public class CMOptimizationProblem( - override val symbols: List, -) : OptimizationProblem, SymbolIndexer, OptimizationFeature { +public class CMOptimizationProblem(override val symbols: List, ) : + OptimizationProblem, SymbolIndexer, OptimizationFeature { private val optimizationData: HashMap, OptimizationData> = HashMap() private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null public var convergenceChecker: ConvergenceChecker = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE, @@ -49,7 +48,7 @@ public class CMOptimizationProblem( addOptimizationData(objectiveFunction) } - public override fun diffExpression(expression: DifferentiableExpression): Unit { + public override fun diffExpression(expression: DifferentiableExpression>) { expression(expression) val gradientFunction = ObjectiveFunctionGradient { val args = it.toMap() diff --git a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt index 42475db6c..b8e8bfd4b 100644 --- a/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt +++ b/kmath-commons/src/main/kotlin/kscience/kmath/commons/optimization/cmFit.kt @@ -12,7 +12,6 @@ import kscience.kmath.structures.asBuffer import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import org.apache.commons.math3.optim.nonlinear.scalar.GoalType - /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ @@ -21,7 +20,7 @@ public fun Fitting.chiSquared( y: Buffer, yErr: Buffer, model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, -): DifferentiableExpression = chiSquared(DerivativeStructureField, x, y, yErr, model) +): DifferentiableExpression> = chiSquared(DerivativeStructureField, x, y, yErr, model) /** * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation @@ -31,7 +30,7 @@ public fun Fitting.chiSquared( y: Iterable, yErr: Iterable, model: DerivativeStructureField.(x: DerivativeStructure) -> DerivativeStructure, -): DifferentiableExpression = chiSquared( +): DifferentiableExpression> = chiSquared( DerivativeStructureField, x.toList().asBuffer(), y.toList().asBuffer(), @@ -39,7 +38,6 @@ public fun Fitting.chiSquared( model ) - /** * Optimize expression without derivatives */ @@ -48,16 +46,15 @@ public fun Expression.optimize( configuration: CMOptimizationProblem.() -> Unit, ): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) - /** * Optimize differentiable expression */ -public fun DifferentiableExpression.optimize( +public fun DifferentiableExpression>.optimize( vararg symbols: Symbol, configuration: CMOptimizationProblem.() -> Unit, ): OptimizationResult = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) -public fun DifferentiableExpression.minimize( +public fun DifferentiableExpression>.minimize( vararg startPoint: Pair, configuration: CMOptimizationProblem.() -> Unit = {}, ): OptimizationResult { diff --git a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt index fa1978f95..3290c8f32 100644 --- a/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt +++ b/kmath-commons/src/test/kotlin/kscience/kmath/commons/optimization/OptimizeTest.kt @@ -47,14 +47,17 @@ internal class OptimizeTest { val sigma = 1.0 val generator = Distribution.normal(0.0, sigma) val chain = generator.sample(RandomGenerator.default(112667)) - val x = (1..100).map { it.toDouble() } - val y = x.map { it -> + val x = (1..100).map(Int::toDouble) + + val y = x.map { it.pow(2) + it + 1 + chain.nextDouble() } - val yErr = x.map { sigma } - val chi2 = Fitting.chiSquared(x, y, yErr) { x -> + + val yErr = List(x.size) { sigma } + + val chi2 = Fitting.chiSquared(x, y, yErr) { x1 -> val cWithDefault = bindOrNull(c) ?: one - bind(a) * x.pow(2) + bind(b) * x + cWithDefault + bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault } val result = chi2.minimize(a to 1.5, b to 0.9, c to 1.0) diff --git a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt index a15df1ac8..abce9c4ec 100644 --- a/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt +++ b/kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/DifferentiableExpression.kt @@ -6,7 +6,7 @@ package kscience.kmath.expressions * @param T the type this expression takes as argument and returns. * @param R the type of expression this expression can be differentiated to. */ -public interface DifferentiableExpression> : Expression { +public interface DifferentiableExpression> : Expression { /** * Differentiates this expression by ordered collection of [symbols]. * @@ -43,6 +43,6 @@ public abstract class FirstDerivativeExpression> : Differen /** * A factory that converts an expression in autodiff variables to a [DifferentiableExpression] */ -public fun interface AutoDiffProcessor, R : Expression> { +public fun interface AutoDiffProcessor, out R : Expression> { public fun process(function: A.() -> I): DifferentiableExpression } diff --git a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt index 682b0cf2e..77902211b 100644 --- a/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt +++ b/kmath-kotlingrad/src/test/kotlin/kscience/kmath/kotlingrad/AdaptingTests.kt @@ -13,13 +13,11 @@ import kotlin.test.assertTrue import kotlin.test.fail internal class AdaptingTests { - private val proto: DReal = DoublePrecision.prototype - @Test fun symbol() { val c1 = MstAlgebra.symbol("x") - assertTrue(c1.toSVar(proto).name == "x") - val c2 = "kitten".parseMath().toSFun(proto) + assertTrue(c1.toSVar>().name == "x") + val c2 = "kitten".parseMath().toSFun>() if (c2 is SVar) assertTrue(c2.name == "kitten") else fail() } @@ -27,15 +25,15 @@ internal class AdaptingTests { fun number() { val c1 = MstAlgebra.number(12354324) assertTrue(c1.toSConst().doubleValue == 12354324.0) - val c2 = "0.234".parseMath().toSFun(proto) + val c2 = "0.234".parseMath().toSFun>() if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail() - val c3 = "1e-3".parseMath().toSFun(proto) + val c3 = "1e-3".parseMath().toSFun>() if (c3 is SConst) assertEquals(0.001, c3.value) else fail() } @Test fun simpleFunctionShape() { - val linear = "2*x+16".parseMath().toSFun(proto) + val linear = "2*x+16".parseMath().toSFun>() if (linear !is Sum) fail() if (linear.left !is Prod) fail() if (linear.right !is SConst) fail() @@ -43,8 +41,8 @@ internal class AdaptingTests { @Test fun simpleFunctionDerivative() { - val x = MstAlgebra.symbol("x").toSVar(proto) - val quadratic = "x^2-4*x-44".parseMath().toSFun(proto) + val x = MstAlgebra.symbol("x").toSVar>() + val quadratic = "x^2-4*x-44".parseMath().toSFun>() val actualDerivative = MstExpression(RealField, quadratic.d(x).toMst()).compile() val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile() assertEquals(actualDerivative("x" to 123.0), expectedDerivative("x" to 123.0)) @@ -52,8 +50,8 @@ internal class AdaptingTests { @Test fun moreComplexDerivative() { - val x = MstAlgebra.symbol("x").toSVar(proto) - val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun(proto) + val x = MstAlgebra.symbol("x").toSVar>() + val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun>() val actualDerivative = MstExpression(RealField, composition.d(x).toMst()).compile() val expectedDerivative = MstExpression( diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt index 01fdf4c5e..9d4655df2 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/Fitting.kt @@ -12,16 +12,18 @@ public object Fitting { * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation */ public fun chiSquared( - autoDiff: AutoDiffProcessor, + autoDiff: AutoDiffProcessor>, x: Buffer, y: Buffer, yErr: Buffer, model: A.(I) -> I, - ): DifferentiableExpression where A : ExtendedField, A : ExpressionAlgebra { + ): DifferentiableExpression> where A : ExtendedField, A : ExpressionAlgebra { require(x.size == y.size) { "X and y buffers should be of the same size" } require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return autoDiff.process { var sum = zero + x.indices.forEach { val xValue = const(x[it]) val yValue = const(y[it]) @@ -29,6 +31,7 @@ public object Fitting { val modelValue = model(xValue) sum += ((yValue - modelValue) / yErrValue).pow(2) } + sum } } @@ -45,6 +48,7 @@ public object Fitting { ): Expression { require(x.size == y.size) { "X and y buffers should be of the same size" } require(y.size == yErr.size) { "Y and yErr buffer should of the same size" } + return Expression { arguments -> x.indices.sumByDouble { val xValue = x[it] @@ -56,4 +60,4 @@ public object Fitting { } } } -} \ No newline at end of file +} diff --git a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt index ea522bff9..0f3cd9dd9 100644 --- a/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt +++ b/kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/OptimizationProblem.kt @@ -27,17 +27,17 @@ public interface OptimizationProblem { /** * Define the initial guess for the optimization problem */ - public fun initialGuess(map: Map): Unit + public fun initialGuess(map: Map) /** * Set an objective function expression */ - public fun expression(expression: Expression): Unit + public fun expression(expression: Expression) /** * Set a differentiable expression as objective function as function and gradient provider */ - public fun diffExpression(expression: DifferentiableExpression): Unit + public fun diffExpression(expression: DifferentiableExpression>) /** * Update the problem from previous optimization run @@ -50,9 +50,8 @@ public interface OptimizationProblem { public fun optimize(): OptimizationResult } -public interface OptimizationProblemFactory> { +public fun interface OptimizationProblemFactory> { public fun build(symbols: List): P - } public operator fun > OptimizationProblemFactory.invoke( @@ -60,7 +59,6 @@ public operator fun > OptimizationProblemFac block: P.() -> Unit, ): P = build(symbols).apply(block) - /** * Optimize expression without derivatives using specific [OptimizationProblemFactory] */ @@ -78,7 +76,7 @@ public fun > Expression.optimizeWith( /** * Optimize differentiable expression using specific [OptimizationProblemFactory] */ -public fun > DifferentiableExpression.optimizeWith( +public fun > DifferentiableExpression>.optimizeWith( factory: OptimizationProblemFactory, vararg symbols: Symbol, configuration: F.() -> Unit, @@ -88,4 +86,3 @@ public fun > DifferentiableExpression.op problem.diffExpression(this) return problem.optimize() } - diff --git a/settings.gradle.kts b/settings.gradle.kts index e825ddbdf..97dfe1b96 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,8 +1,7 @@ pluginManagement { repositories { - mavenLocal() - jcenter() gradlePluginPortal() + jcenter() maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev")