Skip to content

Commit 3ed93d8

Browse files
authored
Merge branch 'TheAlgorithms:master' into master
2 parents 925b1ed + 80a2087 commit 3ed93d8

5 files changed

Lines changed: 192 additions & 89 deletions

File tree

maths/gamma.py

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,43 @@
1+
"""
2+
Gamma function is a very useful tool in math and physics.
3+
It helps calculating complex integral in a convenient way.
4+
for more info: https://en.wikipedia.org/wiki/Gamma_function
5+
In mathematics, the gamma function is one commonly
6+
used extension of the factorial function to complex numbers.
7+
The gamma function is defined for all complex numbers except
8+
the non-positive integers
9+
Python's Standard Library math.gamma() function overflows around gamma(171.624).
10+
"""
111
import math
212

313
from numpy import inf
414
from scipy.integrate import quad
515

616

7-
def gamma(num: float) -> float:
17+
def gamma_iterative(num: float) -> float:
818
"""
9-
https://en.wikipedia.org/wiki/Gamma_function
10-
In mathematics, the gamma function is one commonly
11-
used extension of the factorial function to complex numbers.
12-
The gamma function is defined for all complex numbers except the non-positive
13-
integers
14-
>>> gamma(-1)
19+
Calculates the value of Gamma function of num
20+
where num is either an integer (1, 2, 3..) or a half-integer (0.5, 1.5, 2.5 ...).
21+
22+
>>> gamma_iterative(-1)
1523
Traceback (most recent call last):
1624
...
1725
ValueError: math domain error
18-
>>> gamma(0)
26+
>>> gamma_iterative(0)
1927
Traceback (most recent call last):
2028
...
2129
ValueError: math domain error
22-
>>> gamma(9)
30+
>>> gamma_iterative(9)
2331
40320.0
2432
>>> from math import gamma as math_gamma
25-
>>> all(.99999999 < gamma(i) / math_gamma(i) <= 1.000000001
33+
>>> all(.99999999 < gamma_iterative(i) / math_gamma(i) <= 1.000000001
2634
... for i in range(1, 50))
2735
True
28-
>>> gamma(-1)/math_gamma(-1) <= 1.000000001
36+
>>> gamma_iterative(-1)/math_gamma(-1) <= 1.000000001
2937
Traceback (most recent call last):
3038
...
3139
ValueError: math domain error
32-
>>> gamma(3.3) - math_gamma(3.3) <= 0.00000001
40+
>>> gamma_iterative(3.3) - math_gamma(3.3) <= 0.00000001
3341
True
3442
"""
3543
if num <= 0:
@@ -42,7 +50,66 @@ def integrand(x: float, z: float) -> float:
4250
return math.pow(x, z - 1) * math.exp(-x)
4351

4452

53+
def gamma_recursive(num: float) -> float:
54+
"""
55+
Calculates the value of Gamma function of num
56+
where num is either an integer (1, 2, 3..) or a half-integer (0.5, 1.5, 2.5 ...).
57+
Implemented using recursion
58+
Examples:
59+
>>> from math import isclose, gamma as math_gamma
60+
>>> gamma_recursive(0.5)
61+
1.7724538509055159
62+
>>> gamma_recursive(1)
63+
1.0
64+
>>> gamma_recursive(2)
65+
1.0
66+
>>> gamma_recursive(3.5)
67+
3.3233509704478426
68+
>>> gamma_recursive(171.5)
69+
9.483367566824795e+307
70+
>>> all(isclose(gamma_recursive(num), math_gamma(num))
71+
... for num in (0.5, 2, 3.5, 171.5))
72+
True
73+
>>> gamma_recursive(0)
74+
Traceback (most recent call last):
75+
...
76+
ValueError: math domain error
77+
>>> gamma_recursive(-1.1)
78+
Traceback (most recent call last):
79+
...
80+
ValueError: math domain error
81+
>>> gamma_recursive(-4)
82+
Traceback (most recent call last):
83+
...
84+
ValueError: math domain error
85+
>>> gamma_recursive(172)
86+
Traceback (most recent call last):
87+
...
88+
OverflowError: math range error
89+
>>> gamma_recursive(1.1)
90+
Traceback (most recent call last):
91+
...
92+
NotImplementedError: num must be an integer or a half-integer
93+
"""
94+
if num <= 0:
95+
raise ValueError("math domain error")
96+
if num > 171.5:
97+
raise OverflowError("math range error")
98+
elif num - int(num) not in (0, 0.5):
99+
raise NotImplementedError("num must be an integer or a half-integer")
100+
elif num == 0.5:
101+
return math.sqrt(math.pi)
102+
else:
103+
return 1.0 if num == 1 else (num - 1) * gamma_recursive(num - 1)
104+
105+
45106
if __name__ == "__main__":
46107
from doctest import testmod
47108

