Hi,
some observations on your spec:
- Is there a good reason for representing the resource allocation to nodes using sequences rather than sets? If order is unimportant, you will probably find that your spec becomes simpler if you use sets.
- CHOOSE is deterministic, and therefore your function will always return the same result (as a function needs to do, in fact). Is that important for you or would you rather test all possible "balanced" assignments of resources to nodes?
- Nitpicks: write "pendingRes = {}" rather than "Cardinality(pendingRes) = 0", and moreover you can replace "R \intersect pendingRes" by "pendingRes" (and hence get rid of the LET expression) since pendingRes is a subset of R.
Assuming you can use sets and are interested in all possible balanced resource assignments, you could write something like
IsBalanced(reg) == \A m,n \in N : Cardinality(reg[m]) - Cardinality(reg[n]) \in {-1,0,1}
BalancedAllocations == { reg \in [N -> R] : IsBalanced(reg) }
and then write
Rebalance ==
/\ register' \in BalancedAllocations
/\ PrintT(register')
Note that while the above definitions are succinct and easy to understand, they will be expensive to evaluate for TLC because it will enumerate all functions in [N -> R] and filter out those that satisfy the condition. In general, it is a good idea to favor clarity over efficiency in formal specifications. Only when model checking becomes too much of a bottleneck, you may need to think about efficient evaluation of operator definitions.
Does this make sense?
Regards,
Stephan
P.S.: I didn't actually check any of the above using TLC. -s