mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
feat: Implemented Matrix Exponentiation Method (#11747)
* feat: add Matrix Exponentiation method docs: updated the header documentation and added new documentation for the new function. * feat: added new function matrix exponetiation method * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * feat: This function uses the tail-recursive form of the Euclidean algorithm to calculate * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reduced the number of characters per line in the comments * removed unwanted code * feat: Implemented a new function to swaap numbers without dummy variable * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed previos code * Done with the required changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Done with the required changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Done with the required changes * Done with the required changes * Done with the required changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update maths/fibonacci.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Done with the required changes * Done with the required changes * Done with the required changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>
This commit is contained in:
parent
59ff87dc55
commit
9a572dec2b
|
@ -7,6 +7,8 @@ the Binet's formula function because the Binet formula function uses floats
|
||||||
|
|
||||||
NOTE 2: the Binet's formula function is much more limited in the size of inputs
|
NOTE 2: the Binet's formula function is much more limited in the size of inputs
|
||||||
that it can handle due to the size limitations of Python floats
|
that it can handle due to the size limitations of Python floats
|
||||||
|
NOTE 3: the matrix function is the fastest and most memory efficient for large n
|
||||||
|
|
||||||
|
|
||||||
See benchmark numbers in __main__ for performance comparisons/
|
See benchmark numbers in __main__ for performance comparisons/
|
||||||
https://en.wikipedia.org/wiki/Fibonacci_number for more information
|
https://en.wikipedia.org/wiki/Fibonacci_number for more information
|
||||||
|
@ -17,6 +19,9 @@ from collections.abc import Iterator
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from numpy import ndarray
|
||||||
|
|
||||||
|
|
||||||
def time_func(func, *args, **kwargs):
|
def time_func(func, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -230,6 +235,88 @@ def fib_binet(n: int) -> list[int]:
|
||||||
return [round(phi**i / sqrt_5) for i in range(n + 1)]
|
return [round(phi**i / sqrt_5) for i in range(n + 1)]
|
||||||
|
|
||||||
|
|
||||||
|
def matrix_pow_np(m: ndarray, power: int) -> ndarray:
|
||||||
|
"""
|
||||||
|
Raises a matrix to the power of 'power' using binary exponentiation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m: Matrix as a numpy array.
|
||||||
|
power: The power to which the matrix is to be raised.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The matrix raised to the power.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If power is negative.
|
||||||
|
|
||||||
|
>>> m = np.array([[1, 1], [1, 0]], dtype=int)
|
||||||
|
>>> matrix_pow_np(m, 0) # Identity matrix when raised to the power of 0
|
||||||
|
array([[1, 0],
|
||||||
|
[0, 1]])
|
||||||
|
|
||||||
|
>>> matrix_pow_np(m, 1) # Same matrix when raised to the power of 1
|
||||||
|
array([[1, 1],
|
||||||
|
[1, 0]])
|
||||||
|
|
||||||
|
>>> matrix_pow_np(m, 5)
|
||||||
|
array([[8, 5],
|
||||||
|
[5, 3]])
|
||||||
|
|
||||||
|
>>> matrix_pow_np(m, -1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: power is negative
|
||||||
|
"""
|
||||||
|
result = np.array([[1, 0], [0, 1]], dtype=int) # Identity Matrix
|
||||||
|
base = m
|
||||||
|
if power < 0: # Negative power is not allowed
|
||||||
|
raise ValueError("power is negative")
|
||||||
|
while power:
|
||||||
|
if power % 2 == 1:
|
||||||
|
result = np.dot(result, base)
|
||||||
|
base = np.dot(base, base)
|
||||||
|
power //= 2
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def fib_matrix_np(n: int) -> int:
|
||||||
|
"""
|
||||||
|
Calculates the n-th Fibonacci number using matrix exponentiation.
|
||||||
|
https://www.nayuki.io/page/fast-fibonacci-algorithms#:~:text=
|
||||||
|
Summary:%20The%20two%20fast%20Fibonacci%20algorithms%20are%20matrix
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n: Fibonacci sequence index
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The n-th Fibonacci number.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If n is negative.
|
||||||
|
|
||||||
|
>>> fib_matrix_np(0)
|
||||||
|
0
|
||||||
|
>>> fib_matrix_np(1)
|
||||||
|
1
|
||||||
|
>>> fib_matrix_np(5)
|
||||||
|
5
|
||||||
|
>>> fib_matrix_np(10)
|
||||||
|
55
|
||||||
|
>>> fib_matrix_np(-1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: n is negative
|
||||||
|
"""
|
||||||
|
if n < 0:
|
||||||
|
raise ValueError("n is negative")
|
||||||
|
if n == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
m = np.array([[1, 1], [1, 0]], dtype=int)
|
||||||
|
result = matrix_pow_np(m, n - 1)
|
||||||
|
return int(result[0, 0])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from doctest import testmod
|
from doctest import testmod
|
||||||
|
|
||||||
|
@ -242,3 +329,4 @@ if __name__ == "__main__":
|
||||||
time_func(fib_memoization, num) # 0.0100 ms
|
time_func(fib_memoization, num) # 0.0100 ms
|
||||||
time_func(fib_recursive_cached, num) # 0.0153 ms
|
time_func(fib_recursive_cached, num) # 0.0153 ms
|
||||||
time_func(fib_recursive, num) # 257.0910 ms
|
time_func(fib_recursive, num) # 257.0910 ms
|
||||||
|
time_func(fib_matrix_np, num) # 0.0000 ms
|
||||||
|
|
Loading…
Reference in New Issue
Block a user