Skip to content

Commit da462df

Browse files
committed
Solved issue #475
1 parent ed88315 commit da462df

File tree

4 files changed

+140
-0
lines changed

4 files changed

+140
-0
lines changed

oryx-build-commands.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
PlatformWithVersion=Python
2+
BuildCommands=conda env create --file environment.yml --prefix ./venv --quiet

pydatastructs/multi_threaded_algorithms/__init__.py

Whitespace-only changes.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import threading
2+
3+
class Fibonacci:
4+
"""Representation of Fibonacci data structure
5+
6+
Parameters
7+
----------
8+
n : int
9+
The index for which to compute the Fibonacci number.
10+
backend : str
11+
Optional, by default 'python'. Specifies whether to use the Python implementation or another backend.
12+
"""
13+
14+
def __init__(self, n, backend='python'):
15+
self.n = n
16+
self.backend = backend
17+
self.result = [None] * (n + 1) # To store Fibonacci numbers
18+
self.threads = [] # List to store thread references
19+
20+
def fib(self, i):
21+
"""Calculates the Fibonacci number recursively and stores it in result."""
22+
if i <= 1:
23+
return i
24+
if self.result[i] is not None:
25+
return self.result[i]
26+
self.result[i] = self.fib(i - 1) + self.fib(i - 2)
27+
return self.result[i]
28+
29+
def threaded_fib(self, i):
30+
"""Wrapper function to calculate Fibonacci in a thread and store the result."""
31+
self.result[i] = self.fib(i)
32+
33+
def calculate(self):
34+
"""Calculates the Fibonacci sequence for all numbers up to n using multi-threading."""
35+
# Start threads for each Fibonacci number calculation
36+
for i in range(self.n + 1):
37+
thread = threading.Thread(target=self.threaded_fib, args=(i,))
38+
self.threads.append(thread)
39+
thread.start()
40+
41+
# Wait for all threads to complete
42+
for thread in self.threads:
43+
thread.join()
44+
45+
# Return the nth Fibonacci number after all threads complete
46+
return self.result[self.n]
47+
48+
@property
49+
def sequence(self):
50+
"""Returns the Fibonacci sequence up to the nth number."""
51+
return self.result[:self.n + 1]
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from pydatastructs.multi_threaded_algorithms.fibonacci import Fibonacci
2+
import threading
3+
from pydatastructs.utils.raises_util import raises
4+
5+
6+
def test_Fibonacci():
7+
# Test for the Fibonacci class with default Python backend
8+
f = Fibonacci(20)
9+
assert isinstance(f, Fibonacci)
10+
assert f.n == 20
11+
assert f.calculate() == 6765 # Fibonacci(20)
12+
13+
# Test with different n values
14+
f1 = Fibonacci(7)
15+
assert f1.calculate() == 13 # Fibonacci(7)
16+
17+
f2 = Fibonacci(0)
18+
assert f2.calculate() == 0 # Fibonacci(0)
19+
20+
f3 = Fibonacci(1)
21+
assert f3.calculate() == 1 # Fibonacci(1)
22+
23+
# Test for full Fibonacci sequence up to n
24+
assert f.sequence == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
25+
26+
# Test for larger Fibonacci number
27+
f_large = Fibonacci(100)
28+
assert f_large.calculate() == 354224848179261915075 # Fibonacci(100)
29+
30+
# Test for sequence with larger n values
31+
assert len(f_large.sequence) == 101 # Fibonacci sequence up to 100 should have 101 elements
32+
33+
def test_Fibonacci_with_threading():
34+
# Test for multi-threading Fibonacci calculation for small numbers
35+
f_small = Fibonacci(10)
36+
result_small = f_small.calculate()
37+
assert result_small == 55 # Fibonacci(10)
38+
39+
# Test for multi-threading Fibonacci calculation with medium size n
40+
f_medium = Fibonacci(30)
41+
result_medium = f_medium.calculate()
42+
assert result_medium == 832040 # Fibonacci(30)
43+
44+
# Test for multi-threading Fibonacci calculation with large n
45+
f_large = Fibonacci(50)
46+
result_large = f_large.calculate()
47+
assert result_large == 12586269025 # Fibonacci(50)
48+
49+
# Test the Fibonacci sequence correctness for medium size n
50+
assert f_medium.sequence == [
51+
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,
52+
6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229
53+
]
54+
55+
# Check that sequence length is correct for large n (e.g., Fibonacci(50))
56+
assert len(f_large.sequence) == 51 # Fibonacci sequence up to 50 should have 51 elements
57+
58+
# Test invalid input (n cannot be negative)
59+
assert raises(ValueError, lambda: Fibonacci(-5))
60+
61+
# Test when backend is set to CPP (this part assumes a proper backend, can be skipped if not implemented)
62+
f_cpp = Fibonacci(10, backend='cpp')
63+
result_cpp = f_cpp.calculate()
64+
assert result_cpp == 55 # Fibonacci(10) should be the same result as Python
65+
66+
# Test if sequence matches expected for small number of terms
67+
f_test = Fibonacci(5)
68+
assert f_test.sequence == [0, 1, 1, 2, 3, 5]
69+
70+
def test_Fibonacci_with_invalid_backend():
71+
# Test when an invalid backend is provided (should raise an error)
72+
assert raises(NotImplementedError, lambda: Fibonacci(20, backend='invalid_backend'))
73+
74+
def test_Fibonacci_with_threads():
75+
# Test multi-threaded calculation is correct for different n
76+
f_threaded = Fibonacci(25)
77+
assert f_threaded.calculate() == 75025 # Fibonacci(25)
78+
79+
# Validate that the thread pool handles large n correctly
80+
f_threaded_large = Fibonacci(40)
81+
assert f_threaded_large.calculate() == 102334155 # Fibonacci(40)
82+
83+
# Ensure that no threads are left hanging (checks for thread cleanup)
84+
threads_before = threading.active_count()
85+
f_threaded.calculate()
86+
threads_after = threading.active_count()
87+
assert threads_before == threads_after # No new threads should be created unexpectedly

0 commit comments

Comments
 (0)