kmath icon indicating copy to clipboard operation
kmath copied to clipboard

Non type-safe units

Open CommanderTvis opened this issue 4 years ago • 11 comments

(unit = "m", value = 42.0) / (unit = "s", value = 2.0) = (unit = ("/", "m", "s"), value = 21.0)

Values with a unit can be implemented as pair of MST of the special context and unit.

Possible benefits: valid unit shape, concise implementation. Possible problem: lack of simplification of the shape.

CommanderTvis avatar Feb 27 '21 06:02 CommanderTvis

cc @altavir @Shimuuar @pusolito @green-nick @pedroteixeira from #75

CommanderTvis avatar Feb 27 '21 16:02 CommanderTvis

Prototype: https://github.com/mipt-npm/kmath/blob/commandertvis/units-poc/kmath-units/src/commonMain/kotlin/space/kscience/kmath/units/units.kt

CommanderTvis avatar Feb 27 '21 16:02 CommanderTvis

MST-based units require additional considerations. On one hand, they are not compile-time type-safe, so they do not make sense in this regard. On the other hand, the context used to generate those units could provide runtime type unit check. Also with a staged compilation like one available in jupyter, it could be beneficial.

altavir avatar Feb 27 '21 17:02 altavir

I think the main problem is that N*m ≠ m*N etc.

CommanderTvis avatar Feb 27 '21 17:02 CommanderTvis

MST does not state that binary operation should be commutative. On the contrary, I would not expect that.

altavir avatar Feb 27 '21 18:02 altavir

I mean units are not simplified to a certain comparable form

CommanderTvis avatar Feb 27 '21 18:02 CommanderTvis

However, it is not such hard to implement such an algorithm - it is much easier than simplify a plain expression.

CommanderTvis avatar Feb 27 '21 18:02 CommanderTvis

Did the Measured lib prove useful? This was discussed as a possible path in #75.

pusolito avatar Feb 28 '21 00:02 pusolito

This issue is not about user level api. It is about generalization of symbolic processing of units. Measured is a nice way to use units and we do not want to dublicate it.

altavir avatar Feb 28 '21 06:02 altavir

I've reworked the prototype without MST - units are stored as a product of base units.

import space.kscience.kmath.operations.RealField
import space.kscience.kmath.units.*

public fun main() {
    var res = with(MeasurementExtendedField(RealField)) {
        val a = (2.0 * kg) / (3.0 * m) / (2.0 * with(MeasureAlgebra) { s * s })
        val b = (23.0 * Pa)
        a + b
    }

    println(res)

    res = with(MeasurementExtendedField(RealField)) {
        val a = (2.0 * G(m)) + (3.0 * M(m))
        val b = (3.0 * au)
        a + b
    }

    println(res)
}
Measurement(measure=Measure(chain={SECOND=-2, METER=-1, KILOGRAM=1}, multiplier=1.0), value=23.333333333333332)
Measurement(measure=Measure(chain={METER=1}, multiplier=1.0), value=4.507966121E11)

Process finished with exit code 0

CommanderTvis avatar Feb 28 '21 07:02 CommanderTvis

Actually, it is a dynamic analogue of Measured API.

CommanderTvis avatar Feb 28 '21 07:02 CommanderTvis