Skip to content

Fix hierarchical refinement fall-through into linear search - #166

Open
shaobo-he wants to merge 1 commit into
masterfrom
fix/hierarchical-refinement-fallthrough
Open

Fix hierarchical refinement fall-through into linear search#166
shaobo-he wants to merge 1 commit into
masterfrom
fix/hierarchical-refinement-fallthrough

Conversation

@shaobo-he

@shaobo-he shaobo-he commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

When Z3-based variable refinement is disabled, Corral’s hierarchical refinement search was not used as the final refinement algorithm. Instead it:

  1. ran hierarchical search and obtained a valid tracked set ec;
  2. stored ec in refinementState.trackedTokens;
  3. fell through into the older linear refinement search;
  4. overwrote the hierarchical result with the linear result.

Corral therefore paid for hierarchical search plus linear search, and kept only the linear result.

This behavior has existed since the initial Corral check-in (2013) and is present on upstream master.

Root cause

In GeneralRefinementScheme.doRefinement():

if (useHierarchicalSearch)
{
    var ec = refinementLoop(...);
    refinementState.trackedTokens = ec;
}
// no return / else — falls through
var trackedVars = new HashSet<>(initialTrackedTokens);  // restarts from scratch
// ... linear loop ...
refinementState.trackedTokens = trackedVars;  // overwrites hierarchical result

The linear phase always restarts from initialTrackedTokens, not from ec. Hierarchical results were only used for a debug progress assert before being discarded.

When the fall-through occurs

useZ3Search == true
  → Z3 refinement → return   (default sequential path; no fall-through)

useZ3Search == false && useHierarchicalSearch == true
  → hierarchical → [was: linear overwrite] → now: return

useZ3Search == false && useHierarchicalSearch == false
  → linear only

useZ3Search is forced off when:

  • VariableSlicing.EncounteredParallelAssignment is true; or
  • the concurrent path constructs GeneralRefinementScheme with z3search=false.

Evidence this was unintentional

  • Linear refinement does not seed from the hierarchical result.
  • Historical doRefinement1() (labeled “For CADE 2011”) runs linear, hierarchical, and Z3 independently as timing alternatives and does not compose them.

Change

Two lines after hierarchical assigns trackedTokens = ec:

timeTaken = (DateTime.Now - startTime);
return;

Test plan

  • Default path (Z3 when available): 49/49 regression pass
  • Forced hierarchical path: outcomes match pre-fix (SAFE/UNSAFE), 49/49
  • Parallel-assign cases (015/ParAssign1, ParAssign2): outcomes preserved; path queries drop (e.g. 12→9, 20→14)
  • Across 41 refinement invocations under forced hierarchical: hierarchical and linear tracked-set sizes always matched (fall-through changed cost, not sets, on this suite)

@shaobo-he
shaobo-he requested a review from akashlal August 11, 2026 04:02
When Z3 refinement is disabled, hierarchical search computed a valid
tracked set then fell through into linear search and overwrote the
result. Return after hierarchical so the two algorithms are mutually
exclusive.
@shaobo-he
shaobo-he force-pushed the fix/hierarchical-refinement-fallthrough branch from 0b0d829 to 2b64dfe Compare August 11, 2026 04:03
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.

1 participant