Skip to content

Separate lazy search cardinality from machine-sized storage requirements #1143

Description

@isPANN

Problem and root cause

Machine representation requirements leak into mathematical search-space APIs.

BruteForceProblem::dimensions() -> Vec<usize> requires model implementations to compute and allocate dimensions before the solver can report errors. For example, SetBasis uses vec![2; self.k * self.universe_size]. A valid instance with universe_size = 2, collection = [], and k = usize::MAX panics while computing dimensions.

Meanwhile CartesianIndices stores the total remaining number of configurations in usize and implements ExactSizeIterator. That introduces an unnecessary limit: a lazy iterator can enumerate a Cartesian product whose total cardinality exceeds usize::MAX, while each individual assignment remains small.

Other implementations really do require machine-sized masks or dense tables:

  • src/rules/highlyconnecteddeletion_ilp.rs: 1u64 << n, guarded only by a debug assertion.
  • src/solvers/customized/minimum_decision_tree.rs: 1usize << n.
  • src/solvers/customized/shortest_common_superstring.rs: (1usize << n) * n.
  • src/truth_table.rs: unchecked row-count shifts.

These cases need explicit representation errors before overflowing arithmetic. Computational difficulty itself is not an error.

Required refactor

  1. Replace eager dimension-vector construction with fallible access to coordinate count and coordinate cardinality, using the existing BruteForceProblem trait:
    fn num_variables(&self) -> Result<usize, SolveError>;
    fn dimension(&self, variable: usize) -> Result<usize, SolveError>;
    Update model implementations, generated registrations, inspection callers, and tests together. Checked arithmetic must happen before constructing a derived count.
  2. Change CartesianIndices to terminate when mixed-radix increment exhausts all coordinates. Remove remaining: usize, the mandatory total-product calculation, and ExactSizeIterator. Use an honest non-exact size hint.
  3. Check sizes that the selected implementation actually needs to index or allocate. Use checked shifts/products/additions and fallible allocation at search-space and dense-table construction boundaries. Propagate existing construction/reduction/solve error categories.
  4. For native-mask or dense-table algorithms, report an explicit error when their representation cannot encode the instance. Do not pretend these algorithms support arbitrary-width masks.
  5. Route TruthTable row-count arithmetic through its shared construction path; coordinate deserialization validation with Validate TruthTable invariants during deserialization #1142.

The final design must distinguish:

  • mathematical instance validity;
  • representability of one assignment or required table;
  • total number of lazily visited assignments.

Do not require the last quantity to fit usize just to start lazy enumeration. Do not add time/memory budgets, heuristic thresholds, complexity-based rejection, saturating sizes, or fallback algorithms.

Design references

Acceptance tests

  • The SetBasis case returns a typed error without panic or an impractical allocation.
  • A Cartesian product with more than usize::MAX configurations can yield its first few assignments. Test only a short prefix; do not exhaust it.
  • Empty products, zero-cardinality coordinates, carries, and normal iterator exhaustion are correct.
  • Actual native-width shift and dense-table-size overflows return typed errors in debug and release behavior.
  • Ordinary solver results are unchanged.
  • Valid instances are not rejected based on predicted difficulty.

Run focused tests and make check. Coordinate signature migration as a direct replacement; do not keep a compatibility API. Roughly 199 production model files currently implement dimensions, so implementation must respect the repository's large-change scope confirmation rule.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions