Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dpgen2/exploration/task/caly_task_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def set_params(
for temp in name_of_atoms[1:]:
overlap = overlap & set(temp)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things go wrong on this line, and they are the same root cause.

It rejects valid configurations. Since overlap ⊆ atom_choices always holds, this fires whenever a sub-list equals the global intersection. That is the shape of any "narrow the choices as you go" config, and of every single-sub-list config. Verified against the shipped API:

[["Li"]]                             before: SUCCESS   after: ValueError
[["Li","Na"]]                        before: SUCCESS   after: ValueError
[["Li","H"],["La","H"],["H"]]        before: ok       after: ValueError   (Li, La, H is valid)

The example in the error message two lines below is itself valid. [[A,B,C],[B,C],[C]] assigns C→B→A. I ran the real equivalent, [["Li","Na","K"],["Na","K"],["K"]]: at d3ca156~1 it returned ['Li','Na','K']; at this head it raises. So the message has documented a legal config as forbidden since #217, and this change is what makes the code enforce that. Whatever predicate you land on, that sentence needs to go or be corrected — it is the only user-facing description of the rule, and it is wrong.

It still hangs on genuinely impossible configs. [["Li"],["Li"],["Na","K"]] has an empty global intersection, so no sub-list equals it, the guard stays silent, and the loop spins forever — I killed it at 8 seconds, exit 137. That is the same failure #356 reports, one sub-list larger. 45 of 399 swept configs behave this way.

Hall's condition is the exact test; see the review body for a drop-in that I verified has zero mismatches against exhaustive search. Whichever way you go, it would be worth putting the offending name_of_atoms and the computed intersection into the message — as written it prints neither, so a user cannot tell which sub-list tripped it.

if any(map(lambda s: (set(s) - overlap) == 0, name_of_atoms)):
if any(not (set(atom_choices) - overlap) for atom_choices in name_of_atoms):
raise ValueError(
f"Any sub-list should not equal with intersection, e.g. [[A,B,C], [B,C], [C]] is not allowed."
)
Expand Down
12 changes: 12 additions & 0 deletions tests/exploration/test_make_task_group_from_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,15 @@ def test_make_caly_input(self):
def test_caly_task_group(self):
tgroup = make_calypso_task_group_from_config(self.config)
self.assertTrue(isinstance(tgroup, CalyTaskGroup))

def test_rejects_impossible_random_atom_choices(self):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[["Li"],["Li"]] happens to be a case where the wrong rule and the right rule agree, so this test cannot tell them apart. I patched three different predicates into the guard and ran only this test:

PR's rule  (sub-list == global intersection)        PASSED
Hall's condition (correct)                          PASSED
"raise iff any two sub-lists are identical" (wrong)  PASSED

All three. So it would not catch a wrong fix, which is the thing worth catching here.

Separately: if the guard ever regresses, this test hangs rather than fails. I reverted the predicate to the pre-PR always-false form and ran it under timeout -k 2 15:

Terminated
EXIT_CODE=124

No pytest verdict at all — assertRaisesRegex is wrapping a call that enters an unbounded while True. A wedged CI job is a worse signal than a red one.

To be fair to it, the test does pin something real: that some guard fires before the retry loop for this input. Three additions would make it discriminating and safe:

  • a positive case that must succeed — [["Li","Na","K"],["Na","K"],["K"]], or just [["Li"]] — which fails today;
  • a true negative with an empty intersection — [["Li"],["Li"],["Na"]] — which currently hangs;
  • and asserting on the predicate directly, or adding a timeout, so a regression reports instead of wedging.

"""Fail before random selection when unique choices are impossible."""
config = {
"name_of_atoms": [["Li"], ["Li"]],
"numb_of_atoms": [10, 10],
"numb_of_species": 2,
"distance_of_ions": [[1.0, 1.0], [1.0, 1.0]],
}

with self.assertRaisesRegex(ValueError, "intersection"):
make_calypso_task_group_from_config(config)