Skip to content

Refactor memoized knapsack implementation to remove global state#14535

Open
nickzerjeski wants to merge 4 commits intoTheAlgorithms:masterfrom
nickzerjeski:fix-14464-memoized-knapsack
Open

Refactor memoized knapsack implementation to remove global state#14535
nickzerjeski wants to merge 4 commits intoTheAlgorithms:masterfrom
nickzerjeski:fix-14464-memoized-knapsack

Conversation

@nickzerjeski
Copy link
Copy Markdown

Summary

This PR refactors mf_knapsack() in dynamic_programming/knapsack.py to remove the global DP table and use functools.lru_cache for memoization.

What Changed

  • Replaced global-state recursion (global f) with an internal cached solver closure.
  • Kept mf_knapsack(i, wt, val, j) public API intact.
  • Added explicit type hints to the updated functions.
  • Added doctests for mf_knapsack().
  • Removed obsolete f initialization from the __main__ example.
  • Fixed knapsack() return indexing to use w directly (dp[n][w]) for correctness and clarity.

Why

Issue #14464 requests a cleaner memoized knapsack implementation without global mutable state, with improved readability, typing, and doctests.

Using lru_cache:

  • avoids implicit shared mutable state,
  • makes the function self-contained and reusable,
  • preserves the same 0/1 knapsack recurrence.

Validation

  • python -m doctest -v dynamic_programming/knapsack.py (pass)
  • pytest -q knapsack/tests/test_knapsack.py could not run in this environment (pytest not installed)
  • uv run pytest -q knapsack/tests/test_knapsack.py could not run in this environment (uv not installed)

Issue

Closes #14464

Copilot AI review requested due to automatic review settings April 11, 2026 14:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the memoized 0/1 knapsack implementation to remove reliance on global mutable state by using an lru_cache-backed solver closure, while keeping the public mf_knapsack(i, wt, val, j) API.

Changes:

  • Replaced global DP-table memoization in mf_knapsack() with a per-call lru_cache-memoized inner solver and added input validation + doctests.
  • Fixed knapsack() to return dp[n][w] (avoids incorrect/undefined w_ usage).
  • Added/adjusted type hints for knapsack-related helpers and simplified the __main__ example by removing obsolete global table initialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +11 to +14
from functools import lru_cache


def mf_knapsack(i: int, wt: list[int], val: list[int], j: int) -> int:
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mf_knapsack() annotations are more restrictive than the implementation: it only relies on len() + indexing and immediately converts wt/val to tuples, so tuples (and other Sequence types) work too. Consider widening the types to collections.abc.Sequence[int] to match actual supported inputs (this pattern is already used elsewhere, e.g. dynamic_programming/max_subarray_sum.py:16).

Suggested change
from functools import lru_cache
def mf_knapsack(i: int, wt: list[int], val: list[int], j: int) -> int:
from collections.abc import Sequence
from functools import lru_cache
def mf_knapsack(i: int, wt: Sequence[int], val: Sequence[int], j: int) -> int:

Copilot uses AI. Check for mistakes.

return dp[n][w_], dp
return dp[n][w], dp

Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

knapsack_with_example_solution() validates that wt/val are either lists or tuples, but the updated signature still annotates them as list. Consider annotating them as collections.abc.Sequence[int] (or list[int] | tuple[int, ...]) so the type hints align with the function's documented/validated inputs (see dynamic_programming/max_subarray_sum.py:16 for the existing Sequence[...] pattern).

Copilot uses AI. Check for mistakes.
@algorithms-keeper algorithms-keeper bot added the tests are failing Do not merge until tests pass label Apr 11, 2026
@algorithms-keeper algorithms-keeper bot removed the tests are failing Do not merge until tests pass label Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor memoized knapsack implementation to remove global state

2 participants