48109
testmod()
110+
num = 1.0
111+
while num:
112+
num = float(input("Gamma of: "))
113+
print(f"gamma_iterative({num}) = {gamma_iterative(num)}")
114+
print(f"gamma_recursive({num}) = {gamma_recursive(num)}")
115+
print("\nEnter 0 to exit...")

maths/gamma_recursive.py

Lines changed: 0 additions & 77 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Mish Activation Function
3+
4+
Use Case: Improved version of the ReLU activation function used in Computer Vision.
5+
For more detailed information, you can refer to the following link:
6+
https://en.wikipedia.org/wiki/Rectifier_(neural_networks)#Mish
7+
"""
8+
9+
import numpy as np
10+
11+
12+
def mish(vector: np.ndarray) -> np.ndarray:
13+
"""
14+
Implements the Mish activation function.
15+
16+
Parameters:
17+
vector (np.ndarray): The input array for Mish activation.
18+
19+
Returns:
20+
np.ndarray: The input array after applying the Mish activation.
21+
22+
Formula:
23+
f(x) = x * tanh(softplus(x)) = x * tanh(ln(1 + e^x))
24+
25+
Examples:
26+
>>> mish(vector=np.array([2.3,0.6,-2,-3.8]))
27+
array([ 2.26211893, 0.46613649, -0.25250148, -0.08405831])
28+
29+
>>> mish(np.array([-9.2, -0.3, 0.45, -4.56]))
30+
array([-0.00092952, -0.15113318, 0.33152014, -0.04745745])
31+
32+
"""
33+
return vector * np.tanh(np.log(1 + np.exp(vector)))
34+
35+
36+
if __name__ == "__main__":
37+
import doctest
38+
39+
doctest.testmod()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Softplus Activation Function
3+
4+
Use Case: The Softplus function is a smooth approximation of the ReLU function.
5+
For more detailed information, you can refer to the following link:
6+
https://en.wikipedia.org/wiki/Rectifier_(neural_networks)#Softplus
7+
"""
8+
9+
import numpy as np
10+
11+
12+
def softplus(vector: np.ndarray) -> np.ndarray:
13+
"""
14+
Implements the Softplus activation function.
15+
16+
Parameters:
17+
vector (np.ndarray): The input array for the Softplus activation.
18+
19+
Returns:
20+
np.ndarray: The input array after applying the Softplus activation.
21+
22+
Formula: f(x) = ln(1 + e^x)
23+
24+
Examples:
25+
>>> softplus(np.array([2.3, 0.6, -2, -3.8]))
26+
array([2.39554546, 1.03748795, 0.12692801, 0.02212422])
27+
28+
>>> softplus(np.array([-9.2, -0.3, 0.45, -4.56]))
29+
array([1.01034298e-04, 5.54355244e-01, 9.43248946e-01, 1.04077103e-02])
30+
"""
31+
return np.log(1 + np.exp(vector))
32+
33+
34+
if __name__ == "__main__":
35+
import doctest
36+
37+
doctest.testmod()

other/majority_vote_algorithm.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
This is Booyer-Moore Majority Vote Algorithm. The problem statement goes like this:
3+
Given an integer array of size n, find all elements that appear more than ⌊ n/k ⌋ times.
4+
We have to solve in O(n) time and O(1) Space.
5+
URL : https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm
6+
"""
7+
from collections import Counter
8+
9+
10+
def majority_vote(votes: list[int], votes_needed_to_win: int) -> list[int]:
11+
"""
12+
>>> majority_vote([1, 2, 2, 3, 1, 3, 2], 3)
13+
[2]
14+
>>> majority_vote([1, 2, 2, 3, 1, 3, 2], 2)
15+
[]
16+
>>> majority_vote([1, 2, 2, 3, 1, 3, 2], 4)
17+
[1, 2, 3]
18+
"""
19+
majority_candidate_counter: Counter[int] = Counter()
20+
for vote in votes:
21+
majority_candidate_counter[vote] += 1
22+
if len(majority_candidate_counter) == votes_needed_to_win:
23+
majority_candidate_counter -= Counter(set(majority_candidate_counter))
24+
majority_candidate_counter = Counter(
25+
vote for vote in votes if vote in majority_candidate_counter
26+
)
27+
return [
28+
vote
29+
for vote in majority_candidate_counter
30+
if majority_candidate_counter[vote] > len(votes) / votes_needed_to_win
31+
]
32+
33+
34+
if __name__ == "__main__":
35+
import doctest
36+
37+
doctest.testmod()

0 commit comments

Comments
 (0)