Documentation

Linglib.Tactics.RSAPredict.Backend.Reflection

Reflection — Proof by Reflection for Interval Arithmetic #

Defines a reified expression type RExpr with:

The rsa_decide tactic reifies ℝ expressions into RExpr values, then:

  1. native_decide checks evalValid (always true for RSA expressions)
  2. native_decide evaluates (rhs.eval).hi < (lhs.eval).lo in compiled code
  3. The kernel verifies only eval_sound applications + native_decide

This eliminates the 5M+ Nat.cast kernel reductions from the old Expr-based approach.

inductive Interval.RExpr :

Reified arithmetic expression over ℝ.

Each constructor corresponds to an operation the rsa_decide tactic can reify. The denote function maps back to ℝ; the eval function computes a QInterval bounding the value.

Instances For
    @[implicit_reducible]
    Equations
    def Interval.instReprRExpr.repr :
    RExprStd.Format
    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      @[implicit_reducible]
      Equations
      def Interval.instDecidableEqRExpr.decEq (x✝ x✝¹ : RExpr) :
      Decidable (x✝ = x✝¹)
      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        noncomputable def Interval.RExpr.denote :
        RExpr

        Map a reified expression to its real value. Noncomputable (uses Real.exp, etc.).

        Equations
        Instances For

          Evaluate a reified expression to a bounding QInterval. Fully computable. Every compound operation is coarsened to bounded-precision rationals.

          Equations
          Instances For

            Whether eval avoids unsound fallback branches.

            The fallback intervals in eval (e.g., ⟨-1, 1⟩ for division with non-positive denominator) are hard-coded constants that do not soundly bound the result for arbitrary inputs. evalValid returns true exactly when no such fallback is reached — i.e., every division has a positive denominator, every log/inv has a positive argument, and every rpow has a nonneg base (or zero exponent).

            In practice, rsa_decide only builds RExpr values from RSA computations (positive probabilities, positive denominators), so evalValid is always true. The tactic verifies this via native_decide as a precondition.

            Equations
            Instances For
              def Interval.RExpr.tryExtractLogProduct :
              RExprOption (List (RExpr × ))

              Extract (xᵢ, bᵢ) pairs from a sum-of-weighted-logs RExpr. Returns none if the expression doesn't match the pattern Σ bᵢ · log(xᵢ). Coefficients bᵢ are rational (not just integer), enabling exact evaluation when log arguments coincide and coefficients sum to an integer (e.g., 1/3 · log(x) + 1/3 · log(x) + 1/3 · log(x)x^1 exactly).

              Equations
              Instances For

                Merged eval + evalValid in a single traversal. Returns (interval, valid). This eliminates the redundant eval calls that evalValid makes on subexpressions — each node computes its interval exactly once. Uses a flat pair instead of Option to avoid heap allocation overhead in compiled code.

                Equations
                Instances For

                  Soundness of the merged eval+validity check. If evalBoth returns (I, true), then I contains the real denotation. This mirrors eval_sound but avoids the redundant subexpression evaluation that plagues the separate evalValid + eval approach.

                  Soundness of interval evaluation by reflection.

                  Every well-formed RExpr (one where evalValid = true) evaluates to a QInterval that contains the real denotation. The evalValid precondition excludes expressions with degenerate operations (division by non-positive, log of non-positive, etc.) whose fallback intervals are unsound.

                  theorem Interval.RExpr.gt_of_eval_separated (lhs rhs : RExpr) (hlv : lhs.evalValid = true) (hrv : rhs.evalValid = true) (h : rhs.eval.hi < lhs.eval.lo) :
                  lhs.denote > rhs.denote

                  If interval evaluation proves separation, the denotations are ordered. Requires evalValid for both sides to ensure the intervals are sound.

                  @[implicit_reducible]
                  instance Interval.instDecidableLtRatHiEvalLo (lhs rhs : RExpr) :
                  Decidable (rhs.eval.hi < lhs.eval.lo)

                  Decidable separation check (for native_decide).

                  Equations
                  theorem Interval.RExpr.not_gt_of_eval_bounded (lhs rhs : RExpr) (hlv : lhs.evalValid = true) (hrv : rhs.evalValid = true) (h : lhs.eval.hi rhs.eval.lo) :
                  ¬lhs.denote > rhs.denote

                  Non-separation for ¬(>) goals.

                  @[implicit_reducible]
                  instance Interval.instDecidableLeRatHiEvalLo (lhs rhs : RExpr) :
                  Decidable (lhs.eval.hi rhs.eval.lo)
                  Equations

                  Optimized evaluation for rexp nodes: recursively decomposes the inner expression using exp identities:

                  • exp(a + b) = exp(a) · exp(b) — splits sums
                  • exp(n · log(x)) = x^n when n ∈ ℕ, x > 0 — exact power
                  • exp(n · body) = exp(body)^n when n ∈ ℕ — factors out nat multiplier
                  • exp(other) via Padé — fallback
                  Instances For

                    Like evalBoth but intercepts .rexp nodes to use the exp-log product rewrite via evalRexpOpt. All other cases are identical to evalBoth. evalRexpOpt itself calls evalBoth (not evalBothOpt) for leaf sub-expressions, avoiding mutual recursion — this is correct because .rexp nodes don't nest inside each other in RSA expression trees.

                    Equations
                    Instances For

                      Soundness of evalBothOpt. Mirrors evalBoth_sound — all cases except .rexp are structurally identical; .rexp delegates to evalRexpOpt which needs separate soundness reasoning.

                      def Interval.RExpr.checkGt (lhs rhs : RExpr) :
                      Bool

                      Combined check: eval + validity + separation in a single pass via evalBoth. Each subexpression is evaluated exactly once.

                      Equations
                      Instances For
                        theorem Interval.RExpr.gt_of_checkGt (lhs rhs : RExpr) (h : lhs.checkGt rhs = true) :
                        lhs.denote > rhs.denote

                        If checkGt succeeds, the denotations are ordered.

                        def Interval.RExpr.checkNotGt (lhs rhs : RExpr) :
                        Bool

                        Combined check for ¬(>): eval + validity + upper bound in a single pass.

                        Equations
                        Instances For
                          theorem Interval.RExpr.not_gt_of_checkNotGt (lhs rhs : RExpr) (h : lhs.checkNotGt rhs = true) :
                          ¬lhs.denote > rhs.denote

                          If checkNotGt succeeds, ¬(lhs > rhs).

                          Check if an RExpr is provably zero via interval arithmetic.

                          Equations
                          Instances For
                            def Interval.RExpr.isPos (e : RExpr) :
                            Bool

                            Check if an RExpr is provably positive via interval arithmetic.

                            Equations
                            Instances For
                              theorem Interval.RExpr.denote_eq_zero (e : RExpr) (h : e.isZero = true) :
                              e.denote = 0

                              If isZero succeeds, the denotation is 0.

                              theorem Interval.RExpr.denote_ne_zero (e : RExpr) (h : e.isPos = true) :
                              e.denote 0

                              If isPos succeeds, the denotation is nonzero.

                              Normalize an RExpr by:

                              1. Resolving iteZero with constant conditions (dead-branch elimination)
                              2. Eliminating mul with provably-zero operands
                              3. Rewriting rexp(mul(α, sub(rlog(x), c)))expMulLogSub(α, x, c) All transformations preserve denotation. Dead-branch elimination is critical for proving ¬(>) on symmetric models, where two expressions become structurally identical after resolving iteZero branches.
                              Equations
                              Instances For

                                Normalization preserves denotation.

                                Equations
                                • =
                                Instances For
                                  theorem Interval.RExpr.not_gt_of_normalize_eq (lhs rhs : RExpr) (h : lhs.normalize = rhs.normalize) :
                                  ¬lhs.denote > rhs.denote

                                  If two RExprs normalize to the same tree, their denotations are equal, so neither is greater than the other.

                                  def Interval.RExpr.checkGtOpt (lhs rhs : RExpr) :
                                  Bool

                                  Tree-based comparison using evalBothOpt. Used by rsa_predict for sorry-free soundness proofs.

                                  Equations
                                  Instances For
                                    def Interval.RExpr.checkNotGtOpt (lhs rhs : RExpr) :
                                    Bool

                                    Tree-based comparison for ¬(>).

                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For
                                      theorem Interval.RExpr.gt_of_checkGtOpt (lhs rhs : RExpr) (h : lhs.checkGtOpt rhs = true) :
                                      lhs.denote > rhs.denote

                                      If checkGtOpt succeeds, the denotations are ordered.

                                      theorem Interval.RExpr.not_gt_of_checkNotGtOpt (lhs rhs : RExpr) (h : lhs.checkNotGtOpt rhs = true) :
                                      ¬lhs.denote > rhs.denote

                                      If checkNotGtOpt succeeds, ¬(lhs > rhs).

                                      @[implemented_by _private.Linglib.Tactics.RSAPredict.Backend.Reflection.0.Interval.RExpr.checkGtOptCachedImpl]
                                      def Interval.RExpr.checkGtOptMemo (lhs rhs : RExpr) :
                                      Bool

                                      Memoized gt check. The @[implemented_by] annotation makes native_decide use the fast memoized implementation while the reference implementation (identical to checkGtOpt) is used for kernel verification.

                                      Equations
                                      Instances For
                                        @[implemented_by _private.Linglib.Tactics.RSAPredict.Backend.Reflection.0.Interval.RExpr.checkNotGtOptCachedImpl]
                                        Equations
                                        Instances For
                                          theorem Interval.RExpr.gt_of_checkGtOptMemo (lhs rhs : RExpr) (h : lhs.checkGtOptMemo rhs = true) :
                                          lhs.denote > rhs.denote
                                          theorem Interval.RExpr.not_gt_of_checkNotGtOptMemo (lhs rhs : RExpr) (h : lhs.checkNotGtOptMemo rhs = true) :
                                          ¬lhs.denote > rhs.denote
                                          def Interval.RExpr.evalExact :
                                          RExprOption

                                          Evaluate an RExpr to an exact ℚ value, if possible. Handles exp nodes via log factor grouping (e.g., exp(1/2·log(x) + 1/2·log(x)) groups to exp(1·log(x)) = x). Returns none for log, expMulLogSub, or when log factor coefficients don't sum to natural numbers. Used for ¬(>) goals where interval arithmetic is too imprecise.

                                          Equations
                                          Instances For
                                            theorem Interval.RExpr.evalExact_sound (e : RExpr) (q : ) (h : e.evalExact = some q) :
                                            e.denote = q

                                            Soundness: if evalExact returns q, then denote = (q : ℝ).

                                            If both sides have the same exact ℚ value, ¬(lhs > rhs).

                                            Equations
                                            Instances For
                                              theorem Interval.RExpr.not_gt_of_checkExactNotGt (lhs rhs : RExpr) (h : lhs.checkExactNotGt rhs = true) :
                                              ¬lhs.denote > rhs.denote

                                              Soundness of exact ¬(>) check.

                                              def Interval.RExpr.checkExactGt (lhs rhs : RExpr) :
                                              Bool

                                              If lhs evaluates to a strictly greater ℚ than rhs, lhs.denote > rhs.denote.

                                              Equations
                                              Instances For
                                                theorem Interval.RExpr.gt_of_checkExactGt (lhs rhs : RExpr) (h : lhs.checkExactGt rhs = true) :
                                                lhs.denote > rhs.denote

                                                Soundness of exact (>) check.

                                                def Interval.RExpr.checkExactEq (lhs rhs : RExpr) :
                                                Bool

                                                Check exact equality: both sides evaluate to the same ℚ.

                                                Equations
                                                Instances For
                                                  theorem Interval.RExpr.eq_of_checkExactEq (lhs rhs : RExpr) (h : lhs.checkExactEq rhs = true) :
                                                  lhs.denote = rhs.denote

                                                  Soundness of exact equality check.

                                                  @[irreducible]

                                                  Semantic equality: walk two RExpr trees in parallel, using evalExact at each node when possible. Handles exp/log cases where evalExact returns none by checking structural match and recursing into children. This enables proving exp(log(1/(0+1+1))) = exp(log(1/(1+0+1))) — the exp/log match structurally, and the arithmetic children both evalExact to 1/2.

                                                  Equations
                                                  Instances For
                                                    theorem Interval.RExpr.eq_of_checkSemanticEq (lhs rhs : RExpr) (h : lhs.checkSemanticEq rhs = true) :
                                                    lhs.denote = rhs.denote

                                                    Soundness of semantic equality: if checkSemanticEq returns true, then the two expressions denote the same real number.

                                                    theorem Interval.RExpr.not_gt_of_checkSemanticEq (lhs rhs : RExpr) (h : lhs.checkSemanticEq rhs = true) :
                                                    ¬lhs.denote > rhs.denote

                                                    If semantically equal, neither side is strictly greater.

                                                    theorem Interval.RExpr.not_gt_of_denote_eq (lhs rhs : RExpr) (h : lhs.denote = rhs.denote) :
                                                    ¬lhs.denote > rhs.denote

                                                    When lhs and rhs denote the same value, lhs > rhs is impossible.