Skip to content

Formal Design and Formal Verification ​

Optimization requirements already make extensive use of sets, quantifiers, equalities, and inequalities. They are therefore natural candidates for formal design before coding and for verification that domain rules, mathematical expressions, and program behavior agree afterward. The goal is not necessarily one machine-checked proof for the entire system. It is to give every important rule explicit premises, checkable semantics, and traceable evidence.

1. Three objects to align ​

Distinguish three levels for one business rule:

LevelNotationExample
Domain propositionpA point on a triangulated surface has one interpolated height
Mathematical specificationpf:X→BThe point belongs to one triangle and its height is the barycentric interpolation
Executable implementationpe:X→BTriangle selectors, barycentric weights, and their linear constraints

Let K be the existing domain knowledge and premises. A new rule must first be consistent:

SAT(K∪{pf})⟺∃x∈X:(⋀q∈Kq(x))∧pf(x).

Implementation correctness requires:

K⊨(pf⇔pe),

or explicitly:

∀x∈X:(⋀q∈Kq(x))⇒(pf(x)⇔pe(x)).

A unit, bound, integrality condition, or data assumption that is absent from K cannot be used silently in a proof or test.

2. Formal design workflow ​

2.1 Give the rule an identity ​

Assign a stable ID, domain name, owning Context, source, and version. A name such as bandwidth.no_outflow_without_service expresses business meaning; an implementation sequence number does not.

2.2 Declare the universe and premises ​

Specify:

  • sets, indices, and empty-set behavior;
  • decision-variable domains;
  • parameter units, ranges, and null policy;
  • finite bounds and how they were derived;
  • conversion of strict inequalities;
  • solver and business tolerances.

2.3 Write the domain predicate ​

First write a proposition independent of Big-M, auxiliary variables, or a solver. Split a sentence that contains several conjunctions, exceptions, or “unless” clauses into independently named predicates.

2.4 Derive the mathematical implementation ​

Two workflows are valid:

  1. derive executable pe deductively from K and pf;
  2. propose pe, then prove K⊨(pf⇔pe).

The second workflow cannot stop at “this is a common formulation” or “the sample solves.” It must state the equivalence conditions, especially finite bounds and variable domains.

2.5 Map it to OSPF elements ​

  • an Aggregation or domain Model owns variables;
  • reusable definitions become named intermediate values;
  • a named Pipeline registers constraints;
  • the Context selects registrations for a business mode or solve path;
  • the Application orchestrates without redefining formulas.

2.6 Establish traceability ​

Link the proposition ID, formula, Pipeline, tests, benchmark data, and change record. Any formula change should reveal the affected tests and consuming contexts.

3. Equivalence obligations ​

Logical equivalence separates into two directions:

pe(x)⇒pf(x)⏟soundness: the implementation accepts no domain-invalid solution,pf(x)⇒pe(x)⏟completeness: the implementation rejects no domain-valid solution.

It can also be viewed as positive and negative specification branches:

Specification pfImplementation peResult
truetruePositive branch passes
truefalseFalse negative; completeness violation
falsefalseNegative branch passes
falsetrueFalse positive; soundness violation

Tests cannot cover only expected-feasible examples. Every constraint needs at least one candidate that violates that rule while satisfying as many other premises as possible.

4. Classic derivation I: bivariate linear piecewise function ​

This section follows the current triangulation-and-barycentric-interpolation implementation in ospf-kotlin. The goal is not merely to obtain approximately correct values at a few sampled points. Starting with the business semantics, it derives linear constraints from a logical disjunction and proves that every feasible symbolic solution describes exactly the piecewise-linear surface over the given triangulation.

4.1 Natural-language rule and premises ​

Let T be a non-empty set of triangles. The three three-dimensional vertices of triangle t∈T are:

Ptj=(xtj,ytj,ztj),j∈{1,2,3}.

For input (x,y) and output z, the rule is:

  • (x,y) must lie in the two-dimensional projection of at least one triangle;
  • after selecting a triangle that contains (x,y), z must equal the barycentric interpolation of its three vertex heights;
  • if (x,y) belongs to no triangle, the function is undefined there and the symbolic model must be infeasible.

Every projected triangle must be non-degenerate:

Dt=(xt2−xt1)(yt3−yt1)−(xt3−xt1)(yt2−yt1)≠0.

Triangles that share an edge or vertex must agree on z at every shared position. Triangle interiors must not overlap unless their affine planes agree everywhere on the overlap. Otherwise, one (x,y) may correspond to multiple z values, producing a relation rather than a function.

4.2 Logical language ​

Do not introduce selectors yet. For every triangle t, define the predicate “the input and output lie on this piece”:

Rt(x,y,z)≡∃λt1,λt2,λt3∈R≥0:∑j=13λtj=1∧x=∑j=13λtjxtj∧y=∑j=13λtjytj∧z=∑j=13λtjztj.

The first three conditions say that (x,y) is a point in the projected triangle. The final condition interpolates the height with the same barycentric weights. The entire bivariate linear piecewise function is the logical disjunction of all triangle branches:

pf(x,y,z)≡⋁t∈TRt(x,y,z).

