Getting Started

This page walks you through the core SymbolicUncertainties.jl workflow in under 5 minutes: declare symbolic measurements, combine them with ordinary arithmetic, and read off the closed-form uncertainty expressions that JCGM 100:2008 (GUM) prescribes.

Regulated-use disclaimer

SymbolicUncertainties.jl implements the methodology of JCGM 100:2008 but has not been independently validated for calibration- accreditation contexts. See the Limitations page and LICENSE.md for the full non-warranty clause.

Notation: `±` and the combined standard uncertainty

In this package, a ± b builds a measurement whose uncertainty field is a combined standard uncertainty u_c, matching the Julia ecosystem convention established by Measurements.jl. This departs from JCGM 100:2008 §7.2.2, which recommends presenting a result with its combined standard uncertainty using one of four textual forms (for example m_S = 100.02147 g with u_c = 0.35 mg or the parenthetical form m_S = 100.02147(35) g) and deliberately avoids the ± glyph because it is historically associated with the expanded uncertainty y ± U = y ± k·u_c defined in §6.2. When producing a GUM-conformant calibration report, do not copy the Unicode ± display verbatim — use one of the four §7.2.2 textual forms instead, which report produces for you. See Reporting a Result.

Declare symbolic variables

using Symbolics
using SymbolicUncertainties
using DynamicQuantities

@variables V σV I σI V1 σV1 V2 σV2

Both Symbolics (for @variables) and SymbolicUncertainties (for SymbolicMeasurement and ±) need to be loaded.

Build a measurement with ±

The infix constructor ± pairs an estimate with its standard uncertainty:

V_m = V ± σV
I_m = I ± σI
V1_m = V1 ± σV1
V2_m = V2 ± σV2

\[V2 \pm σV2\]

Either operand can be a Symbolics.Num, a plain Number, or a mixture of the two. Plain numbers are promoted to symbolic literals automatically:

SymbolicMeasurement(1.5, 0.1)     # numeric constructor (unitless)

\[1.5 \pm 0.1\]

A negative numeric standard uncertainty is refused at construction time — the standard uncertainty u_c must be non-negative per JCGM 100:2008 §4.3.1:

julia> SymbolicMeasurement(1.5, -0.1)
ERROR: ArgumentError: standard uncertainty must be non-negative (GUM §4.3.1)

Combine measurements with the five binary operators

All five standard arithmetic operators (+, -, *, /, ^) are defined on SymbolicMeasurement. Each returns a new SymbolicMeasurement whose err field carries the propagated uncertainty expression implementing the relevant GUM §5.1 formula.

V1_m + V2_m     # sum            — REQ-010
V1_m - V2_m     # difference     — REQ-011
V_m * I_m     # product        — REQ-012
V_m^2         # integer power  — REQ-014
V_m / I_m     # quotient       — REQ-013

\[V / I \pm sqrt(((1 / I)^2)*(σV^2) + (((-V) / (I^2))^2)*(σI^2))\]

Unary - and + are defined too. Negation goes through the same chain rule with c = -1, so the source is preserved and a quantity still cancels against its own negation; a sign change cannot alter a dispersion, so u_c is unchanged (JCGM 100:2008 §4.3.1):

-V_m          # same u_c as V_m
V_m + (-V_m)  # exactly zero, uncertainty included

\[0 \pm 0\]

Mixed-mode expressions with plain numbers or bare symbolic variables also work — the non-measurement operand is treated as if it had zero uncertainty:

2 * V_m       # equivalent to (2 ± 0) * V_m
V_m / I       # I is a bare Symbolics.Num, not a measurement

\[V / I \pm sqrt(((1 / I)^2)*(σV^2))\]

