GreedySlice

GreedySlice selects items by value density (score per token), greedily filling the budget from highest-density items first.

Overview

GreedySlice is the simplest and fastest slicer strategy. It computes a “value density” for each item — the ratio of relevance score to token cost — then iterates items in descending density order, including each item if it fits within the remaining budget. Zero-token items have infinite density and are always included.

This is the fractional knapsack heuristic applied to a 0/1 selection problem. It does not guarantee optimal selection (the KnapsackSlice provides that), but it is fast and produces good results in practice.

Algorithm

GREEDY-SLICE(scoredItems, budget):
    if length(scoredItems) = 0 or budget.targetTokens <= 0:
        return []

    // Step 1: Compute value densities
    densities <- new array of (density: float64, index: integer) of length(scoredItems)
    for i <- 0 to length(scoredItems) - 1:
        tokens <- scoredItems[i].item.tokens
        if tokens = 0:
            densities[i] <- (MAX_FLOAT, i)
        else:
            densities[i] <- (scoredItems[i].score / tokens, i)

    // Step 2: Sort by density descending, tiebreak by index ascending
    STABLE-SORT(densities, by density descending, then by index ascending)

    // Step 3: Greedy fill
    remaining <- budget.targetTokens
    selected <- empty list

    for i <- 0 to length(densities) - 1:
        originalIndex <- densities[i].index
        item <- scoredItems[originalIndex].item
        tokens <- item.tokens

        if tokens = 0:
            APPEND(selected, item)
        else if tokens <= remaining:
            APPEND(selected, item)
            remaining <- remaining - tokens

    return selected

Value Density

Value density measures how much relevance score an item provides per token consumed:

density = score / tokens
  • Items with tokens = 0 have density MAX_FLOAT (the largest representable finite double), ensuring they sort first and are always included. Among zero-token items, all share the same density MAX_FLOAT. The sort tiebreak is index only — score values are irrelevant for zero-token items.
  • Items with high scores and low token counts are preferred over items with moderate scores and high token counts.

Deterministic Tie-Break Contract

When two items have equal value density, the item with the lower original index in the input list MUST be preferred (original-index ascending). This is achieved either by using a stable sort or by including the original index as an explicit secondary sort key (density descending, then original index ascending).

This contract guarantees that GreedySlice produces identical output for identical inputs across repeated invocations. Budget-simulation methods (GetMarginalItems, FindMinBudgetFor) depend on this determinism to produce meaningful diff and binary-search results.

Among zero-token items — all sharing density MAX_FLOAT — score values MUST NOT affect relative order. The tiebreak is original index only.

Since the input is pre-sorted by score descending (from the Sort stage), this original-index tiebreaking preserves score order among equal-density items as a natural consequence.

Edge Cases

ConditionResult
Empty scoredItemsEmpty list
budget.targetTokens <= 0Empty list
All items are zero-tokenAll items selected
Single item fits within budgetThat item is selected
Single item exceeds budgetEmpty list (only zero-token items, if any)
All items exceed budget individuallyOnly zero-token items are selected
All items fit within budgetAll items selected

Complexity

  • Time: O(N log N) — dominated by the sort. The greedy fill pass is O(N).
  • Space: O(N) for the density array.

Conformance Notes

  • The density for zero-token items MUST be treated as the maximum possible value, ensuring they are always sorted first and always included.
  • Among zero-token items, tiebreaking is by original index only; score values MUST NOT affect the relative order of zero-token items.
  • The sort MUST use original-index-ascending tiebreaking for equal densities. Given items A (density 0.5, index 0) and B (density 0.5, index 3), A must precede B. This is the deterministic tie-break contract that budget simulation depends on.
  • Items that do not fit (tokens > remaining) are skipped, not deferred. The algorithm makes a single pass through the sorted densities — it does not backtrack or attempt smaller items after skipping a large one.
  • The output list order is determined by the greedy iteration order (density-descending), not the original input order. The Place stage handles final ordering.