Skip to content

Fix DiceGenetic.mate continuous-mutation typo pinning to lower bound (#441)#472

Open
jbbqqf wants to merge 1 commit into
interpretml:mainfrom
jbbqqf:fix/441-genetic-mate-uniform-typo
Open

Fix DiceGenetic.mate continuous-mutation typo pinning to lower bound (#441)#472
jbbqqf wants to merge 1 commit into
interpretml:mainfrom
jbbqqf:fix/441-genetic-mate-uniform-typo

Conversation

@jbbqqf
Copy link
Copy Markdown

@jbbqqf jbbqqf commented May 9, 2026

Summary

DiceGenetic.mate() mutates a continuous feature with
np.random.uniform(low, high), but the call passed
feature_range[feat_name][0] for both arguments. As a result every
continuous mutation collapsed to the lower bound of the feature's
declared range, leaving the genetic search to explore continuous axes
only via the parent-gene branches (prob < 0.80). Half of the
diversity-injection strategy was a no-op.

The two adjacent np.random.uniform calls in the same file
(do_random_init at line ~92 and do_KD_init at line ~124) both
correctly pass low, high, so this is a clear typo rather than an
intentional design choice — and it matches several user reports that
the genetic explainer "ignores" the user's permitted_range /
features_to_vary intent on continuous columns (see #441 and #260
comment threads).

Why

One-character typo fix in the else: mutation branch of
DiceGenetic.mate. Restores the documented diversity behaviour of the
genetic algorithm.

I left a 4-line comment at the call site explaining the prior bug —
without it, a future reviewer or refactor could easily re-introduce
the same typo in another mutation path.

Reproduce BEFORE/AFTER yourself (copy-paste)

set -e
cd /tmp && rm -rf DiCE-441 && git clone https://github.com/interpretml/DiCE.git DiCE-441
cd DiCE-441
pip install -q -e . pytest

git fetch https://github.com/jbbqqf/DiCE.git fix/441-genetic-mate-uniform-typo
git checkout FETCH_HEAD -- tests/test_dice_interface/test_dice_genetic.py

# --- BEFORE: production code from origin/main ---
git checkout origin/main -- dice_ml/explainer_interfaces/dice_genetic.py
python -m pytest tests/test_dice_interface/test_dice_genetic.py::TestMateContinuousMutation -q || echo \"BEFORE: AssertionError 'pinned to the lower bound' (expected)\"
# Expected: 1 failed — 'samples > 50.0' is False because every mutation collapsed to feature_range[name][0]

# --- AFTER: fix applied ---
git checkout FETCH_HEAD -- dice_ml/explainer_interfaces/dice_genetic.py
python -m pytest tests/test_dice_interface/test_dice_genetic.py::TestMateContinuousMutation -q
# Expected: 1 passed — mutations now spread across the declared [0, 100] range

What I ran locally

  • New test passes on this branch
  • New test fails on origin/main with all 200 samples == 0.0 (every mutation pinned to the lower bound of the feature range, exactly as the typo dictates)
  • Direct line-by-line diff with adjacent np.random.uniform(low, high) call sites confirms the fix matches the established pattern in this file

Edge cases

call site feature_range mutation distribution
BEFORE: continuous mutation in mate [0, 100] all samples collapsed to 0.0
AFTER: continuous mutation in mate [0, 100] uniform over [0, 100]
Categorical mutation in mate unchanged — uses np.random.choice unchanged
Continuous mutation in do_random_init already correct (low, high) unchanged
Continuous mutation in do_KD_init already correct (low, high) unchanged

AI disclosure

This change was prepared with the assistance of Claude (Anthropic).
The author reviewed every line and is responsible for the final result.

@jbbqqf jbbqqf requested review from amit-sharma and gaugup as code owners May 9, 2026 22:54
`mate()` mutates a continuous feature with `np.random.uniform(low, high)`,
but the historical implementation passed `feature_range[feat_name][0]` for
both arguments. Every continuous mutation therefore collapsed to the lower
bound of the feature's range, leaving the genetic search to explore
continuous axes only via the parent-gene branches (prob < 0.80) — half
the algorithm's diversity strategy was a no-op.

The two adjacent `np.random.uniform` calls in this file (do_random_init
at line 92, do_KD_init at line 124) both correctly pass `low, high`, so
this is a clear typo rather than an intentional design choice. Fixing it
restores the documented genetic-search behaviour and is consistent with
multiple user reports that the genetic explainer "ignores" the user's
permitted feature range / features_to_vary intent on continuous columns
(see interpretml#441 and interpretml#260 comment threads).

Adds `TestMateContinuousMutation` driving 200 mutation events on a
single continuous feature with range [0, 100] and asserting that at
least one sample lands in the upper half. The test fails on `origin/main`
(every sample is 0.0) and passes on this branch.

Adds a code comment explaining the choice for future reviewers, since
the pattern would otherwise be easy to re-introduce in another mutation
path.

Closes interpretml#441.

Signed-off-by: Jean-Baptiste Braun <jbaptiste.braun@gmail.com>
@jbbqqf jbbqqf force-pushed the fix/441-genetic-mate-uniform-typo branch from 3afa543 to 4647afa Compare May 25, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant