⚡ 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:

  1. Generate all possible paths of length 3
  2. 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

Popular posts from this blog

๐Ÿง  The Search-and-Select Pattern

๐Ÿงฎ Exploring Combinatoric Calculus

๐Ÿ“ฆ v0.0.0-dev.1 — Search & AsyncSearch