Skip to content

refactor: add search helpers and rename parameters#8

Open
dhalmazna wants to merge 6 commits intofeat/segment-and-hyperpixel-scoringfrom
feat/algorithm-utils
Open

refactor: add search helpers and rename parameters#8
dhalmazna wants to merge 6 commits intofeat/segment-and-hyperpixel-scoringfrom
feat/algorithm-utils

Conversation

@dhalmazna
Copy link
Copy Markdown
Collaborator

@dhalmazna dhalmazna commented Mar 14, 2026

Context:
This PR refactors the hyperpixel scoring utilities to directly accept abstract sets instead of lists, improving type safety and removing redundant conversions. It also adds the is_terminal function.

What was added / changed:

  • algorithm/search_helpers.py: Introduced shared utilities for search algorithms:
    • is_terminal: A state-check helper to determine if a search path has reached its maximum length or exhausted its frontier.
  • Refactoring and Naming:
    • Updated calculate_hyperpixel_deltas to accept Sequence[Set[int]].
    • Standardized terminology by renaming segments to region across ImageGraph and scoring utilities.
    • Optimized create_surrogate_dataset by removing unnecessary sorting and leveraging Set abstractions.

Related Task:
XAI-29

@dhalmazna dhalmazna self-assigned this Mar 14, 2026
Copilot AI review requested due to automatic review settings March 14, 2026 12:13
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 14, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 67e0f19b-105b-4231-ac7b-cb61f7ceb5a0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title mentions 'add search helpers' which aligns with the new search_helpers.py module, and 'rename parameters' which covers the parameter renames in graph.py and segmentation.py. However, it misses the re-exports added to init.py and uses generic 'refactor' framing rather than highlighting the primary feature addition.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/algorithm-utils

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request lays the groundwork for upcoming search algorithms by centralizing common logic and low-level graph operations. It aims to keep the main algorithm implementations clean and optimized by providing dedicated utility modules for tasks such as efficient bitmask manipulation and batched evaluation of segment masks, ensuring a robust and scalable foundation.

Highlights

  • New Search Helper Utilities: Introduced ciao/algorithm/search_helpers.py to house shared functions for Monte Carlo Tree Search (MCTS) and Monte Carlo Graph Search (MCGS) algorithms. This includes evaluate_masks for batched mask evaluation and is_terminal for fast state-checking.
  • Expanded Bitmask Graph Primitives: Enhanced ciao/algorithm/bitmask_graph.py with new low-level bitwise operations. Added functions for node mutation (add_node, remove_node, has_node), random selection (pick_random_set_bit), and a random walk sampler (sample_connected_superset) for Monte Carlo rollouts.
  • Module Export Updates: The ciao/algorithm/__init__.py file was updated to export all newly added utility functions, making them accessible from the top-level ciao.algorithm package.
Changelog
  • ciao/algorithm/init.py
    • Imported new functions from bitmask_graph module: add_node, has_node, mask_to_ids, pick_random_set_bit, remove_node, sample_connected_superset.
    • Imported new functions from search_helpers module: evaluate_masks, is_terminal.
    • Exported all newly imported functions via the __all__ list.
  • ciao/algorithm/bitmask_graph.py
    • Imported the random module.
    • Added mask_to_ids function to convert an integer bitmask to a list of segment indices.
    • Added has_node function to efficiently check if a specific node is present in a bitmask.
    • Added add_node function to set a specific bit in a mask, effectively adding a node.
    • Added remove_node function to clear a specific bit in a mask, effectively removing a node.
    • Added pick_random_set_bit function to select a random set bit from a mask without allocating a list.
    • Added sample_connected_superset function for generating a connected superset via a random walk expansion.
    • Updated the module docstring to reflect its current state as providing primitives.
  • ciao/algorithm/search_helpers.py
    • Created a new file to house shared utilities for MCTS and MCGS algorithms.
    • Imported necessary modules: numpy, torch, get_frontier, iter_bits, ModelPredictor, and calculate_hyperpixel_deltas.
    • Added is_terminal function to determine if a search state is terminal based on maximum depth or an empty frontier.
    • Added evaluate_masks function to compute class score deltas for a list of segment masks in a batched manner, including validation for positive integer masks.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a solid set of foundational utilities for search algorithms and bitmask operations. The new functions are well-documented and the separation into bitmask_graph.py and search_helpers.py is logical. My review focuses on improving consistency, efficiency, documentation accuracy, and robustness. I've suggested a more efficient implementation for mask_to_ids, a correction to a docstring, a robustness improvement for sample_connected_superset, and a change to ensure the new mask_to_ids utility is used consistently.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds foundational utilities to support upcoming Monte Carlo search algorithms by centralizing common terminal-state checks, batched mask evaluation, and extending bitmask graph primitives.

Changes:

  • Added ciao/algorithm/search_helpers.py with is_terminal and evaluate_masks for shared MCTS/MCGS logic.
  • Extended ciao/algorithm/bitmask_graph.py with node mutation helpers, random set-bit selection, and a connected-superset sampler.
  • Re-exported the new utilities from ciao/algorithm/__init__.py.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
