From 5546f481c3ae078786714e86c41ea9c19e9a40a0 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Sat, 2 Nov 2019 12:50:09 +0100 Subject: [PATCH] Add binding for DoubleArray --- .../src/main/kotlin/DataBinding.kt | 17 +++++++++++++++++ .../src/main/kotlin/GradientDescent.kt | 9 +++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/orx-gradient-descent/src/main/kotlin/DataBinding.kt b/orx-gradient-descent/src/main/kotlin/DataBinding.kt index 24fdb7b5..9397dbe1 100644 --- a/orx-gradient-descent/src/main/kotlin/DataBinding.kt +++ b/orx-gradient-descent/src/main/kotlin/DataBinding.kt @@ -11,6 +11,14 @@ fun modelToArray(model: T): DoubleArray { val doubles = mutableListOf() model::class.java.declaredFields.forEach { when { + it.type == DoubleArray::class.java -> { + it.isAccessible = true + val da = it.get(model) as DoubleArray + for (d in da) { + doubles.add(d) + } + } + it.type == Double::class.java -> { it.isAccessible = true doubles.add(it.getDouble(model)) @@ -48,6 +56,15 @@ fun arrayToModel(data: DoubleArray, model: T) { var index = 0 model::class.java.declaredFields.forEach { when { + it.type == DoubleArray::class.java -> { + it.isAccessible = true + //it.setDouble(model, data[index]) + val da = it.get(model) as DoubleArray + for (i in 0 until da.size) { + da[i] = data[index] + index++ + } + } it.type == Double::class.java -> { it.isAccessible = true it.setDouble(model, data[index]) diff --git a/orx-gradient-descent/src/main/kotlin/GradientDescent.kt b/orx-gradient-descent/src/main/kotlin/GradientDescent.kt index 2a447f2b..53c3d8c3 100644 --- a/orx-gradient-descent/src/main/kotlin/GradientDescent.kt +++ b/orx-gradient-descent/src/main/kotlin/GradientDescent.kt @@ -35,6 +35,7 @@ fun max(a: Double, b: Double, c: Double, d: Double, e: Double, f: Double, g: Dou return max(max(max(max(max(max(max(a, b), c), d), e), f), g), h) } + fun gradient(x: DoubleArray, objective: (parameters: DoubleArray) -> Double): DoubleArray { var k = 0 val tempX = x.copyOf() @@ -83,6 +84,7 @@ private fun add(x: Array, y: Array) = Array(x.size) { private fun sub(x: Array, y: Array) = Array(x.size) { sub(x[it], y[it]) } private fun mul(x: Array, y: Double) = Array(x.size) { mul(x[it], y) } private fun mul(x: DoubleArray, y: Double) = DoubleArray(x.size) { x[it] * y } +private fun mul(x: DoubleArray, y: DoubleArray) = DoubleArray(x.size) { x[it] * y[it] } private fun div(x: Array, y: Double) = Array(x.size) { div(x[it], y) } private fun div(x: DoubleArray, y: Double) = DoubleArray(x.size) { x[it] / y } private fun norm2(x: DoubleArray): Double { @@ -96,7 +98,9 @@ fun dot(x: Array, y: DoubleArray): DoubleArray = DoubleArray(x.size class MinimizationResult(val solution: DoubleArray, val value: Double, val gradient: DoubleArray, val inverseHessian: Array, val iterations: Int) -fun minimize(_x0: DoubleArray, endOnLineSearch: Boolean = false, tol: Double = 1e-8, maxIterations: Int = 1000, f: (DoubleArray) -> Double): MinimizationResult { +fun minimize(_x0: DoubleArray, + weights: DoubleArray = DoubleArray(_x0.size) { 1.0 }, + endOnLineSearch: Boolean = false, tol: Double = 1e-8, maxIterations: Int = 1000, f: (DoubleArray) -> Double): MinimizationResult { val grad = { a: DoubleArray -> gradient(a, f) } var x0 = _x0.copyOf() var g0 = grad(x0) @@ -175,7 +179,8 @@ fun minimize(_x0: DoubleArray, endOnLineSearch: Boolean = false, tol: Double = 1 fun minimizeModel(model: T, endOnLineSearch: Boolean = false, tol: Double = 1e-8, maxIterations: Int = 1000, function: (T) -> Double) { val doubles = modelToArray(model) - val solution = minimize(doubles, endOnLineSearch, tol, maxIterations) { + val weights = DoubleArray(doubles.size) { 1.0 } + val solution = minimize(doubles, weights, endOnLineSearch, tol, maxIterations) { arrayToModel(it, model) function(model) }