Algorithm Search⌘K

Proofs: Postfix expression evaluation

These are the human proofs of Postfix expression evaluation, at full length.

Postfix evaluation returns the value of a postfix expression and rejects every other string full

This proof shows: correctness, termination.

Claim. Let s=s1⋯sms = s_1 \cdots s_m be a token string. If s∈Ps \in \mathcal{P}, POSTFIX-EVAL returns val⁡(s)\operatorname{val}(s). If s∉Ps \notin \mathcal{P}, it reports an error. In both cases it stops after at most mm rounds of the loop.

Setup. We use the definitions of the reverse Polish notation page: the weight ww of a token (11 for an operand, 1−ar⁡(ω)1 - \operatorname{ar}(\omega) for an operator), the prefix sums Pj=∑i≤jw(si)P_j = \sum_{i \le j} w(s_i) with P0=0P_0 = 0, and its theorem: s∈Ps \in \mathcal{P} exactly when Pj≥1P_j \ge 1 for 1≤j≤m1 \le j \le m and Pm=1P_m = 1, and each element of P\mathcal{P} splits by rule 2 in exactly one way, so val⁡\operatorname{val} is well defined.

We prove this invariant for the loop of line L2. It holds before round j+1j + 1, for 0≤j≤m0 \le j \le m, provided that rounds 1,…,j1, \ldots, j reported no error:

(E) Pi≥1P_i \ge 1 for 1≤i≤j1 \le i \le j. The prefix s1⋯sjs_1 \cdots s_j is a concatenation F1⋯FpF_1 \cdots F_p with p=Pjp = P_j and each Fr∈PF_r \in \mathcal{P}, and the stack holds val⁡(F1),…,val⁡(Fp)\operatorname{val}(F_1), \ldots, \operatorname{val}(F_p) from the bottom to the top. In particular ∣S∣=Pj|S| = P_j.

Step 1: initialization. Before round 1, j=0j = 0, the prefix is empty, p=0=P0p = 0 = P_0, and the stack is empty. (E) holds.

Step 2: maintenance. Assume (E) for jj, and consider round j+1j + 1 with token sj+1s_{j+1}.

  • Operand. Line L3 pushes v=sj+1v = s_{j+1}. Set Fp+1=vF_{p+1} = v, which is in P\mathcal{P} by rule 1, with val⁡(Fp+1)=v\operatorname{val}(F_{p+1}) = v. Now p+1=Pj+1=Pj+1≥1p + 1 = P_j + 1 = P_{j+1} \ge 1, and (E) holds for j+1j + 1.
  • Operator ω\omega of arity kk with k≤pk \le p. Line L5 does not report an error, since ∣S∣=p≥k|S| = p \ge k. Line L6 pops the top kk values, which are val⁡(Fp−k+1),…,val⁡(Fp)\operatorname{val}(F_{p-k+1}), \ldots, \operatorname{val}(F_p): the first pop is the top, val⁡(Fp)\operatorname{val}(F_p), and it goes to y[k]y[k], so y[r]=val⁡(Fp−k+r)y[r] = \operatorname{val}(F_{p-k+r}) for r=1,…,kr = 1, \ldots, k. Let G=Fp−k+1⋯Fp ωG = F_{p-k+1} \cdots F_p\, \omega. By rule 2, G∈PG \in \mathcal{P}, and by the definition of val⁡\operatorname{val}, val⁡(G)=fω(y[1],…,y[k])\operatorname{val}(G) = f_\omega(y[1], \ldots, y[k]), which line L7 pushes. So the prefix s1⋯sj+1s_1 \cdots s_{j+1} is F1⋯Fp−k GF_1 \cdots F_{p-k}\, G, a concatenation of p−k+1p - k + 1 postfix expressions, and the stack holds their values in order. Since Pj+1=Pj+1−k=p−k+1≥1P_{j+1} = P_j + 1 - k = p - k + 1 \ge 1, (E) holds for j+1j + 1.
  • Operator ω\omega of arity kk with k>pk > p. Line L5 reports an error. In this case Pj+1=p+1−k≤0P_{j+1} = p + 1 - k \le 0, so the condition of the theorem fails at j+1j + 1, and s∉Ps \notin \mathcal{P}. The error is correct.

Step 3: termination. Each round increases jj by exactly 1, and the loop has mm rounds, so it stops after at most mm rounds, either at an error of line L5 or after round mm. Lines L6 and L7 run a bounded number of steps for each round, kk pops and one push.

Step 4: the result. Suppose that no round reported an error. Then (E) holds for j=mj = m: Pi≥1P_i \ge 1 for all ii, and the stack holds PmP_m values.

  • If Pm=1P_m = 1, then ss satisfies the condition of the theorem, so s∈Ps \in \mathcal{P}. By (E), s=F1s = F_1 and the stack holds only val⁡(F1)=val⁡(s)\operatorname{val}(F_1) = \operatorname{val}(s). Line L8 finds ∣S∣=1|S| = 1, and line L9 returns val⁡(s)\operatorname{val}(s).
  • If Pm≠1P_m \ne 1, then s∉Ps \notin \mathcal{P} by the theorem, and line L8 finds ∣S∣=Pm≠1|S| = P_m \ne 1 and reports an error.

Suppose now that a round j+1j + 1 reported an error. By Step 2 this happens only in the third case, where s∉Ps \notin \mathcal{P}.

So for s∈Ps \in \mathcal{P} no error occurs (each error case implies s∉Ps \notin \mathcal{P}), and the algorithm returns val⁡(s)\operatorname{val}(s). For s∉Ps \notin \mathcal{P} it cannot return a value, because a return at line L9 needs no error in the loop and Pm=1P_m = 1, which with (E) means s∈Ps \in \mathcal{P}. So it reports an error. ■\blacksquare

Back to Postfix expression evaluation