ciao/algorithm/search_helpers.py New shared helpers for terminal checks and batched reward evaluation.
ciao/algorithm/bitmask_graph.py New bitmask primitives and sampling utilities for graph-based expansions.
ciao/algorithm/init.py Exposes new utilities at the package level via imports and __all__.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +97 to +124
def sample_connected_superset(
base_mask: int,
target_length: int,
adj_masks: tuple[int, ...],
used_mask: int,
) -> int:
"""Sample a connected superset via random walk expansion.

IMPORTANT: This is NOT a uniform sampler over all connected supersets.
The distribution is biased towards segments discovered early and
depends on graph topology. This bias is acceptable for Monte Carlo
estimation in the parent algorithm.

Args:
base_mask: Starting set (must be non-empty and connected)
target_length: Desired size of the superset
adj_masks: Adjacency bitmasks for neighbor lookups
used_mask: Global exclusion mask (segments that must not be added)

Returns:
Bitmask of connected superset containing base_mask
"""
mask = base_mask

while mask.bit_count() < target_length:
frontier = get_frontier(mask, adj_masks, used_mask)
if frontier == 0:
break
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This checking would be too computationally expensive. The mask will be always connected because of the way it is created - we always add a neighbor from the frontier.

@dhalmazna dhalmazna force-pushed the feat/algorithm-utils branch 2 times, most recently from dd0ad92 to b2ab7f8 Compare March 17, 2026 13:38
@dhalmazna dhalmazna force-pushed the feat/segment-and-hyperpixel-scoring branch from f30a530 to 2c6a6ab Compare March 17, 2026 13:46
@dhalmazna dhalmazna marked this pull request as draft March 23, 2026 06:50
@dhalmazna dhalmazna force-pushed the feat/algorithm-utils branch from b2ab7f8 to 4282be2 Compare March 23, 2026 07:21
@dhalmazna dhalmazna marked this pull request as ready for review March 23, 2026 07:24
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ciao/algorithm/search_helpers.py (1)

14-23: Consider enforcing a positive max_depth contract.

At Line 21, max_depth <= 0 makes states terminal immediately. A fast-fail guard can prevent silent misuse.

Proposed guard
 def is_terminal(
     current_region: frozenset[int],
     image_graph: ImageGraph,
     used_segments: frozenset[int],
     max_depth: int,
 ) -> bool:
     """Check if state is terminal (max depth or no frontier)."""
+    if max_depth <= 0:
+        raise ValueError(f"max_depth must be positive, got {max_depth}.")
     return len(current_region) >= max_depth or not image_graph.get_frontier(
         current_region, used_segments
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ciao/algorithm/search_helpers.py` around lines 14 - 23, The is_terminal
function should enforce a positive max_depth to avoid silently treating all
states as terminal when max_depth <= 0; update is_terminal to validate the
max_depth parameter (e.g., raise ValueError or assert) at the start of the
function and include a clear message referencing max_depth, leaving the existing
logic that checks len(current_region) >= max_depth and image_graph.get_frontier
unchanged; locate the validation in the is_terminal definition so callers
receive immediate feedback if they pass non-positive depths.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ciao/algorithm/search_helpers.py`:
- Around line 14-23: The is_terminal function should enforce a positive
max_depth to avoid silently treating all states as terminal when max_depth <= 0;
update is_terminal to validate the max_depth parameter (e.g., raise ValueError
or assert) at the start of the function and include a clear message referencing
max_depth, leaving the existing logic that checks len(current_region) >=
max_depth and image_graph.get_frontier unchanged; locate the validation in the
is_terminal definition so callers receive immediate feedback if they pass
non-positive depths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f53bc35-b679-4ef9-a881-88ca421e97d5

📥 Commits

Reviewing files that changed from the base of the PR and between d797ff7 and 4282be2.

📒 Files selected for processing (4)
  • ciao/algorithm/__init__.py
  • ciao/algorithm/graph.py
  • ciao/algorithm/search_helpers.py
  • ciao/data/segmentation.py

@dhalmazna dhalmazna force-pushed the feat/algorithm-utils branch from 4282be2 to a53863c Compare March 25, 2026 08:08
@dhalmazna dhalmazna changed the title feat: add foundational search utilities and extend bitmask primitives feat: add foundational search utilities Mar 25, 2026
@dhalmazna dhalmazna marked this pull request as draft March 25, 2026 08:45
Copy link
Copy Markdown
Member

@Adames4 Adames4 left a comment

Choose a reason for hiding this comment

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

Please re-request review when PR is ready, thanks

@dhalmazna dhalmazna changed the title feat: add foundational search utilities refactor: unify hyperpixel scoring and add search helpers Mar 25, 2026
@dhalmazna dhalmazna changed the title refactor: unify hyperpixel scoring and add search helpers refactor: add search helpers and rename parameters Mar 25, 2026
@dhalmazna dhalmazna marked this pull request as ready for review March 25, 2026 09:57
@dhalmazna dhalmazna requested a review from Adames4 March 25, 2026 09:58
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.

3 participants