Make label normalization mandatory and collision-safe, and retime it for players and strategies - #965
Conversation
|
|
@tturocy one thing to confirm: As per Bullet 2, user creation requires a valid unique label. The one thing I want to confirm is the parser: it creates outcomes from file labels (can be empty/duplicate), so raise-on-duplicate there would break loading — am I right that we also want readers to accept those and generate _1/_2. Those only fit if the parser's exempt from the rule (sets labels non-enforcing, normalization after) -- is this the plan to follow? Please let me know if you want loading strict instead, I'll rewrite the test games. |
|
This is a good catch, I had mis-remembered how I implemented the normalisation. Normalisation in the loader is done after the game has been constructed, rather than as the file is read. So you're correct Our thinking when we introduced this normalisation is that there are potentially too many files out there with empty labels (in particular), which requiring unique labels will break. So we want to continue the behaviour of the loader to "unique-ify" labels. However this normalisation has to get moved now. Probably, the right way to do this will be to make a separate branch and change the timing of the normalisation, so it's being done on the raw lists of labels rather than the game objects, and we'll merge that first. Then there won't be a clash with the new |
|
Well, there's good news and bad news on the tests - it's good that it looks like our new BAGG checks are doing something, but it is puzzling that it is crashing on MacOS only (while I have tried locally on this branch on MacOS and do not have a problem...!) |
the normalize_labels / p_normalizeLabels parameter throughout the read path: ReadEfgFile, ReadNfgFile, ReadGbtFile, ReadAggFile, ReadBaggFile, ReadGame, and the pygambit read_* wrappers.
…. Actions and outcomes are deliberately *not* retimed here. This commit is self-contained and can be reverted independently of the mandatory and collision-safe normalization it builds on.
Issues closed by this PR
(normalization foundation; enforcement to follow in a later PR)
Description of the changes in this PR
Prepares the label-normalization path in the file loader for the unique-nonempty-label enforcement
planned in #861. Loading accepts files with empty or duplicate labels, with labels "unique-ified" as before.
Three self-contained commits:
Mandatory normalization. Label normalization on file read is now unconditional
(the previous opt-in parameter is removed), so every loaded game has normalized labels.
Collision-safe normalization.
NormalizeLabelsnow tracks the labels already usedin each scope and never generates a duplicate suffix, so an input like
{"x", "x", "x_1"}no longer renumbers to a second
"x_1".NormalizeLabelsis generalized to work overboth game-object containers and raw label-string lists via accessor lambdas, with a
NormalizeLabelStringshelper for the string case.Retime player/strategy normalization ahead of construction (revertable). Player and strategy labels
are normalized on the raw label lists read from the file, before the game objects are constructed,
rather than renaming objects afterwards. This is a step toward retiming normalization planned in
[ENH]: Require unique labels for game objects (within appropriate scope) #861.
Actions and outcomes are deliberately not retimed here
Both are multi-reference scopes: an infoset's actions are re-stated at each later node and
validated by
CheckInfosetActions, and outcomes are keyed by id across the whole tree via theoutcome map. Normalizing their labels at first definition makes the later raw re-statement no longer
match what was stored.
Retiming actions breaks loading when an infoset has duplicate action labels (so normalization changes
them, e.g.
{ "1" "1" }→1_1, 1_2) and is referenced at more than one node (soCheckInfosetActionsre-checks it against the raw labels) -- resulted in 8 test failures.