This definition also expresses the domain: if no Rt holds, no legal output z exists. If several predicates hold on a shared boundary, the surface-consistency premise ensures that all of them produce the same z.

4.3 Derivation of the linear inequalities ​

The “at least one branch holds” logic must become a mixed-integer linear model. Introduce a selector for every triangle:

δt∈{0,1}.

Step 1: activate exactly one piece.

∑t∈Tδt=1.

If the solver's standard form retains only inequalities, this equality is equivalent to:

∑tδt≤1,−∑tδt≤−1.

Step 2: activate the corresponding barycentric weights. Introduce λtj≥0 for every vertex and impose:

∑j=13λtj=δt,∀t∈T.

When δt=0, non-negativity and the weight sum force every weight of that piece to zero. When δt=1, the weights are non-negative and sum to one. The inequality-only form is:

∑jλtj−δt≤0,δt−∑jλtj≤0.

Step 3: combine the coordinates and heights of all branches.

Define:

Ax(λ)=∑t∈T∑j=13λtjxtj,Ay(λ)=∑t∈T∑j=13λtjytj,Az(λ)=∑t∈T∑j=13λtjztj.

Link the inputs and output:

x=Ax(λ),y=Ay(λ),z^=Az(λ).

Each equality v=Av(λ) expands into a pair of linear inequalities:

v−Av(λ)≤0,Av(λ)−v≤0,v∈{x,y,z^}.

The logical disjunction has now been converted completely into binary variables, non-negative variables, and linear inequalities. No arbitrarily large Big-M is needed. In ospf-kotlin, zVars play the role of δt and lambdaVars play the role of λtj.

4.4 Equivalence proof ​

Soundness pe⇒pf: Since ∑tδt=1 and every δt is binary, exactly one triangle t⋆ is selected. For every t≠t⋆:

∑jλtj=δt=0.

Together with λtj≥0, this makes every weight of an inactive triangle zero. The weights of t⋆ are non-negative and sum to one, and the input-output linking constraints therefore satisfy Rt⋆(x,y,z^). Consequently, pf(x,y,z^) holds.

Completeness pf⇒pe: If pf(x,y,z) holds, at least one triangle t⋆ and one set of barycentric weights satisfy Rt⋆(x,y,z). Set δt⋆=1 and every other selector to zero; retain the weights of that piece and set all other weights to zero. This assignment satisfies every linear constraint.

Under the non-degeneracy and overlap-consistency premises KT, therefore:

KT⊨(pf(x,y,z)⇔pe(x,y,z)).

Soundness ensures that the model accepts no point outside the domain or with an incorrect interpolated value. Completeness ensures that the linear model represents every surface point admitted by the logical specification.

4.5 Tests derived from the proof ​

Use the triangle:

P1=(0,0,0),P2=(1,0,1),P3=(0,1,1).

The surface on this piece is z=x+y, so the correct result for (x,y)=(0.25,0.25) is:

z=0.5.

At minimum, verify:

ClassInputVerification
Three verticesP1,P2,P3Weights are one-hot and the result equals the vertex height
Interior point(0.25,0.25)Three weights are non-negative and sum to one; z=0.5
Shared edgeOne weight is zeroAdjacent pieces return the same z and order does not affect the result
Outside domainPoint belongs to no triangleDirect evaluation returns empty and the symbolic model is infeasible
Degenerate triangleDt=0 or nearly zeroConstruction/evaluation rejects it according to contract, outside the proof domain
Overlapping piecesOne (x,y) is in multiple interiorsEither reject them or prove equal heights throughout the overlap
Dual-path consistencySame inputevaluate agrees with z^ after the solver fixes the inputs

See Bivariate Linear Piecewise Function for APIs and additional boundaries.

This example focuses on the successive translation of one business rule into executable constraints. It does not address code reuse or implementation techniques for intermediate values.

5.1 Natural-language rule ​

For every loading position p:

  • if the position is not selected for recommended loading, its recommended load weight must be zero;
  • if it is selected, its recommended load weight must lie in the permitted interval [W―p,W―p];
  • the interval uses one consistent weight unit and satisfies 0<W―p≤W―p.

The “if ... then ...” and interval clauses must first become logical propositions rather than jumping directly to a Big-M row.

5.2 Logical language ​

Define:

up∈{0,1}

to indicate whether position p is selected, and let wp∈R≥0 be its recommended load weight. The domain predicate is:

pf(up,wp)≡(up=0∧wp=0)∨(up=1∧W―p≤wp≤W―p).

Equivalently, it is the conjunction of two implications:

up=0⇒wp=0,up=1⇒W―p≤wp≤W―p.

Because up is binary, the states are mutually exclusive and exhaustive. The positive lower bound also means wp>0 if and only if up=1. If the business permits a selected position to carry a zero recommendation, use a zero lower bound and remove that biconditional interpretation.

5.3 Derivation of the linear inequalities ​

First consider the upper bound. The two logical states require:

up=0:wp≤0,up=1:wp≤W―p.

Since up∈{0,1}, both cases combine into:

wp≤W―pup.

For the lower bound, the two states require:

