From 1b296aa0b8a3b9d8fa8873fc4268e9edd379a1f5 Mon Sep 17 00:00:00 2001 From: Saptadeep Banerjee <69459134+imSanko@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:49:54 +0530 Subject: [PATCH 1/7] Added Fibonacci_Heap for DSA --- data_structures/heap/fibonacci_heap.py | 101 +++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 data_structures/heap/fibonacci_heap.py diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py new file mode 100644 index 000000000000..0b7e70987c39 --- /dev/null +++ b/data_structures/heap/fibonacci_heap.py @@ -0,0 +1,101 @@ +class FibonacciNode: + def __init__(self, key): + self.key = key + self.children = [] + self.marked = False + self.degree = 0 + self.parent = None + +class FibonacciHeap: + def __init__(self): + self.trees = [] + self.least = None + self.count = 0 + + def insert(self, key): + new_node = FibonacciNode(key) + self.trees.append(new_node) + self.count += 1 + if self.least is None or key < self.least.key: + self.least = new_node + + def extract_min(self): + if self.count == 0: + raise ValueError("Heap is empty") + + min_node = self.least + self.trees.remove(min_node) + + for child in min_node.children: + child.parent = None + self.trees.append(child) + + self.count -= 1 + + if self.least is min_node: + self.least = None + for node in self.trees: + if self.least is None or node.key < self.least.key: + self.least = node + + self.consolidate() + return min_node.key + + def consolidate(self): + degree_counts = [None] * (2 * len(self.trees)) + + for node in self.trees[:]: + degree = node.degree + while degree_counts[degree] is not None: + other_node = degree_counts[degree] + if node.key > other_node.key: + node, other_node = other_node, node # Swap nodes + self.link(other_node, node) + degree_counts[degree] = None + degree += 1 + degree_counts[degree] = node + + self.trees = [node for node in degree_counts if node is not None] + + def link(self, node1, node2): + self.trees.remove(node2) + node1.children.append(node2) + node2.parent = node1 + node1.degree += 1 + node2.marked = False + + def decrease_key(self, node, new_key): + if new_key > node.key: + raise ValueError("New key must be less than or equal to old key") + + node.key = new_key + + if node == self.least: + self.update_least() + + parent = node.parent + if parent is not None and node.key < parent.key: + self.cut(node, parent) + self.cascading_cut(parent) + + def cut(self, node, parent): + parent.children.remove(node) + parent.degree -= 1 + self.trees.append(node) + node.parent = None + node.marked = False + + def cascading_cut(self, node): + parent = node.parent + if parent is not None: + if not node.marked: + node.marked = True + else: + self.cut(node, parent) + self.cascading_cut(parent) + + def update_least(self): + self.least = None + for node in self.trees: + if self.least is None or node.key < self.least.key: + self.least = node From c564f087013b5baadc7c2ef030fbdab52991b86b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 12:24:09 +0000 Subject: [PATCH 2/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/fibonacci_heap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/heap/fibonacci_heap.py b/data_structures/heap/fibonacci_heap.py index 0b7e70987c39..e2d16c67571a 100644 --- a/data_structures/heap/fibonacci_heap.py +++ b/data_structures/heap/fibonacci_heap.py @@ -6,6 +6,7 @@ def __init__(self, key): self.degree = 0 self.parent = None + class FibonacciHeap: def __init__(self): self.trees = [] @@ -86,8 +87,7 @@ def cut(self, node, parent): node.marked = False def cascading_cut(self, node): - parent = node.parent - if parent is not None: + if (parent := node.parent) is not None: if not node.marked: node.marked = True else: From 9c64f79b75d46fbdd0b80c42e1a7e2028e56fed0 Mon Sep 17 00:00:00 2001 From: Saptadeep Banerjee Date: Mon, 2 Oct 2023 07:21:39 +0530 Subject: [PATCH 3/7] Adding the New Metropolis_Hasting Algorithm --- dynamic_programming/Metropolis_Hasting.py | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 dynamic_programming/Metropolis_Hasting.py diff --git a/dynamic_programming/Metropolis_Hasting.py b/dynamic_programming/Metropolis_Hasting.py new file mode 100644 index 000000000000..543ff9860d4f --- /dev/null +++ b/dynamic_programming/Metropolis_Hasting.py @@ -0,0 +1,28 @@ +import numpy as np + +def metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state): + samples = [initial_state] + current_state = initial_state + + for _ in range(num_samples): + proposed_state = proposal_distribution(current_state) + acceptance_ratio = min(1, target_distribution(proposed_state) / target_distribution(current_state)) + + if np.random.rand() < acceptance_ratio: + current_state = proposed_state + + samples.append(current_state) + + return samples[1:] + +def target_distribution(x): + return np.exp(-x**2 / 2) / np.sqrt(2 * np.pi) + +def proposal_distribution(x): + return x + np.random.normal(0, 1) + +if __name__ == "__main__": + num_samples = 10000 + initial_state = 0 + + samples = metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state) From 4e33aee6b83be64a8702d7bdeb7d178c3223d4c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 01:52:46 +0000 Subject: [PATCH 4/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/Metropolis_Hasting.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dynamic_programming/Metropolis_Hasting.py b/dynamic_programming/Metropolis_Hasting.py index 543ff9860d4f..bb37fd979863 100644 --- a/dynamic_programming/Metropolis_Hasting.py +++ b/dynamic_programming/Metropolis_Hasting.py @@ -1,12 +1,17 @@ import numpy as np -def metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state): + +def metropolis_hastings( + target_distribution, proposal_distribution, num_samples, initial_state +): samples = [initial_state] current_state = initial_state for _ in range(num_samples): proposed_state = proposal_distribution(current_state) - acceptance_ratio = min(1, target_distribution(proposed_state) / target_distribution(current_state)) + acceptance_ratio = min( + 1, target_distribution(proposed_state) / target_distribution(current_state) + ) if np.random.rand() < acceptance_ratio: current_state = proposed_state @@ -15,14 +20,19 @@ def metropolis_hastings(target_distribution, proposal_distribution, num_samples, return samples[1:] + def target_distribution(x): - return np.exp(-x**2 / 2) / np.sqrt(2 * np.pi) + return np.exp(-(x**2) / 2) / np.sqrt(2 * np.pi) + def proposal_distribution(x): return x + np.random.normal(0, 1) + if __name__ == "__main__": num_samples = 10000 initial_state = 0 - samples = metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state) + samples = metropolis_hastings( + target_distribution, proposal_distribution, num_samples, initial_state + ) From 39848cdf19466c28734b965a495d42f66712e87d Mon Sep 17 00:00:00 2001 From: Saptadeep Banerjee Date: Mon, 2 Oct 2023 07:52:01 +0530 Subject: [PATCH 5/7] Added the Metropolish Hasting Algorithm --- dynamic_programming/Metropolis_Hasting.py | 38 ----------------------- 1 file changed, 38 deletions(-) delete mode 100644 dynamic_programming/Metropolis_Hasting.py diff --git a/dynamic_programming/Metropolis_Hasting.py b/dynamic_programming/Metropolis_Hasting.py deleted file mode 100644 index bb37fd979863..000000000000 --- a/dynamic_programming/Metropolis_Hasting.py +++ /dev/null @@ -1,38 +0,0 @@ -import numpy as np - - -def metropolis_hastings( - target_distribution, proposal_distribution, num_samples, initial_state -): - samples = [initial_state] - current_state = initial_state - - for _ in range(num_samples): - proposed_state = proposal_distribution(current_state) - acceptance_ratio = min( - 1, target_distribution(proposed_state) / target_distribution(current_state) - ) - - if np.random.rand() < acceptance_ratio: - current_state = proposed_state - - samples.append(current_state) - - return samples[1:] - - -def target_distribution(x): - return np.exp(-(x**2) / 2) / np.sqrt(2 * np.pi) - - -def proposal_distribution(x): - return x + np.random.normal(0, 1) - - -if __name__ == "__main__": - num_samples = 10000 - initial_state = 0 - - samples = metropolis_hastings( - target_distribution, proposal_distribution, num_samples, initial_state - ) From 75aeae5530474717de82cc0415cc0c18f751dd2b Mon Sep 17 00:00:00 2001 From: Saptadeep Banerjee Date: Mon, 2 Oct 2023 07:52:29 +0530 Subject: [PATCH 6/7] Added the Metropolish Hasting Algo --- data_structures/heap/metropolish_hasting.py | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 data_structures/heap/metropolish_hasting.py diff --git a/data_structures/heap/metropolish_hasting.py b/data_structures/heap/metropolish_hasting.py new file mode 100644 index 000000000000..543ff9860d4f --- /dev/null +++ b/data_structures/heap/metropolish_hasting.py @@ -0,0 +1,28 @@ +import numpy as np + +def metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state): + samples = [initial_state] + current_state = initial_state + + for _ in range(num_samples): + proposed_state = proposal_distribution(current_state) + acceptance_ratio = min(1, target_distribution(proposed_state) / target_distribution(current_state)) + + if np.random.rand() < acceptance_ratio: + current_state = proposed_state + + samples.append(current_state) + + return samples[1:] + +def target_distribution(x): + return np.exp(-x**2 / 2) / np.sqrt(2 * np.pi) + +def proposal_distribution(x): + return x + np.random.normal(0, 1) + +if __name__ == "__main__": + num_samples = 10000 + initial_state = 0 + + samples = metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state) From c0c28f94f61276ed6c3facd97bb821c020c0cb09 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 02:23:14 +0000 Subject: [PATCH 7/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/heap/metropolish_hasting.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/data_structures/heap/metropolish_hasting.py b/data_structures/heap/metropolish_hasting.py index 543ff9860d4f..bb37fd979863 100644 --- a/data_structures/heap/metropolish_hasting.py +++ b/data_structures/heap/metropolish_hasting.py @@ -1,12 +1,17 @@ import numpy as np -def metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state): + +def metropolis_hastings( + target_distribution, proposal_distribution, num_samples, initial_state +): samples = [initial_state] current_state = initial_state for _ in range(num_samples): proposed_state = proposal_distribution(current_state) - acceptance_ratio = min(1, target_distribution(proposed_state) / target_distribution(current_state)) + acceptance_ratio = min( + 1, target_distribution(proposed_state) / target_distribution(current_state) + ) if np.random.rand() < acceptance_ratio: current_state = proposed_state @@ -15,14 +20,19 @@ def metropolis_hastings(target_distribution, proposal_distribution, num_samples, return samples[1:] + def target_distribution(x): - return np.exp(-x**2 / 2) / np.sqrt(2 * np.pi) + return np.exp(-(x**2) / 2) / np.sqrt(2 * np.pi) + def proposal_distribution(x): return x + np.random.normal(0, 1) + if __name__ == "__main__": num_samples = 10000 initial_state = 0 - samples = metropolis_hastings(target_distribution, proposal_distribution, num_samples, initial_state) + samples = metropolis_hastings( + target_distribution, proposal_distribution, num_samples, initial_state + )