// Independent reading noise and one shared calibration term are declared.
import aner.tensor
import aner.science

let readings = science.calibrated([[20.0], [22.0]], "degC",
    noise_stddev: 0.2, calibration_stddev: 0.3)
let first = readings.gather_rows(List(0))
let second = readings.gather_rows(List(1))
let fused = science.mean(first, second)
let difference = first.subtract(second)
let self_difference = first.subtract(first)
let duplicated_mean = science.mean(first, first)
let kelvin = fused.convert("K")

print("Fused mean in degrees Celsius")
print(fused.item())
print("Fused variance is 0.11 within tolerance")
print(fused.variance() > 0.109999999999 && fused.variance() < 0.110000000001)
print("Difference mean and variance 0.08 within tolerance")
print(difference.item())
print(difference.variance() > 0.079999999999 && difference.variance() < 0.080000000001)
print("The same observation cancels its own uncertainty")
print(self_difference.variance())
print("Duplicating one observation does not create independent noise")
print(duplicated_mean.variance() > 0.129999999999 && duplicated_mean.variance() < 0.130000000001)
print("Kelvin conversion preserves physical uncertainty")
print(kelvin.item() > 294.149999999 && kelvin.item() < 294.150000001)
print(kelvin.variance() > 0.109999999999 && kelvin.variance() < 0.110000000001)

// A frozen affine physical relationship propagates input measurement noise.
// This is neither training nor uncertainty in learned model parameters.
let length = science.calibrated([[20.0]], "m", 0.2, 0.3)
let force = length.affine(slope: 2.0, intercept: 1.0, slope_unit: "N/m", output_unit: "N")
print("Frozen relationship y = 2*x + 1")
print(force.item())
print(force.unit())
print("Propagated input-noise variance is 0.52 within tolerance")
print(force.variance() > 0.519999999999 && force.variance() < 0.520000000001)