up=0:wp≥0,up=1:wp≥W―p.

They combine into:

wp≥W―pup.

The final linear implementation is therefore:

pe(up,wp)≡W―pup≤wp≤W―pup.

Here W―p is not an arbitrarily large Big-M. It is the valid business upper bound for position p; W―p is likewise part of the specification.

5.4 Equivalence proof ​

Soundness pe⇒pf:

  • If up=0, the linear row becomes 0≤wp≤0, so wp=0.
  • If up=1, it becomes W―p≤wp≤W―p.

Both binary branches satisfy the domain predicate, so the implementation accepts no rule-violating solution.

Completeness pf⇒pe:

  • In the domain state up=0∧wp=0, substitution gives 0≤0≤0.
  • In the domain state up=1∧W―p≤wp≤W―p, substitution yields exactly that interval.

Under the premises

up∈{0,1},0<W―p≤W―p,

we therefore have:

Kweight⊨(pf(up,wp)⇔pe(up,wp)).

5.5 Tests derived from the proof ​

For W―p=100kg and W―p=500kg, cover at least:

upwpExpectedProof branch
00FeasiblePositive unselected case
0δInfeasibleNegative unselected case
1100FeasibleClosed lower boundary
1300FeasibleInterval interior
1500FeasibleClosed upper boundary
1100−δInfeasibleBelow lower bound
1500+δInfeasibleAbove upper bound

δ must exceed the solver's feasibility tolerance. Also verify that:

  • the equivalence test fails if up is incorrectly relaxed to a continuous variable;
  • inconsistent units among the bounds and weight are rejected or converted before model construction;
  • data with W―p>W―p is rejected during initialization;
  • a small multi-position instance compares the truth values of pf and pe point by point;
  • Kotlin and Rust solver tests reach the same feasibility verdict after fixing up,wp.

6. Five verification layers ​

LayerSubjectRecommended evidence
1. Domain predicateNatural language agrees with the formal specificationDomain review, truth table, counterexamples
2. Mathematical derivationK⊨(pf⇔pe)Algebraic proof, SMT/exhaustion, small counterexample model
3. Symbol constructionOSPF expression equals peSnapshot of coefficients, constants, bounds, and row sense
4. Solver contractCompiled model implements symbol semanticsTiny feasible/infeasible models and multi-backend tests
5. Application behaviorContext composition and analysis are correctBenchmarks, regression suite, and domain invariants

Passing layer 3 does not prove layer 2. Obtaining the expected objective from a solver does not replace negative-branch verification.

7. Consistency, redundancy, and conflict ​

Before adding p, check these separately.

Consistency ​

SAT(K∪{p}).

If unsatisfiable, report an unsatisfiable core or minimal conflicting rule set using domain names.

Redundancy ​

K⊨p.

A redundant constraint does not change the feasible region. It may remain as an LP strengthening, readable invariant, or diagnostic aid, but record that purpose instead of treating it as new business knowledge.

Conflict ​

K⊨¬p.

The new rule rejects every currently feasible case. If that is an intended business change, replace or version the affected rules and benchmarks rather than simply stacking it on top.

8. Numerical semantics ​

A formal specification uses exact relations; a floating-point solver uses tolerances. A verification report should state:

  • the specification relation, such as g(x)≤b;
  • solver tolerance εs;
  • test-oracle tolerance εt;
  • business tolerance εb;
  • scaling and units.

Do not use a value inside the tolerance gray zone as the only negative test. For an equality, cover b−δ, b, and b+δ, and state which are business-valid, mathematically valid, and solver-accepted.

9. Verification in decomposition algorithms ​

Column generation ​

Prove that the feasible columns produced by Pricing have the same definition as columns accepted by Master, and verify:

c¯p=cp−∑iπiaip

with one cost, coefficient, and dual-sign convention on both sides. Compare against complete column enumeration on small instances.

Benders ​

Prove that selective registration is equivalent to the complete model, fixed-variable mapping preserves semantics, and every cut is valid for all feasible original solutions. A feasibility cut must reject the current infeasible master candidate; an optimality cut must provide the correct recourse lower bound at its generating point.

10. Change control ​

When a rule changes:

  1. update its domain proposition, premises, and version;
  2. recheck consistency, redundancy, and affected deductions;
  3. update the mathematical derivation and intermediate-value interfaces;
  4. modify the Pipeline or function-symbol implementation;
  5. update tests from the new proof branches;
  6. run Context, complete-model, decomposition, and backend regressions;
  7. record whether the feasible region or objective semantics changed.

An implementation optimization that preserves the truth set of pe is a semantics-preserving refactor. A changed truth set is a domain-rule change.

11. Definition of done ​

A rule is complete only when:

  • it has a stable ID, owner, and business description;
  • premises, units, domains, and tolerances are explicit;
  • both the mathematical specification and executable expression are recorded;
  • both equivalence directions have a proof or sufficient checkable evidence;
  • positive, negative, boundary, and invalid-input tests exist;
  • documentation traces to intermediate values, Pipeline, tests, and benchmarks;
  • contract tests pass on every solver backend used in production.