Right, that was my original idea, but perhaps we can do something much simpler:
Inv == top[(pop ** n)[s]] = xwhere n and s are the variables in my PushPop module. I think that the invariant
Inv is an inductive invariant, that it proves the theorem, and that no further axioms than "my" two (specifically with regards to the empty stack and the construction of S) are necessary to prove
Inv.
Finally, while your axiomatization constructs S and its operations "from scratch" in terms of X and the axioms, wouldn't it be easier in practice to do something like the following, instead of CHOOSEing the functions etc.:
CONSTANTS X, \* The set of elements
S, \* The set of stacks
push, pop, top, EMPTY
ASSUME /\ EMPTY \in S
/\ push \in [S \X X -> S]
/\ pop \in [S \ {EMPTY} -> S]
/\ top \in [S \ {EMPTY} -> X]
/\ \A x \in X, s \in S : push[<<x, s>>] \in S \* closure
/\ \A x \in X, s \in S : push[<<x, s>>] /= EMPTY
/\ \A x \in X, s \in S : top[push[<<x, s>>]] = x
/\ \A x \in X, s \in S : pop[push[<<x, s>>]] = s
/\ \A s \in S : s = EMPTY \/ \E s1 \in S, x \in X : s = push[<<x, s1>>]
Doesn't this specify S sufficiently in terms of X and the operations, rather than constructing S as you've done?
Ron