Skip to content

Make reduction execution fail explicitly and keep declared capabilities executable #1117

Description

@isPANN

Background

The reduction model has a sound high-level shape: a rule constructs a target problem, witness reductions map target configurations back to source configurations, and aggregate reductions map final target values back to source values.

Several runtime details currently weaken that contract. They rely on recovered panics, fabricated configurations, or capability metadata that can disagree with the available executor. The panic-probing and capability behavior described below are present on the branch for PR #1083; the extraction behavior also exists in the existing rule implementations.

This is one runtime-contract hardening issue. The three objectives may be delivered together in PR #1083 because they govern the same registered-reduction execution boundary. The extract_solution signature change necessarily causes a repository-wide mechanical migration of rule implementations, callers, and tests; that migration is part of this issue rather than a general rewrite.

Problem 1: normal variant probing uses panic and recovery

ReductionGraph::compute_source_size iterates every reduction entry with the same source problem name and calls each source_size_fn. A function generated for a different variant fails its downcast and panics. catch_reduction catches the panic and installs a thread-local panic-hook silencer so the expected panic does not appear on stderr.

Current control flow:

try an executor for a different variant
→ downcast panic
→ catch panic
→ suppress panic output
→ treat the entry as not applicable

A type or variant mismatch is normal dispatch state and must be checked before invocation. Panics must remain reserved for actual defects.

Relevant code:

  • src/rules/graph.rs: compute_source_size
  • src/rules/pareto.rs: catch_reduction

Problem 2: extraction failures fabricate all-zero source configurations

ReductionResult::extract_solution returns only Vec<usize>, so a rule cannot report malformed or non-extractable target input. Multiple rules return vec![0; n] as a failure marker, including SAT to NAE-SAT and several Hamiltonian reductions.

This makes these states indistinguishable:

a legitimate all-zero source configuration
extraction failed and fabricated an all-zero configuration

Representative locations can be found with:

rg 'return (Ok\()?vec!\[0' src/rules

Extraction failure must be explicit. Audit each zero fallback: replace genuine failure markers with an error; retain a zero configuration only where it is the mathematically defined mapping and add a semantic test proving that fact.

Problem 3: capability metadata can disagree with executable behavior

ReductionEntry stores executor functions and capability booleans independently:

reduce_fn: Option<ReduceFn>
reduce_aggregate_fn: Option<AggregateReduceFn>
capabilities: EdgeCapabilities

An entry can therefore advertise a mode without providing a valid executor for it. In addition, the #[reduction] macro currently assigns EdgeCapabilities::both() when the source and target base names are equal. Aggregate execution then uses WitnessBackedIdentityAggregateStep, which returns the target JSON value unchanged.

A shared base name does not prove that source and target aggregate value types or meanings are identical. Identity aggregate mapping must be backed by a compile-time value-type equality guarantee or by an explicit aggregate executor.

Relevant code:

  • problemreductions-macros/src/lib.rs: same-name capability inference
  • src/rules/registry.rs: ReductionEntry and EdgeCapabilities
  • src/rules/graph.rs: WitnessBackedIdentityAggregateStep

Objectives

Variant dispatch

  • Select source_size_fn by the exact registered source name and variant before calling it.
  • Remove panic-and-recover behavior used for ordinary variant mismatch.
  • Do not silence or swallow genuine reduction panics.
  • Add a regression with at least two variants sharing a base name that proves only the exact variant executor is invoked.

Solution extraction

  • Give extraction an explicit failure result rather than encoding failure as a configuration.
  • Update CLI, bundle, dynamic-chain, and rule callers to propagate a useful error.
  • Remove failure-marker zero vectors from the audited rules.
  • Add tests distinguishing a legitimate zero configuration from extraction failure.

Capability integrity

  • Make executable functions the source of truth for supported modes, or validate every registry entry before graph construction.
  • Reject inconsistent entries such as aggregate=true without an aggregate executor or a type-safe identity mapping.
  • Remove same-base-name as sufficient evidence for identity aggregate mapping.
  • Add negative tests that intentionally construct inconsistent entries and verify rejection.

Verification

rg "catch_reduction|catch_unwind" src/rules
rg 'return (Ok\()?vec!\[0' src/rules
make check

The first command must no longer find panic recovery used as normal reduction dispatch. The second may only find zero configurations with documented mathematical meaning, never failure markers. make check must pass after each scoped PR.

Scope control

  • The three objectives may be delivered together in PR Symbolic growth, exact Pareto path search, and deterministic solver backends #1083; do not split them solely for issue bookkeeping.
  • Keep the combined change limited to exact variant dispatch, executor-backed capability integrity, explicit extraction failure, and the mechanical caller/test migration required by the extraction API.
  • Do not combine this work with a general graph.rs file split.
  • Do not add compatibility wrappers around the old failure behavior.
  • Replace the old behavior and delete the superseded panic hooks, silent fallbacks, and redundant capability state.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions