Skip to content

Commit 9a572de

Browse files
Acuspeedsterpre-commit-ci[bot]tianyizheng02
authored
feat: Implemented Matrix Exponentiation Method (TheAlgorithms#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 <[email protected]> * [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 <[email protected]>
1 parent 59ff87d commit 9a572de

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

Diff for: maths/fibonacci.py

+88
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
88
NOTE 2: the Binet's formula function is much more limited in the size of inputs
99
that it can handle due to the size limitations of Python floats
10+
NOTE 3: the matrix function is the fastest and most memory efficient for large n
11+
1012
1113
See benchmark numbers in __main__ for performance comparisons/
1214
https://en.wikipedia.org/wiki/Fibonacci_number for more information
@@ -17,6 +19,9 @@
1719
from math import sqrt
1820
from time import time
1921

22+
import numpy as np
23+
from numpy import ndarray
24+
2025

2126
def time_func(func, *args, **kwargs):
2227
"""
@@ -230,6 +235,88 @@ def fib_binet(n: int) -> list[int]:
230235
return [round(phi**i / sqrt_5) for i in range(n + 1)]
231236

232237

238+
def matrix_pow_np(m: ndarray, power: int) -> ndarray:
239+
"""
240+
Raises a matrix to the power of 'power' using binary exponentiation.
241+
242+
Args:
243+
m: Matrix as a numpy array.
244+
power: The power to which the matrix is to be raised.
245+
246+
Returns:
247+
The matrix raised to the power.
248+
249+
Raises:
250+
ValueError: If power is negative.
251+
252+
>>> m = np.array([[1, 1], [1, 0]], dtype=int)
253+
>>> matrix_pow_np(m, 0) # Identity matrix when raised to the power of 0
254+
array([[1, 0],
255+
[0, 1]])
256+
257+
>>> matrix_pow_np(m, 1) # Same matrix when raised to the power of 1
258+
array([[1, 1],
259+
[1, 0]])
260+
261+
>>> matrix_pow_np(m, 5)
262+
array([[8, 5],
263+
[5, 3]])
264+
265+
>>> matrix_pow_np(m, -1)
266+
Traceback (most recent call last):
267+
...
268+
ValueError: power is negative
269+
"""
270+
result = np.array([[1, 0], [0, 1]], dtype=int) # Identity Matrix
271+
base = m
272+
if power < 0: # Negative power is not allowed
273+
raise ValueError("power is negative")
274+
while power:
275+
if power % 2 == 1:
276+
result = np.dot(result, base)
277+
base = np.dot(base, base)
278+
power //= 2
279+
return result
280+
281+
282+
def fib_matrix_np(n: int) -> int:
283+
"""
284+
Calculates the n-th Fibonacci number using matrix exponentiation.
285+
https://www.nayuki.io/page/fast-fibonacci-algorithms#:~:text=
286+
Summary:%20The%20two%20fast%20Fibonacci%20algorithms%20are%20matrix
287+
288+
Args:
289+
n: Fibonacci sequence index
290+
291+
Returns:
292+
The n-th Fibonacci number.
293+
294+
Raises:
295+
ValueError: If n is negative.
296+
297+
>>> fib_matrix_np(0)
298+
0
299+
>>> fib_matrix_np(1)
300+
1
301+
>>> fib_matrix_np(5)
302+
5
303+
>>> fib_matrix_np(10)
304+
55
305+
>>> fib_matrix_np(-1)
306+
Traceback (most recent call last):
307+
...
308+
ValueError: n is negative
309+
"""
310+
if n < 0:
311+
raise ValueError("n is negative")
312+
if n == 0:
313+
return 0
314+
315+
m = np.array([[1, 1], [1, 0]], dtype=int)
316+
result = matrix_pow_np(m, n - 1)
317+
return int(result[0, 0])
318+
319+
233320
if __name__ == "__main__":
234321
from doctest import testmod
235322

@@ -242,3 +329,4 @@ def fib_binet(n: int) -> list[int]:
242329
time_func(fib_memoization, num) # 0.0100 ms
243330
time_func(fib_recursive_cached, num) # 0.0153 ms
244331
time_func(fib_recursive, num) # 257.0910 ms
332+
time_func(fib_matrix_np, num) # 0.0000 ms

0 commit comments

Comments
 (0)