⚡ Early vs. Late Restriction
⚡ Early vs. Late Restriction in Combinatorial Search
One of the core design strengths of @fizzwiz/fluent — and by extension @fizzwiz/search — is the ability to optimize combinatorial search via early restriction of the search space.
This distinction may look subtle, but its impact on performance can be dramatic.
๐ง The Problem
Imagine generating all sorted paths of length 3 from the items [0, 1], with repetitions.
A naive approach would:
- Generate all possible paths of length 3
- Filter out the unsorted ones
This works — but performs far more work than necessary.
With @fizzwiz/fluent, you can reject invalid paths immediately, before their descendants are ever constructed.
⚙️ Early vs. Late Restriction
Side-by-side comparison:
const
// Returns a `What` of paths without eagerly building arrays
space = Each.each([0, 1], [0, 1], [0, 1]),
// Predicate: enforce ascending order
predicate = path => !path.parent || path.parent.last <= path.last,
// ✅ Early restriction: discards invalid partial paths immediately
earlier = new Search()
.from(new Path())
.through(space.which(predicate, true)) // restricts the search space
.via(new ArrayQueue()),
// ❌ Late restriction: filters only after full paths are generated
latter = new Search()
.from(new Path())
.through(space)
.via(new ArrayQueue())
.which(predicate); // restricts the result
Both approaches produce the same final set of valid paths, but the work done differs drastically.
๐งช Same Results, Very Different Cost
- ⚡ Early restriction prevents combinatorial explosion by stopping invalid paths early.
- ๐ Late restriction wastes time constructing and inspecting doomed paths.
For deep, recursive, or unbounded searches, this difference often determines whether a solution is tractable at all.
๐ฏ Why This Matters
Early restriction aligns the algorithm with human reasoning:
As soon as something is clearly wrong, stop exploring it.
By defining a cartesian product formally without ever materializing it, and adopting a fluent syntax for specializing a general pattern to a specific intent, you mirror the same flexibility used in human reasoning. As a result, your code becomes:
- Faster
- More expressive
- Easier to reason about
— @fizzwiz ✨
Comments
Post a Comment