-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #415 from yashksaini-coder/fix-414
Feature: 🎸 Enhance + Update + Docs for Memoization
- Loading branch information
Showing
19 changed files
with
412 additions
and
367 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Memoisation Module | ||
|
||
## Overview | ||
|
||
The **Memoisation** module is a comprehensive collection of mathematical and algorithmic functions optimized with memoization techniques to significantly enhance performance by caching previously computed results. This approach is particularly beneficial for functions that involve expensive recursive calls, such as those commonly found in combinatorial mathematics, dynamic programming, and other computationally intensive applications. By leveraging memoization, the module reduces the computational overhead of repetitive calculations, leading to substantial improvements in execution speed and efficiency. | ||
|
||
## Features | ||
|
||
- **Memoizer Class**: A class-based memoization decorator designed to cache function results based on input arguments. This allows for the efficient reuse of previously computed values, reducing the need for redundant calculations. The Memoizer Class is a versatile tool that can be applied to a wide range of functions, making it an essential component of the module. | ||
- **Combinatorial Calculations**: The module includes optimized functions for computing combinations efficiently using memoization. This is particularly useful for problems involving permutations, combinations, and other combinatorial calculations that can be computationally expensive without memoization. | ||
- **Mathematical Functions**: The module provides a suite of mathematical functions that have been optimized using memoization techniques: | ||
- **Factorial**: Calculate the factorial of a number with caching. This function leverages memoization to store previously computed factorials, ensuring that subsequent calculations are performed efficiently. | ||
- **Fibonacci**: Compute Fibonacci numbers efficiently. The Fibonacci function utilizes memoization to cache previously computed values, reducing the computational complexity of calculating Fibonacci numbers. | ||
- **Longest Common Subsequence (LCS)**: Determine the length of the LCS between two strings. This function employs memoization to cache intermediate results, making it more efficient than traditional recursive approaches. | ||
- **Knapsack Solver**: Solve the classic knapsack problem using memoization. The Knapsack Solver function leverages memoization to cache solutions to subproblems, reducing the computational overhead of solving this complex problem. | ||
|
||
## Usage and Instructions | ||
|
||
To utilize the Memoisation module effectively, follow these steps: | ||
|
||
1. **Installation**: Ensure you have Python 3.6 or later installed. Clone the repository and navigate to the project directory. | ||
2. **Importing the Module**: Import the Memoisation module in your Python script or project using `import memoisation`. | ||
3. **Function Usage**: Use the provided functions as you would any other Python function. For example, to calculate the factorial of a number, use `memoisation.factorial(number)`. | ||
4. **Memoizer Class**: To apply memoization to a custom function, use the `@memoisation.memoizer` decorator. This will enable caching of function results based on input arguments. | ||
|
||
By following these instructions and leveraging the features of the Memoisation module, you can significantly improve the performance of your Python applications that involve computationally intensive mathematical and algorithmic operations. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import logging | ||
from dataclasses import dataclass, field | ||
from typing import Dict, Tuple | ||
|
||
logging.basicConfig(level=logging.INFO) | ||
logger = logging.getLogger(__name__) | ||
|
||
@dataclass | ||
class Memoizer: | ||
cache: Dict[Tuple, int] = field(default_factory=dict) | ||
|
||
def memoize(self, func): | ||
def wrapper(*args): | ||
try: | ||
if args in self.cache: | ||
logger.info(f"Fetching from cache for args: {args}") | ||
return self.cache[args] | ||
result = func(*args) | ||
self.cache[args] = result | ||
logger.info(f"Caching result for args: {args}") | ||
return result | ||
except Exception as e: | ||
logger.error(f"Error in Memoizer: {e}") | ||
raise | ||
return wrapper | ||
|
||
@dataclass | ||
class CombinatorialCalculator: | ||
memoizer: Memoizer = field(default_factory=Memoizer) | ||
|
||
@staticmethod | ||
def combination(n: int, k: int) -> int: | ||
if k > n: | ||
return 0 | ||
if k == 0 or k == n: | ||
return 1 | ||
return CombinatorialCalculator.combination(n-1, k-1) + CombinatorialCalculator.combination(n-1, k) | ||
|
||
def get_combination(self, n: int, k: int) -> int: | ||
decorated_combination = self.memoizer.memoize(CombinatorialCalculator.combination) | ||
return decorated_combination(n, k) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import logging | ||
from functools import wraps | ||
|
||
logging.basicConfig(level=logging.INFO) | ||
logger = logging.getLogger(__name__) | ||
|
||
def memoize(func): | ||
cache = {} | ||
|
||
@wraps(func) | ||
def wrapper(*args): | ||
try: | ||
if args in cache: | ||
logger.info(f"Fetching from cache for args: {args}") | ||
return cache[args] | ||
result = func(*args) | ||
cache[args] = result | ||
logger.info(f"Caching result for args: {args}") | ||
return result | ||
except Exception as e: | ||
logger.error(f"Error in memoize decorator: {e}") | ||
raise | ||
return wrapper |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import logging | ||
from dataclasses import dataclass | ||
from decorator import memoize | ||
|
||
logging.basicConfig(level=logging.INFO) | ||
logger = logging.getLogger(__name__) | ||
|
||
@dataclass | ||
class FactorialCalculator: | ||
@staticmethod | ||
@memoize | ||
def factorial(n: int) -> int: | ||
if n < 0: | ||
raise ValueError("Factorial is not defined for negative numbers.") | ||
elif n == 0 or n == 1: | ||
return 1 | ||
return n * FactorialCalculator.factorial(n - 1) |
Oops, something went wrong.