Skip to content

fix: FLOW2.reach() handles mixed-type conditional parameters (#903)#1557

Merged
thinkall merged 2 commits into
microsoft:mainfrom
immu4989:flaml-fix-flow2-mixed-type-reach
Jun 11, 2026
Merged

fix: FLOW2.reach() handles mixed-type conditional parameters (#903)#1557
thinkall merged 2 commits into
microsoft:mainfrom
immu4989:flaml-fix-flow2-mixed-type-reach

Conversation

@immu4989

@immu4989 immu4989 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Why are these changes needed?

FLOW2.reach in flaml/tune/searcher/flow2.py builds a numeric delta array by subtracting two incumbents element-wise:

delta = np.array([incumbent1[key] - incumbent2.get(key, np.inf) for key in self._tunable_keys])

When a search space contains a conditional tune.choice whose branches yield values of different types — e.g. one branch returns the literal string 'None' and another returns an int from tune.qrandint (the exact pattern from #903) — two FLOW2 instances can hold incumbents whose values are different types for the same key. The subtraction then raises:

TypeError: unsupported operand type(s) for -: 'float' and 'str'

This was reported by @bbudescu in #903 (2023-01); @sonichi's suggested fix in that thread is to wrap the line in try/except TypeError and return False. This PR implements exactly that. Returning False is the right semantics here — a string-vs-numeric incumbent comparison is structurally not "within step" of each other, so reporting "cannot reach" is correct.

Verified

  • Repro from Conditional parameter flow2 crash #903 reproduces cleanly on current main via FLOW2.reach() (TypeError: unsupported operand type(s) for -: 'float' and 'str').
  • After the fix, reach() returns False for the mixed-type case (no crash).
  • A focused regression test was added in test/tune/test_searcher.py::test_flow2_reach_mixed_type_incumbents — verified to fail on main without the fix and pass with it.
  • Existing tests in test/tune/test_searcher.py continue to pass.
  • pre-commit run --files flaml/tune/searcher/flow2.py test/tune/test_searcher.py — all hooks pass.

Related issue number

Closes #903

Checks

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a crash in FLOW2.reach() when conditional/choice parameters produce incumbents with mixed types (e.g., numeric vs string), by treating such comparisons as “not reachable” instead of raising a TypeError. This improves robustness of the FLOW2 local search logic in flaml/tune/searcher/flow2.py for hierarchical/conditional search spaces.

Changes:

  • Wrap the incumbent delta computation in FLOW2.reach() with a try/except TypeError and return False on mixed-type subtraction.
  • Add a regression test ensuring reach() returns False (and does not crash) for mixed-type incumbents.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
flaml/tune/searcher/flow2.py Prevents FLOW2.reach() from crashing on mixed-type incumbent comparisons by returning False on TypeError.
test/tune/test_searcher.py Adds a regression test covering the mixed-type incumbent case reported in #903.

Comment thread test/tune/test_searcher.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@thinkall thinkall left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you very much for the PR, @immu4989 !

@thinkall thinkall merged commit 40b20ac into microsoft:main Jun 11, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conditional parameter flow2 crash

4 participants