A constant sensitivity is reported as |c|·u rather than sqrt(c²u²): 2 * V_m carries 2σV, not sqrt(4σV²). The package can make that reduction because a standard uncertainty is non-negative by construction (REQ-005) — Symbolics cannot, since it has no way to be told so (Symbolics.jl#98).

Worked example — Ohm's law

The textbook GUM example R = V / I illustrates the quotient rule for uncertainty propagation.

R_m = V_m / I_m

\[V / I \pm sqrt(((1 / I)^2)*(σV^2) + (((-V) / (I^2))^2)*(σI^2))\]

The resulting measurement's err field is algebraically equivalent to the GUM §5.1 reference form

\[u_R = \frac{V}{I}\sqrt{\left(\frac{\sigma_V}{V}\right)^2 + \left(\frac{\sigma_I}{I}\right)^2}\]

which you can reconstruct directly with Symbolics:

reference_err = (V / I) * sqrt((σV / V)^2 + (σI / I)^2)
(V*sqrt((σI / I)^2 + (σV / V)^2)) / I

Numerical substitution confirms the equivalence:

dict = Dict(V => 12.0, σV => 0.1, I => 0.5, σI => 0.005)
(
    Symbolics.substitute(R_m.err, dict),
    Symbolics.substitute(reference_err, dict),
)

# For physical units, use evaluate:
dict_units = Dict(V => 12.0u"V", σV => 0.1u"V", I => 0.5u"A", σI => 0.005u"A")
evaluate(R_m, dict_units)
(val = 24.0 m² kg s⁻³ A⁻², err = 0.3124099870362662 m² kg s⁻³ A⁻²)
Repeated operands are exact

The binary operators track operand identity. If the same measurement appears several times in an expression, the shared source is recognised and its sensitivities combine before the variance is formed:

julia> x = 8.4 ± 0.7
8.4 ± 0.7

julia> x - x
0.0 ± 0

julia> x / x
1 ± 0

julia> x + x
16.8 ± 1.4

(x + x is 2x with uncertainty , not σ√2.)

A quantity records which independent sources it derives from, so there is no right and wrong way to write the same model: the operators and propagate give the same answer.

Two measurements built by two separate ± calls remain independent, even when written with the same symbols: two resistors of equal nominal tolerance are not the same resistor.

See Uncertainty Sources for the representation this rests on.

Printing

A SymbolicMeasurement prints as val ± err in Unicode, with an ASCII +/- fallback in contexts where Unicode is unavailable (for example, plain-text log pipelines):

show(stdout, V_m)
println()
show(IOContext(stdout, :unicode => false), V_m)
V ± σV
V +/- σV

What's next

Sensitivity Analysis covers the mathematical functions — sin, cos, log, exp, sqrt and the rest — and multi-variable propagation through a function you supply (propagate(f, measurements)). Uncertainty Budget builds the EA-4/02 §7.3 table on top of the JCGM 100:2008 §5.1.3 sensitivity coefficients.

API reference

The core type and its constructors

SymbolicUncertainties.SymbolicMeasurementType
SymbolicMeasurement

A measurand recorded in the canonical JCGM 100:2008 estimate ± standard uncertainty form, using Symbolics.jl expressions throughout.

Implements the methodology of JCGM 100:2008 §4.1 (estimate of the measurand), §5.1 (combined standard uncertainty), and §G.4 (effective degrees of freedom).

Since M11 the quantity records which independent sources it derives from and with what sensitivity, rather than a bare uncertainty number. Every combined uncertainty, sensitivity coefficient, budget and covariance is derived from that structure.

Fields:

  • val::Symbolics.Num — symbolic expression for the estimate of the measurand (JCGM 100:2008 §4.1).
  • terms::Dict{SourceId,Symbolics.Num}∂val/∂source for each independent source the quantity depends on (JCGM 100:2008 §5.1.3, sensitivity coefficients cᵢ).
  • sources::Dict{SourceId,Source} — descriptor of each source: its standard uncertainty, optional degrees of freedom, display name. Carried by the quantity rather than held in module state, so that Symbolics.substitute stays local (REQ-120, REQ-123).
  • cov::Dict{Tuple{SourceId,SourceId},Symbolics.Num} — declared covariances between sources (JCGM 100:2008 §5.2.2). Empty by default: sources are independent unless declared otherwise.

Properties:

  • m.err — combined standard uncertainty u_c, computed from the fields above (JCGM 100:2008 §5.1), no longer a stored field.
  • m.dof — effective degrees of freedom ν_eff (§G.4).

SymbolicMeasurement is deliberately not a subtype of Real or AbstractFloat — this avoids implicit promotion loops with the Julia numeric tower and protects the symbolic uncertainty information from being silently dropped during generic numeric code.

Traces REQ-001, REQ-002, REQ-006, REQ-200.

source
SymbolicUncertainties.SymbolicMeasurementMethod
SymbolicMeasurement(val::Number, err::Number)

Build a SymbolicMeasurement from two plain numeric values, promoting both to Symbolics.Num literals so that the full symbolic pipeline applies uniformly to downstream operations.

Raises ArgumentError if err is a negative Real — the standard uncertainty must be non-negative per JCGM 100:2008 §4.3.1.

Implements the methodology of JCGM 100:2008 §4.3.1. Traces REQ-004, REQ-005.

source
SymbolicUncertainties.:±Method
±(a, u)

Infix constructor for SymbolicMeasurement. The left operand is the estimate of the measurand; the right operand is its standard uncertainty. Either operand may be a Symbolics.Num or a plain Number; numeric operands are promoted to Num literals.

± denotes the standard uncertainty (u_c), not the expanded uncertainty (U = k · u_c), consistent with JCGM 100:2008 §6.

Implements the methodology of JCGM 100:2008 §6. Traces REQ-003.

source

Binary arithmetic operators

Base.:+Method
Base.:+(x::SymbolicMeasurement, y::SymbolicMeasurement)

Propagate a sum per JCGM 100:2008 §5.1.3: val = x.val + y.val, with sensitivity coefficients cₓ = cᵧ = 1.

Implements the methodology of JCGM 100:2008 §5.1. Traces REQ-010, REQ-110, REQ-202.

source
Base.:-Method
Base.:-(x::SymbolicMeasurement, y::SymbolicMeasurement)

Propagate a difference per JCGM 100:2008 §5.1.3: val = x.val - y.val, with sensitivity coefficients cₓ = 1, cᵧ = -1.

The signs are retained rather than squared away, which is what makes x - x exactly zero when both operands are the same measurement.

Implements the methodology of JCGM 100:2008 §5.1. Traces REQ-011, REQ-110, REQ-202.

source
Base.:*Method
Base.:*(x::SymbolicMeasurement, y::SymbolicMeasurement)

Propagate a product per JCGM 100:2008 §5.1.3: val = x.val · y.val, with sensitivity coefficients cₓ = y.val, cᵧ = x.val.

Implements the methodology of JCGM 100:2008 §5.1. Traces REQ-012, REQ-110.

source
Base.:/Method
Base.:/(x::SymbolicMeasurement, y::SymbolicMeasurement)

Propagate a quotient per JCGM 100:2008 §5.1.3: val = x.val / y.val, with sensitivity coefficients cₓ = 1/y.val, cᵧ = -x.val/y.val².

This is the operator behind the Ohm's-law worked example (R = V/I), the M1 exit gate. Since M11 it also makes x / x exactly dimensionless-one with zero uncertainty.

Implements the methodology of JCGM 100:2008 §5.1. Traces REQ-013, REQ-110, REQ-202.

source
Base.:^Method
Base.:^(x::SymbolicMeasurement, n::Union{Real, Symbolics.Num})

Propagate a power per JCGM 100:2008 §5.1.3: val = x.val^n, with sensitivity coefficient cₓ = n · x.val^(n-1).

The exponent is a plain Real or a Symbolics.Num, never another measurement.

Implements the methodology of JCGM 100:2008 §5.1. Traces REQ-014, REQ-110.

source

Unary arithmetic operators

Base.:-Method
Base.:-(x::SymbolicMeasurement)

Negate a measurement: val = -x.val, sensitivity c = -1.

A sign change cannot change a dispersion, so u_c is unaffected (JCGM 100:2008 §4.3.1). Going through _chain rather than rebuilding from .err is what keeps the source identity, so m + (-m) is exactly zero rather than σ√2.

Implements the methodology of JCGM 100:2008 §5.1. Traces REQ-011, REQ-202.

source
Base.:+Method
Base.:+(x::SymbolicMeasurement)

Unary plus: the identity, present so that +m is not a MethodError where -m is defined.

Traces REQ-010.

source

Display

Base.showMethod
Base.show(io::IO, m::SymbolicMeasurement)

Display a SymbolicMeasurement as val ± err in Unicode when the output context supports it, falling back to val +/- err in plain ASCII when the context carries :unicode => false.

Traces REQ-111.

source