I have a TLA+ spec akin to the following:
CONSTANT Items
VARIABLE item
And I'd like Items
to be symmetric, and to select a single element from Items
and store it into item
.
I've been using item = CHOOSE x \in Items: TRUE
, but I learned that this breaks symmetry on Items: TLC will always select the first item from the set.
I'd like to select a single item in a way that preserves symmetry, to allow TLC to explore all states. I don't care which item we select -- only that it is one, and that it is from Items
. (Later, I need item
to be \in Items
.
While I'd prefer item
to be a single element, it would also be okay for item
to be a set of cardinality 1, so later I can check for \subseteq Items
.
It was recommended to me to replace CHOOSE
with {x \in Items: TRUE}
to preserve symmetry and have the result be \subseteq Items
, but this does not constrain the resulting set to cardinality 1.
Is there a way to ask TLA+ to give me a single item, or a set of cardinality 1, from a symmetric set of values?
I learned a bit more about TLA+/TLC since posting the question, and here's my answer:
To simply select an element from a symmetry set in the initial predicate:
item \in Items
or in an action:
item' \in Items
If you want to select an item that matches a predicate, as you can specify with CHOOSE, then this is the alternative:
item \in {x \in Items: P(x)}
This'll form a subset of Items that match the predicate, then select a single element of those.
Here's some data that shows the difference between this syntax and CHOOSE. Consider this module:
----------------------------- MODULE ChooseDemo -----------------------------
CONSTANT Items
VARIABLE item
TypeInvariant == item \in Items
Init == item = CHOOSE x \in Items: TRUE
Next == item' \in {x \in Items: x /= item}
=============================================================================
When Items
has three items:
Now consider this module:
--------------------------- MODULE SetFormingDemo ---------------------------
CONSTANT Items
VARIABLE item
TypeInvariant == item \in Items
Init == item \in {x \in Items: TRUE}
Next == item' \in {x \in Items: x /= item}
=============================================================================
When Items
has three items:
Hence, by using the set-forming syntax, TLC finds more states than it did with CHOOSE.