Skip to content

Commit

Permalink
Merge pull request #415 from yashksaini-coder/fix-414
Browse files Browse the repository at this point in the history
Feature: 🎸 Enhance + Update + Docs for Memoization
  • Loading branch information
UTSAVS26 authored Nov 9, 2024
2 parents 30b7f0b + 61caec0 commit 8b3236f
Show file tree
Hide file tree
Showing 19 changed files with 412 additions and 367 deletions.
67 changes: 0 additions & 67 deletions pysnippets/Memoisation/Importance-of-memoisation copy.md

This file was deleted.

193 changes: 0 additions & 193 deletions pysnippets/Memoisation/Memoisation.md

This file was deleted.

26 changes: 26 additions & 0 deletions pysnippets/Memoisation/Memoization.md
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.
41 changes: 41 additions & 0 deletions pysnippets/Memoisation/class_based_memoization.py
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)
23 changes: 23 additions & 0 deletions pysnippets/Memoisation/decorator.py
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
17 changes: 17 additions & 0 deletions pysnippets/Memoisation/factorial.py
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)
Loading

0 comments on commit 8b3236f

Please sign in to comment.