From d8a0afc55065467bc642fca181c6560565cb0247 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 7 Jul 2017 19:08:04 +0200 Subject: [PATCH 01/59] fix error in preshow --- data_structures/Binary Tree/binary_seach_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/Binary Tree/binary_seach_tree.py b/data_structures/Binary Tree/binary_seach_tree.py index 1dac948ae3c5..7840b2a32be8 100644 --- a/data_structures/Binary Tree/binary_seach_tree.py +++ b/data_structures/Binary Tree/binary_seach_tree.py @@ -68,7 +68,7 @@ def empty(self): return False def preShow(self, curr_node): - if curr_node is None: + if curr_node is not None: print(curr_node.getLabel(), end=" ") self.preShow(curr_node.getLeft()) From 8384cbb8792cade306b630b56917e9ee41b4ba55 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 7 Jul 2017 20:06:33 +0200 Subject: [PATCH 02/59] finish AVL --- data_structures/AVL/AVL.py | 82 ++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/data_structures/AVL/AVL.py b/data_structures/AVL/AVL.py index 0e3008dc15b1..ad84583652ac 100644 --- a/data_structures/AVL/AVL.py +++ b/data_structures/AVL/AVL.py @@ -39,7 +39,7 @@ def setParent(self, parent): def setHeight(self, height): self.height = height - def getHeight(self, height): + def getHeight(self): return self.height @@ -72,38 +72,36 @@ def insert(self, value): if node.getLabel() < dad_node.getLabel(): dad_node.setLeft(node) dad_node.setHeight(dad_node.getHeight() + 1) - - if (dad_node.getRight().getHeight() - - dad_node.getLeft.getHeight() > 1): - self.rebalance(dad_node) - else: dad_node.setRight(node) dad_node.setHeight(dad_node.getHeight() + 1) - - if (dad_node.getRight().getHeight() - - dad_node.getLeft.getHeight() > 1): - self.rebalance(dad_node) break def rebalance(self, node): - if (node.getRight().getHeight() - - node.getLeft.getHeight() > 1): - if (node.getRight().getHeight() > - node.getLeft.getHeight()): - pass - else: - pass - pass - elif (node.getRight().getHeight() - - node.getLeft.getHeight() > 2): - if (node.getRight().getHeight() > - node.getLeft.getHeight()): - pass + height_right = 0 + height_left = 0 + + if node.getRight() is not None: + height_right = node.getRight().getHeight() + + if node.getLeft() is not None: + height_left = node.getLeft().getHeight() + + if abs(height_left - height_right) > 1: + if height_left > height_right: + right_child = node.getRight() + if (right_child.getLeft().getHeight() > + right_child.getRight().getHeight()): + self.rotate_left(node) + else: + self.double_rotate_right(node) else: - pass - pass - pass + left_child = node.getLeft() + if (left_child.getLeft().getHeight() > + left_child.getRight().getHeight()): + self.double_rotate_left(node) + else: + self.rotate_right(node) def rotate_left(self, node): # TODO: is this pythonic enought? @@ -129,3 +127,35 @@ def double_rotate_left(self, node): def double_rotate_right(self, node): self.rotate_left(node.getLeft().getLeft()) self.rotate_right(node) + + def empty(self): + if self.root is None: + return True + return False + + def preShow(self, curr_node): + if curr_node is not None: + self.preShow(curr_node.getLeft()) + print(curr_node.getLabel(), end=" ") + self.preShow(curr_node.getRight()) + + def getRoot(self): + return self.root + +t = AVL() +t.insert(11) +t.insert(14) +t.insert(3) +t.insert(4) +t.insert(5) +t.insert(6) +t.insert(7) +t.insert(8) +t.insert(9) +t.insert(10) +t.insert(1) +t.insert(12) +t.insert(13) +t.insert(2) +t.insert(15) +t.preShow(t.getRoot()) From 67f23f59b15581be38c5d630018e590148928384 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 8 Jul 2017 01:26:49 +0200 Subject: [PATCH 03/59] rotate left almost working --- data_structures/AVL/AVL.py | 183 ++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 51 deletions(-) diff --git a/data_structures/AVL/AVL.py b/data_structures/AVL/AVL.py index ad84583652ac..4a360fee56f9 100644 --- a/data_structures/AVL/AVL.py +++ b/data_structures/AVL/AVL.py @@ -23,18 +23,24 @@ def getLeft(self): def setLeft(self, left): self.left = left - + self.left.setParent(self) + self.left.setHeight(self.height + 1) + def getRight(self): return self.rigt def setRight(self, right): self.rigt = right + self.rigt.setParent(self) + self.rigt.setHeight(self.height + 1) def getParent(self): return self.parent def setParent(self, parent): self.parent = parent + self.height = (self.parent.getHeight() + 1 if + (self.parent is not None) else 0) def setHeight(self, height): self.height = height @@ -53,6 +59,7 @@ def insert(self, value): node = Node(value) if self.root is None: self.root = node + self.root.setHeight(0) self.size = 1 else: # Same as Binary Tree @@ -71,54 +78,59 @@ def insert(self, value): else: if node.getLabel() < dad_node.getLabel(): dad_node.setLeft(node) - dad_node.setHeight(dad_node.getHeight() + 1) else: dad_node.setRight(node) - dad_node.setHeight(dad_node.getHeight() + 1) + self.rebalance(dad_node) break def rebalance(self, node): height_right = 0 height_left = 0 - - if node.getRight() is not None: - height_right = node.getRight().getHeight() - - if node.getLeft() is not None: - height_left = node.getLeft().getHeight() - - if abs(height_left - height_right) > 1: - if height_left > height_right: - right_child = node.getRight() - if (right_child.getLeft().getHeight() > - right_child.getRight().getHeight()): - self.rotate_left(node) - else: - self.double_rotate_right(node) - else: - left_child = node.getLeft() - if (left_child.getLeft().getHeight() > - left_child.getRight().getHeight()): - self.double_rotate_left(node) + n = node + while n is not None: + height_right = 0 + height_left = 0 + + if node.getRight() is not None: + height_right = node.getRight().getHeight() + + if node.getLeft() is not None: + height_left = node.getLeft().getHeight() + + if abs(height_left - height_right) > 1: + if height_left > height_right: + left_child = node.getRight() + if (): + self.rotate_left(n) + break + else: + self.double_rotate_right(n) + break else: - self.rotate_right(node) + right_child = node.getRight() + if right_child is not None: + h_right = (right_child.getRight().getHeight() + if (right_child.getRight() is not None) else 0) + h_left = (right_child.getLeft().getHeight() + if (right_child.getLeft() is not None) else 0) + + if (h_left > h_right): + self.double_rotate_left(n) + break + else: + self.rotate_right(n) + print(n.getLabel()) + break + n = n.getParent() def rotate_left(self, node): - # TODO: is this pythonic enought? - aux = node.getLabel() - node = aux.getRight() - node.setHeight(node.getHeight() - 1) - node.setLeft(Node(aux)) - node.getLeft().setHeight(node.getHeight() + 1) - node.getRight().setHeight(node.getRight().getHeight() - 1) + pass def rotate_right(self, node): - aux = node.getLabel() - node = aux.getLeft() - node.setHeight(node.getHeight() - 1) - node.setRight(Node(aux)) - node.getLeft().setHeight(node.getHeight() + 1) - node.getLeft().setHeight(node.getLeft().getHeight() - 1) + n = Node(node.getLabel()) + n.setRight(node.getRight()) + n.setLeft(Node(node.getParent().getLabel())) + node = n def double_rotate_left(self, node): self.rotate_right(node.getRight().getRight()) @@ -139,23 +151,92 @@ def preShow(self, curr_node): print(curr_node.getLabel(), end=" ") self.preShow(curr_node.getRight()) + def preorden(self, curr_node): + if curr_node is not None: + self.preShow(curr_node.getLeft()) + self.preShow(curr_node.getRight()) + print(curr_node.getLabel(), end=" ") + def getRoot(self): return self.root t = AVL() -t.insert(11) -t.insert(14) -t.insert(3) -t.insert(4) -t.insert(5) -t.insert(6) -t.insert(7) -t.insert(8) -t.insert(9) -t.insert(10) +# t.insert(1) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(2) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(3) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# print(t.getRoot().getHeight()) +# print(t.getRoot().getRight().getHeight()) t.insert(1) -t.insert(12) -t.insert(13) t.insert(2) -t.insert(15) -t.preShow(t.getRoot()) +t.insert(3) +# t.insert(4) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(5) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(6) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(7) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(8) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(9) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(10) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(11) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(12) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(13) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(14) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) +# print("\n") +# t.insert(15) +# t.preShow(t.getRoot()) +# print("\n") +# t.preorden(t.getRoot()) From d8cd33add2274af8f8ef6371f2bb019bab734b98 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 8 Jul 2017 20:50:47 +0200 Subject: [PATCH 04/59] using python properties --- data_structures/AVL/AVL.py | 67 +++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/data_structures/AVL/AVL.py b/data_structures/AVL/AVL.py index 4a360fee56f9..f1ac16ef817d 100644 --- a/data_structures/AVL/AVL.py +++ b/data_structures/AVL/AVL.py @@ -12,41 +12,32 @@ def __init__(self, label): self.parent = None self.height = 0 - def getLabel(self): - return self.label + @property + def right(self): + return self.right - def setLabel(self, label): - self.label = label - - def getLeft(self): - return self.left - - def setLeft(self, left): - self.left = left - self.left.setParent(self) - self.left.setHeight(self.height + 1) - - def getRight(self): - return self.rigt + @right.setter + def right(self, node): + node.parent = self + self.right = node - def setRight(self, right): - self.rigt = right - self.rigt.setParent(self) - self.rigt.setHeight(self.height + 1) - - def getParent(self): + @property + def left(self): return self.parent - def setParent(self, parent): - self.parent = parent - self.height = (self.parent.getHeight() + 1 if - (self.parent is not None) else 0) + @left.setter + def left(self, node): + node.parent = self + self.left = node - def setHeight(self, height): - self.height = height + @property + def parent(self): + return self.parent - def getHeight(self): - return self.height + @parent.setter + def parent(self, node): + self.parent = node + self.height = self.parent.height + 1 class AVL: @@ -59,7 +50,7 @@ def insert(self, value): node = Node(value) if self.root is None: self.root = node - self.root.setHeight(0) + self.root.height = 0 self.size = 1 else: # Same as Binary Tree @@ -71,16 +62,18 @@ def insert(self, value): dad_node = curr_node - if node.getLabel() < curr_node.getLabel(): - curr_node = curr_node.getLeft() + if node.label < curr_node.label: + curr_node = curr_node.left else: - curr_node = curr_node.getRight() + curr_node = curr_node.rigt else: - if node.getLabel() < dad_node.getLabel(): - dad_node.setLeft(node) + if node.label < dad_node.label: + dad_node.left = node else: - dad_node.setRight(node) + dad_node.right = node + self.rebalance(dad_node) + self.size += 1 break def rebalance(self, node): @@ -119,7 +112,6 @@ def rebalance(self, node): break else: self.rotate_right(n) - print(n.getLabel()) break n = n.getParent() @@ -130,7 +122,6 @@ def rotate_right(self, node): n = Node(node.getLabel()) n.setRight(node.getRight()) n.setLeft(Node(node.getParent().getLabel())) - node = n def double_rotate_left(self, node): self.rotate_right(node.getRight().getRight()) From 8e41aca1b943d9bbbd742f57a0aa58cfa5e6c35e Mon Sep 17 00:00:00 2001 From: Rafael Date: Mon, 10 Jul 2017 18:29:45 +0200 Subject: [PATCH 05/59] node now eses pythonproperties --- data_structures/AVL/AVL.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/data_structures/AVL/AVL.py b/data_structures/AVL/AVL.py index f1ac16ef817d..0c34cb597eb6 100644 --- a/data_structures/AVL/AVL.py +++ b/data_structures/AVL/AVL.py @@ -7,9 +7,6 @@ class Node: def __init__(self, label): self.label = label - self.left = None - self.rigt = None - self.parent = None self.height = 0 @property @@ -23,7 +20,7 @@ def right(self, node): @property def left(self): - return self.parent + return self.left @left.setter def left(self, node): @@ -48,6 +45,7 @@ def __init__(self): def insert(self, value): node = Node(value) + if self.root is None: self.root = node self.root.height = 0 @@ -65,7 +63,7 @@ def insert(self, value): if node.label < curr_node.label: curr_node = curr_node.left else: - curr_node = curr_node.rigt + curr_node = curr_node.right else: if node.label < dad_node.label: dad_node.left = node @@ -92,7 +90,7 @@ def rebalance(self, node): if abs(height_left - height_right) > 1: if height_left > height_right: - left_child = node.getRight() + # left_child = node.getRight() if (): self.rotate_left(n) break @@ -100,12 +98,12 @@ def rebalance(self, node): self.double_rotate_right(n) break else: - right_child = node.getRight() + right_child = node.right if right_child is not None: - h_right = (right_child.getRight().getHeight() - if (right_child.getRight() is not None) else 0) - h_left = (right_child.getLeft().getHeight() - if (right_child.getLeft() is not None) else 0) + h_right = (right_child.right.height + if (right_child.right is not None) else 0) + h_left = (right_child.left.height + if (right_child.left is not None) else 0) if (h_left > h_right): self.double_rotate_left(n) @@ -119,9 +117,13 @@ def rotate_left(self, node): pass def rotate_right(self, node): - n = Node(node.getLabel()) - n.setRight(node.getRight()) - n.setLeft(Node(node.getParent().getLabel())) + aux = node.parent + node.parent = node + node.left = aux + + print(node.parent.label) + print(node.parent.right.label) + print(node.parent.left.label) def double_rotate_left(self, node): self.rotate_right(node.getRight().getRight()) From e1befed97603c84e2daae43254610d695794f7b8 Mon Sep 17 00:00:00 2001 From: Stephen Lee <245885195@qq.com> Date: Thu, 21 Sep 2017 13:17:36 +0800 Subject: [PATCH 06/59] add bp neural network with 3 layers --- Neural_Network/neuralnetwork_bp3.py | 134 ++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 Neural_Network/neuralnetwork_bp3.py diff --git a/Neural_Network/neuralnetwork_bp3.py b/Neural_Network/neuralnetwork_bp3.py new file mode 100644 index 000000000000..5c4f879eda2f --- /dev/null +++ b/Neural_Network/neuralnetwork_bp3.py @@ -0,0 +1,134 @@ +#-*- coding:utf-8 -*- +''' +Author: Stephen Lee +Date: 2017.9.21 + +BP neural network with three layers +''' + +import numpy as np +import matplotlib.pyplot as plt + +class Bpnw(): + + def __init__(self,n_layer1,n_layer2,n_layer3,rate_w=0.3,rate_t=0.3): + ''' + :param n_layer1: number of input layer + :param n_layer2: number of hiden layer + :param n_layer3: number of output layer + :param rate_w: rate of weight learning + :param rate_t: rate of threshold learning + ''' + self.num1 = n_layer1 + self.num2 = n_layer2 + self.num3 = n_layer3 + self.rate_weight = rate_w + self.rate_thre = rate_t + self.thre2 = -2*np.random.rand(self.num2)+1 + self.thre3 = -2*np.random.rand(self.num3)+1 + self.vji = np.mat(-2*np.random.rand(self.num2, self.num1)+1) + self.wkj = np.mat(-2*np.random.rand(self.num3, self.num2)+1) + + def sig(self,x): + return 1 / (1 + np.exp(-1*x)) + + def sig_plain(self,x): + return 1 / (1 + np.exp(-1*x)) + + def do_round(self,x): + return round(x, 3) + + def trian(self,patterns,data_train, data_teach, n_repeat, error_accuracy,draw_e = bool): + ''' + :param patterns: the number of patterns + :param data_train: training data x; numpy.ndarray + :param data_teach: training data y; numpy.ndarray + :param n_repeat: echoes + :param error_accuracy: error accuracy + :return: None + ''' + data_train = np.asarray(data_train) + data_teach = np.asarray(data_teach) + print('-------------------Start Training-------------------------') + print(' - - Shape: Train_Data ',np.shape(data_train)) + print(' - - Shape: Teach_Data ',np.shape(data_teach)) + rp = 0 + all_mse = [] + mse = 10000 + while rp < n_repeat and mse >= error_accuracy: + alle = 0 + final_out = [] + for g in range(np.shape(data_train)[0]): + net_i = data_train[g] + out1 = net_i + + net_j = out1 * self.vji.T - self.thre2 + out2=self.sig(net_j) + + net_k = out2 * self.wkj.T - self.thre3 + out3 = self.sig(net_k) + + # learning process + pd_k_all = np.multiply(np.multiply(out3,(1 - out3)),(data_teach[g]-out3)) + pd_j_all = np.multiply(pd_k_all * self.wkj,np.multiply(out2,1-out2)) + #upgrade weight + self.wkj = self.wkj + pd_k_all.T * out2 *self.rate_weight + self.vji = self.vji + pd_j_all.T * out1 * self.rate_weight + #upgrade threshold + self.thre3 = self.thre3 - pd_k_all * self.rate_thre + self.thre2 = self.thre2 - pd_j_all * self.rate_thre + #calculate sum of error + errors = np.sum(abs((data_teach[g] - out3))) + + alle = alle + errors + final_out.extend(out3.getA().tolist()) + final_out3 = [list(map(self.do_round,each)) for each in final_out] + + rp = rp + 1 + mse = alle/patterns + all_mse.append(mse) + def draw_error(): + yplot = [error_accuracy for i in range(int(n_repeat * 1.2))] + plt.plot(all_mse, '+-') + plt.plot(yplot, 'r--') + plt.xlabel('Learning Times') + plt.ylabel('All_mse') + plt.grid(True,alpha = 0.7) + plt.show() + print('------------------Training Complished---------------------') + print(' - - Training epoch: ', rp, ' - - Mse: %.6f'%mse) + print(' - - Last Output: ', final_out3) + if draw_e: + draw_error() + + def predict(self,data_test): + ''' + :param data_test: data test, numpy.ndarray + :return: predict output data + ''' + data_test = np.asarray(data_test) + produce_out = [] + print('-------------------Start Testing-------------------------') + print(' - - Shape: Test_Data ',np.shape(data_test)) + print(np.shape(data_test)) + for g in range(np.shape(data_test)[0]): + + net_i = data_test[g] + out1 = net_i + + net_j = out1 * self.vji.T - self.thre2 + out2 = self.sig(net_j) + + net_k = out2 * self.wkj.T - self.thre3 + out3 = self.sig(net_k) + produce_out.extend(out3.getA().tolist()) + res = [list(map(self.do_round,each)) for each in produce_out] + return np.asarray(res) + + +def main(): + #I will fish the mian function later + pass + +if __name__ == '__main__': + main() From 53b6fe15c93aa4a69d1f42710c320efa7ab5ae26 Mon Sep 17 00:00:00 2001 From: Stephen Lee <245885195@qq.com> Date: Fri, 22 Sep 2017 10:30:19 +0800 Subject: [PATCH 07/59] improve --- Neural_Network/neuralnetwork_bp3.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Neural_Network/neuralnetwork_bp3.py b/Neural_Network/neuralnetwork_bp3.py index 5c4f879eda2f..23ce7395ea87 100644 --- a/Neural_Network/neuralnetwork_bp3.py +++ b/Neural_Network/neuralnetwork_bp3.py @@ -9,7 +9,7 @@ import numpy as np import matplotlib.pyplot as plt -class Bpnw(): +class Bpnn(): def __init__(self,n_layer1,n_layer2,n_layer3,rate_w=0.3,rate_t=0.3): ''' @@ -38,7 +38,7 @@ def sig_plain(self,x): def do_round(self,x): return round(x, 3) - def trian(self,patterns,data_train, data_teach, n_repeat, error_accuracy,draw_e = bool): + def trian(self,patterns,data_train, data_teach, n_repeat, error_accuracy, draw_e=False): ''' :param patterns: the number of patterns :param data_train: training data x; numpy.ndarray @@ -127,8 +127,26 @@ def predict(self,data_test): def main(): - #I will fish the mian function later - pass + #example data + data_x = [[1,2,3,4], + [5,6,7,8], + [2,2,3,4], + [7,7,8,8]] + data_y = [[1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [0,0,0,1]] + + test_x = [[1,2,3,4], + [3,2,3,4]] + + #building network model + model = Bpnn(4,10,4) + #training the model + model.trian(patterns=4,data_train=data_x,data_teach=data_y, + n_repeat=100,error_accuracy=0.1,draw_e=True) + #predicting data + model.predict(test_x) if __name__ == '__main__': main() From 0e0e75db194ed335791a84244d82bf9b85e934b6 Mon Sep 17 00:00:00 2001 From: Stephen Lee <245885195@qq.com> Date: Fri, 22 Sep 2017 11:25:26 +0800 Subject: [PATCH 08/59] improve --- Neural_Network/neuralnetwork_bp3.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Neural_Network/neuralnetwork_bp3.py b/Neural_Network/neuralnetwork_bp3.py index 23ce7395ea87..896411a5df2a 100644 --- a/Neural_Network/neuralnetwork_bp3.py +++ b/Neural_Network/neuralnetwork_bp3.py @@ -49,9 +49,9 @@ def trian(self,patterns,data_train, data_teach, n_repeat, error_accuracy, draw_e ''' data_train = np.asarray(data_train) data_teach = np.asarray(data_teach) - print('-------------------Start Training-------------------------') - print(' - - Shape: Train_Data ',np.shape(data_train)) - print(' - - Shape: Teach_Data ',np.shape(data_teach)) + # print('-------------------Start Training-------------------------') + # print(' - - Shape: Train_Data ',np.shape(data_train)) + # print(' - - Shape: Teach_Data ',np.shape(data_teach)) rp = 0 all_mse = [] mse = 10000 @@ -95,9 +95,9 @@ def draw_error(): plt.ylabel('All_mse') plt.grid(True,alpha = 0.7) plt.show() - print('------------------Training Complished---------------------') - print(' - - Training epoch: ', rp, ' - - Mse: %.6f'%mse) - print(' - - Last Output: ', final_out3) + # print('------------------Training Complished---------------------') + # print(' - - Training epoch: ', rp, ' - - Mse: %.6f'%mse) + # print(' - - Last Output: ', final_out3) if draw_e: draw_error() @@ -108,9 +108,9 @@ def predict(self,data_test): ''' data_test = np.asarray(data_test) produce_out = [] - print('-------------------Start Testing-------------------------') - print(' - - Shape: Test_Data ',np.shape(data_test)) - print(np.shape(data_test)) + # print('-------------------Start Testing-------------------------') + # print(' - - Shape: Test_Data ',np.shape(data_test)) + # print(np.shape(data_test)) for g in range(np.shape(data_test)[0]): net_i = data_test[g] From 52ee9a1e128c137793f08f69f4835b67f3b9c5d1 Mon Sep 17 00:00:00 2001 From: Stephen Lee <245885195@qq.com> Date: Fri, 22 Sep 2017 14:34:28 +0800 Subject: [PATCH 09/59] commit convolution_neural_network.py --- Neural_Network/convolution_neural_network.py | 343 +++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 Neural_Network/convolution_neural_network.py diff --git a/Neural_Network/convolution_neural_network.py b/Neural_Network/convolution_neural_network.py new file mode 100644 index 000000000000..539c315a0ac2 --- /dev/null +++ b/Neural_Network/convolution_neural_network.py @@ -0,0 +1,343 @@ +#-*- coding: utf-8 -*- + +''' + - - - - - -- - - - - - - - - - - - - - - - - - - - - - - + Name - - CNN - Convolution Neural Network For Photo Recognizing + Goal - - Recognize Handing Writting Word Photo + Detail:Total 5 layers neural network + * Convolution layer + * Pooling layer + * Input layer layer of BP + * Hiden layer of BP + * Output layer of BP + Author: Stephen Lee + Program: PYTHON + Date: 2017.9.20 + - - - - - -- - - - - - - - - - - - - - - - - - - - - - - + ''' +import numpy as np +import matplotlib.pyplot as plt + + +class CNN(): + conv1 = [] + w_conv1 = [] + thre_conv1 = [] + step_conv1 = 0 + size_pooling1 = 0 + num_bp1 = 0 + num_bp2 = 0 + num_bp3 = 0 + thre_bp1 = [] + thre_bp2 = [] + wkj = np.mat([]) + vji = np.mat([]) + rate_weight = 0 + rate_thre = 0 + + + def __init__(self,conv1_get,size_p1,bp_num1,bp_num2,bp_num3,rate_w=0.2,rate_t=0.2): + ''' + :param conv1_get: [a,c,d],size, number, step of convolution kernel + :param size_p1: pooling size + :param bp_num1: units number of flatten layer + :param bp_num2: units number of hidden layer + :param bp_num3: units number of output layer + :param rate_w: rate of weight learning + :param rate_t: rate of threshold learning + ''' + self.num_bp1 = bp_num1 + self.num_bp2 = bp_num2 + self.num_bp3 = bp_num3 + self.conv1 = conv1_get[:2] + self.step_conv1 = conv1_get[2] + self.size_pooling1 = size_p1 + self.rate_weight = rate_w + self.rate_thre = rate_t + self.w_conv1 = [np.mat(-1*np.random.rand(self.conv1[0],self.conv1[0])+0.5) for i in range(self.conv1[1])] + self.wkj = np.mat(-1 * np.random.rand(self.num_bp3, self.num_bp2) + 0.5) + self.vji = np.mat(-1*np.random.rand(self.num_bp2, self.num_bp1)+0.5) + self.thre_conv1 = -2*np.random.rand(self.conv1[1])+1 + self.thre_bp2 = -2*np.random.rand(self.num_bp2)+1 + self.thre_bp3 = -2*np.random.rand(self.num_bp3)+1 + + + def save_model(self,save_path): + #将模型保存 + import pickle + model_dic = {'num_bp1':self.num_bp1, + 'num_bp2':self.num_bp2, + 'num_bp3':self.num_bp3, + 'conv1':self.conv1, + 'step_conv1':self.step_conv1, + 'size_pooling1':self.size_pooling1, + 'rate_weight':self.rate_weight, + 'rate_thre':self.rate_thre, + 'w_conv1':self.w_conv1, + 'wkj':self.wkj, + 'vji':self.vji, + 'thre_conv1':self.thre_conv1, + 'thre_bp2':self.thre_bp2, + 'thre_bp3':self.thre_bp3} + with open(save_path, 'wb') as f: + pickle.dump(model_dic, f) + + print('模型已经保存: %s'% save_path) + + + def paste_model(self,save_path): + #实例方法, + #虽然这么写一点也不简洁。。。。 + #卸载这个里面的话,只是用于修改已经存在的模型,要根据读取的数据返回实例的模型,再写一个吧 + import pickle + with open(save_path, 'rb') as f: + model_dic = pickle.load(f) + self.num_bp1 = model_dic.get('num_bp1') + self.num_bp2 = model_dic.get('num_bp2') + self.num_bp3 = model_dic.get('num_bp3') + self.conv1 = model_dic.get('conv1') + self.step_conv1 = model_dic.get('step_conv1') + self.size_pooling1 = model_dic.get('size_pooling1') + self.rate_weight = model_dic.get('rate_weight') + self.rate_thre = model_dic.get('rate_thre') + self.w_conv1 = model_dic.get('w_conv1') + self.wkj = model_dic.get('wkj') + self.vji = model_dic.get('vji') + self.thre_conv1 = model_dic.get('thre_conv1') + self.thre_bp2 = model_dic.get('thre_bp2') + self.thre_bp3 = model_dic.get('thre_bp3') + print('已经成功读取模型') + + @classmethod + def ReadModel(cls,model_path): + #类方法,读取保存的模型,返回一个实例。 + import pickle + with open(model_path, 'rb') as f: + model_dic = pickle.load(f) + + conv_get= model_dic.get('conv1') + conv_get.append(model_dic.get('step_conv1')) + size_p1 = model_dic.get('size_pooling1') + bp1 = model_dic.get('num_bp1') + bp2 = model_dic.get('num_bp2') + bp3 = model_dic.get('num_bp3') + r_w = model_dic.get('rate_weight') + r_t = model_dic.get('rate_thre') + #创建实例 + conv_ins = CNN(conv_get,size_p1,bp1,bp2,bp3,r_w,r_t) + #修改实例的参数 + conv_ins.w_conv1 = model_dic.get('w_conv1') + conv_ins.wkj = model_dic.get('wkj') + conv_ins.vji = model_dic.get('vji') + conv_ins.thre_conv1 = model_dic.get('thre_conv1') + conv_ins.thre_bp2 = model_dic.get('thre_bp2') + conv_ins.thre_bp3 = model_dic.get('thre_bp3') + return conv_ins + + + def sig(self,x): + return 1 / (1 + np.exp(-1*x)) + def do_round(self,x): + return round(x, 3) + #卷积 + def Convolute(self,data,convs,w_convs,thre_convs,conv_step): + size_conv = convs[0] + num_conv =convs[1] + size_data = np.shape(data)[0] + #得到原图像滑动的小图,data_focus + data_focus = [] + for i_focus in range(0, size_data - size_conv + 1, conv_step): + for j_focus in range(0, size_data - size_conv + 1, conv_step): + focus = data[i_focus:i_focus + size_conv, j_focus:j_focus + size_conv] + data_focus.append(focus) + #计算所有卷积核得到的特征图,每个特征图以矩阵形式,存储为一个列表data_featuremap + data_featuremap = [] + Size_FeatureMap = int((size_data - size_conv) / conv_step + 1) + for i_map in range(num_conv): + featuremap = [] + for i_focus in range(len(data_focus)): + net_focus = np.sum(np.multiply(data_focus[i_focus], w_convs[i_map])) - thre_convs[i_map] + featuremap.append(self.sig(net_focus)) + featuremap = np.asmatrix(featuremap).reshape(Size_FeatureMap, Size_FeatureMap) + data_featuremap.append(featuremap) + + #将data_focus中的focus展开为一维 + focus1_list = [] + for each_focus in data_focus: + focus1_list.extend(self.Expand_Mat(each_focus)) + focus_list = np.asarray(focus1_list) + return focus_list,data_featuremap + + # 池化 + def Pooling(self,featuremaps,size_pooling): + size_map = len(featuremaps[0]) + size_pooled = int(size_map/size_pooling) + featuremap_pooled = [] + for i_map in range(len(featuremaps)): + map = featuremaps[i_map] + map_pooled = [] + for i_focus in range(0,size_map,size_pooling): + for j_focus in range(0, size_map, size_pooling): + focus = map[i_focus:i_focus + size_pooling, j_focus:j_focus + size_pooling] + #平均池化 + map_pooled.append(np.average(focus)) + #最大池化 + #map_pooled.append(np.max(focus)) + map_pooled = np.asmatrix(map_pooled).reshape(size_pooled,size_pooled) + featuremap_pooled.append(map_pooled) + return featuremap_pooled + + def Expand(self,datas): + #将三元的数据展开为1为的list + data_expanded = [] + for i in range(len(datas)): + shapes = np.shape(datas[i]) + data_listed = datas[i].reshape(1,shapes[0]*shapes[1]) + data_listed = data_listed.getA().tolist()[0] + data_expanded.extend(data_listed) + #连接所有数据 + data_expanded = np.asarray(data_expanded) + return data_expanded + + def Expand_Mat(self,data_mat): + #用来展开矩阵为一维的list + data_mat = np.asarray(data_mat) + shapes = np.shape(data_mat) + data_expanded = data_mat.reshape(1,shapes[0]*shapes[1]) + return data_expanded + + def Getpd_From_Pool(self,out_map,pd_pool,num_map,size_map,size_pooling): + ''' + 误差反传,从pooled到前一个map, 例如将池化层6*6的误差矩阵扩大为12*12的误差矩阵 + pd_pool: 是采样层的误差,list形式。。。。要改要改 + out_map: 前面特征图的输出,数量*size*size的列表形式 + return: pd_all:前面层所有的特征图的pd, num*size_map*size_map的列表形式 + ''' + pd_all = [] + i_pool = 0 + for i_map in range(num_map): + pd_conv1 = np.ones((size_map, size_map)) + for i in range(0, size_map, size_pooling): + for j in range(0, size_map, size_pooling): + pd_conv1[i:i + size_pooling, j:j + size_pooling] = pd_pool[i_pool] + i_pool = i_pool + 1 + pd_conv2 = np.multiply(pd_conv1,np.multiply(out_map[i_map],(1-out_map[i_map]))) + pd_all.append(pd_conv2) + return pd_all + + def trian(self,patterns,datas_train, datas_teach, n_repeat, error_accuracy,draw_e = bool): + print('----------------------Start Training-------------------------') + print(' - - Shape: Train_Data ',np.shape(datas_train)) + print(' - - Shape: Teach_Data ',np.shape(datas_teach)) + rp = 0 + all_mse = [] + mse = 10000 + while rp < n_repeat and mse >= error_accuracy: + alle = 0 + print('-------------进行第%d次学习--------------'%rp) + for p in range(len(datas_train)): + #print('------------学习第%d个图像--------------'%p) + data_train = np.asmatrix(datas_train[p]) + data_teach = np.asarray(datas_teach[p]) + data_focus1,data_conved1 = self.Convolute(data_train,self.conv1,self.w_conv1, + self.thre_conv1,conv_step=self.step_conv1) + data_pooled1 = self.Pooling(data_conved1,self.size_pooling1) + shape_featuremap1 = np.shape(data_conved1) + ''' + print(' -----original shape ', np.shape(data_train)) + print(' ---- after convolution ',np.shape(data_conv1)) + print(' -----after pooling ',np.shape(data_pooled1)) + ''' + data_bp_input = self.Expand(data_pooled1) + # 计算第一层输入输出 + bp_out1 = data_bp_input + # 计算第二层输入输出 + bp_net_j = np.dot(bp_out1,self.vji.T) - self.thre_bp2 + bp_out2 = self.sig(bp_net_j) + # 计算第三层输入输出 + bp_net_k = np.dot(bp_out2 ,self.wkj.T) - self.thre_bp3 + bp_out3 = self.sig(bp_net_k) + + # 计算一般化误差 + pd_k_all = np.multiply((data_teach - bp_out3), np.multiply(bp_out3, (1 - bp_out3))) + pd_j_all = np.multiply(np.dot(pd_k_all,self.wkj), np.multiply(bp_out2, (1 - bp_out2))) + pd_i_all = np.dot(pd_j_all,self.vji) + + pd_conv1_pooled = pd_i_all / (self.size_pooling1*self.size_pooling1) + pd_conv1_pooled = pd_conv1_pooled.T.getA().tolist() + pd_conv1_all = self.Getpd_From_Pool(data_conved1,pd_conv1_pooled,shape_featuremap1[0], + shape_featuremap1[1],self.size_pooling1) + + #卷积层1的权重和阈值修正,每个卷积核的权重需要修正 12*12(map) 次 + #修正量为featuremap中点的偏导值 乘以 前一层图像focus, 整个权重模板一起更新 + for k_conv in range(self.conv1[1]): + pd_conv_list = self.Expand_Mat(pd_conv1_all[k_conv]) + delta_w = self.rate_weight * np.dot(pd_conv_list,data_focus1) + + self.w_conv1[k_conv] = self.w_conv1[k_conv] + delta_w.reshape((self.conv1[0],self.conv1[0])) + + self.thre_conv1[k_conv] = self.thre_conv1[k_conv] - np.sum(pd_conv1_all[k_conv]) * self.rate_thre + # 更新kj层的权重 + + self.wkj = self.wkj + pd_k_all.T * bp_out2 * self.rate_weight + # 更新ji层的权重 + self.vji = self.vji + pd_j_all.T * bp_out1 * self.rate_weight + # 更新阈值 + self.thre_bp3 = self.thre_bp3 - pd_k_all * self.rate_thre + self.thre_bp2 = self.thre_bp2 - pd_j_all * self.rate_thre + # 计算总误差 + errors = np.sum(abs((data_teach - bp_out3))) + alle = alle + errors + #print(' ----Teach ',data_teach) + #print(' ----BP_output ',bp_out3) + rp = rp + 1 + mse = alle/patterns + all_mse.append(mse) + def draw_error(): + yplot = [error_accuracy for i in range(int(n_repeat * 1.2))] + plt.plot(all_mse, '+-') + plt.plot(yplot, 'r--') + plt.xlabel('Learning Times') + plt.ylabel('All_mse') + plt.grid(True, alpha=0.5) + plt.show() + print('------------------Training Complished---------------------') + print(' - - Training epoch: ', rp, ' - - Mse: %.6f' % mse) + if draw_e: + draw_error() + return mse + + def produce(self,datas_test): + #对验证和测试数据集进行输出 + produce_out = [] + print('-------------------Start Testing-------------------------') + print(' - - Shape: Test_Data ',np.shape(datas_test)) + for p in range(len(datas_test)): + print('--------测试第%d个图像----------' % p) + data_test = np.asmatrix(datas_test[p]) + data_focus1, data_conved1 = self.Convolute(data_test, self.conv1, self.w_conv1, + self.thre_conv1, conv_step=self.step_conv1) + data_pooled1 = self.Pooling(data_conved1, self.size_pooling1) + data_bp_input = self.Expand(data_pooled1) + # 计算第一层输入输出 + bp_out1 = data_bp_input + # 计算第二层输入输出 + bp_net_j = bp_out1 * self.vji.T - self.thre_bp2 + bp_out2 = self.sig(bp_net_j) + # 计算第三层输入输出 + bp_net_k = bp_out2 * self.wkj.T - self.thre_bp3 + bp_out3 = self.sig(bp_net_k) + produce_out.extend(bp_out3.getA().tolist()) + res = [list(map(self.do_round,each)) for each in produce_out] + return np.asarray(res) + + def convolution(self,data): + #返回卷积和池化后的数据,用于查看图像 + data_test = np.asmatrix(data) + data_focus1, data_conved1 = self.Convolute(data_test, self.conv1, self.w_conv1, + self.thre_conv1, conv_step=self.step_conv1) + data_pooled1 = self.Pooling(data_conved1, self.size_pooling1) + + return data_conved1,data_pooled1 + + From 6e61ac19cd50288175b7b2c94d93133adc69492d Mon Sep 17 00:00:00 2001 From: Stephen Lee <245885195@qq.com> Date: Fri, 22 Sep 2017 14:56:20 +0800 Subject: [PATCH 10/59] commit convolution_neural_network.py --- Neural_Network/convolution_neural_network.py | 158 +++++++------------ 1 file changed, 60 insertions(+), 98 deletions(-) diff --git a/Neural_Network/convolution_neural_network.py b/Neural_Network/convolution_neural_network.py index 539c315a0ac2..d8ab0d2e572b 100644 --- a/Neural_Network/convolution_neural_network.py +++ b/Neural_Network/convolution_neural_network.py @@ -11,30 +11,15 @@ * Hiden layer of BP * Output layer of BP Author: Stephen Lee - Program: PYTHON + Github: 245885195@qq.com Date: 2017.9.20 - - - - - -- - - - - - - - - - - - - - - - - - - - - - - ''' + import numpy as np import matplotlib.pyplot as plt - class CNN(): - conv1 = [] - w_conv1 = [] - thre_conv1 = [] - step_conv1 = 0 - size_pooling1 = 0 - num_bp1 = 0 - num_bp2 = 0 - num_bp3 = 0 - thre_bp1 = [] - thre_bp2 = [] - wkj = np.mat([]) - vji = np.mat([]) - rate_weight = 0 - rate_thre = 0 - def __init__(self,conv1_get,size_p1,bp_num1,bp_num2,bp_num3,rate_w=0.2,rate_t=0.2): ''' @@ -63,7 +48,7 @@ def __init__(self,conv1_get,size_p1,bp_num1,bp_num2,bp_num3,rate_w=0.2,rate_t=0. def save_model(self,save_path): - #将模型保存 + #save model dict with pickle import pickle model_dic = {'num_bp1':self.num_bp1, 'num_bp2':self.num_bp2, @@ -82,35 +67,11 @@ def save_model(self,save_path): with open(save_path, 'wb') as f: pickle.dump(model_dic, f) - print('模型已经保存: %s'% save_path) - - - def paste_model(self,save_path): - #实例方法, - #虽然这么写一点也不简洁。。。。 - #卸载这个里面的话,只是用于修改已经存在的模型,要根据读取的数据返回实例的模型,再写一个吧 - import pickle - with open(save_path, 'rb') as f: - model_dic = pickle.load(f) - self.num_bp1 = model_dic.get('num_bp1') - self.num_bp2 = model_dic.get('num_bp2') - self.num_bp3 = model_dic.get('num_bp3') - self.conv1 = model_dic.get('conv1') - self.step_conv1 = model_dic.get('step_conv1') - self.size_pooling1 = model_dic.get('size_pooling1') - self.rate_weight = model_dic.get('rate_weight') - self.rate_thre = model_dic.get('rate_thre') - self.w_conv1 = model_dic.get('w_conv1') - self.wkj = model_dic.get('wkj') - self.vji = model_dic.get('vji') - self.thre_conv1 = model_dic.get('thre_conv1') - self.thre_bp2 = model_dic.get('thre_bp2') - self.thre_bp3 = model_dic.get('thre_bp3') - print('已经成功读取模型') + print('Model saved: %s'% save_path) @classmethod def ReadModel(cls,model_path): - #类方法,读取保存的模型,返回一个实例。 + #read saved model import pickle with open(model_path, 'rb') as f: model_dic = pickle.load(f) @@ -123,9 +84,9 @@ def ReadModel(cls,model_path): bp3 = model_dic.get('num_bp3') r_w = model_dic.get('rate_weight') r_t = model_dic.get('rate_thre') - #创建实例 + #create model instance conv_ins = CNN(conv_get,size_p1,bp1,bp2,bp3,r_w,r_t) - #修改实例的参数 + #modify model parameter conv_ins.w_conv1 = model_dic.get('w_conv1') conv_ins.wkj = model_dic.get('wkj') conv_ins.vji = model_dic.get('vji') @@ -137,20 +98,22 @@ def ReadModel(cls,model_path): def sig(self,x): return 1 / (1 + np.exp(-1*x)) + def do_round(self,x): return round(x, 3) - #卷积 - def Convolute(self,data,convs,w_convs,thre_convs,conv_step): + + def convolute(self,data,convs,w_convs,thre_convs,conv_step): + #convolution process size_conv = convs[0] num_conv =convs[1] size_data = np.shape(data)[0] - #得到原图像滑动的小图,data_focus + #get the data slice of original image data, data_focus data_focus = [] for i_focus in range(0, size_data - size_conv + 1, conv_step): for j_focus in range(0, size_data - size_conv + 1, conv_step): focus = data[i_focus:i_focus + size_conv, j_focus:j_focus + size_conv] data_focus.append(focus) - #计算所有卷积核得到的特征图,每个特征图以矩阵形式,存储为一个列表data_featuremap + #caculate the feature map of every single kernel, and saved as list of matrix data_featuremap = [] Size_FeatureMap = int((size_data - size_conv) / conv_step + 1) for i_map in range(num_conv): @@ -161,15 +124,15 @@ def Convolute(self,data,convs,w_convs,thre_convs,conv_step): featuremap = np.asmatrix(featuremap).reshape(Size_FeatureMap, Size_FeatureMap) data_featuremap.append(featuremap) - #将data_focus中的focus展开为一维 + #expanding the data slice to One dimenssion focus1_list = [] for each_focus in data_focus: focus1_list.extend(self.Expand_Mat(each_focus)) focus_list = np.asarray(focus1_list) return focus_list,data_featuremap - # 池化 - def Pooling(self,featuremaps,size_pooling): + def pooling(self,featuremaps,size_pooling,type='average_pool'): + #pooling process size_map = len(featuremaps[0]) size_pooled = int(size_map/size_pooling) featuremap_pooled = [] @@ -179,39 +142,40 @@ def Pooling(self,featuremaps,size_pooling): for i_focus in range(0,size_map,size_pooling): for j_focus in range(0, size_map, size_pooling): focus = map[i_focus:i_focus + size_pooling, j_focus:j_focus + size_pooling] - #平均池化 - map_pooled.append(np.average(focus)) - #最大池化 - #map_pooled.append(np.max(focus)) + if type == 'average_pool': + #average pooling + map_pooled.append(np.average(focus)) + elif type == 'max_pooling': + #max pooling + map_pooled.append(np.max(focus)) map_pooled = np.asmatrix(map_pooled).reshape(size_pooled,size_pooled) featuremap_pooled.append(map_pooled) return featuremap_pooled - def Expand(self,datas): - #将三元的数据展开为1为的list + def _expand(self,datas): + #expanding three dimension data to one dimension list data_expanded = [] for i in range(len(datas)): shapes = np.shape(datas[i]) data_listed = datas[i].reshape(1,shapes[0]*shapes[1]) data_listed = data_listed.getA().tolist()[0] data_expanded.extend(data_listed) - #连接所有数据 data_expanded = np.asarray(data_expanded) return data_expanded - def Expand_Mat(self,data_mat): - #用来展开矩阵为一维的list + def _expand_mat(self,data_mat): + #expanding matrix to one dimension list data_mat = np.asarray(data_mat) shapes = np.shape(data_mat) data_expanded = data_mat.reshape(1,shapes[0]*shapes[1]) return data_expanded - def Getpd_From_Pool(self,out_map,pd_pool,num_map,size_map,size_pooling): + def _calculate_gradient_from_pool(self,out_map,pd_pool,num_map,size_map,size_pooling): ''' - 误差反传,从pooled到前一个map, 例如将池化层6*6的误差矩阵扩大为12*12的误差矩阵 - pd_pool: 是采样层的误差,list形式。。。。要改要改 - out_map: 前面特征图的输出,数量*size*size的列表形式 - return: pd_all:前面层所有的特征图的pd, num*size_map*size_map的列表形式 + calcluate the gradient from the data slice of pool layer + pd_pool: list of matrix + out_map: the shape of data slice(size_map*size_map) + return: pd_all: list of matrix, [num, size_map, size_map] ''' pd_all = [] i_pool = 0 @@ -226,6 +190,7 @@ def Getpd_From_Pool(self,out_map,pd_pool,num_map,size_map,size_pooling): return pd_all def trian(self,patterns,datas_train, datas_teach, n_repeat, error_accuracy,draw_e = bool): + #model traning print('----------------------Start Training-------------------------') print(' - - Shape: Train_Data ',np.shape(datas_train)) print(' - - Shape: Teach_Data ',np.shape(datas_teach)) @@ -234,58 +199,53 @@ def trian(self,patterns,datas_train, datas_teach, n_repeat, error_accuracy,draw_ mse = 10000 while rp < n_repeat and mse >= error_accuracy: alle = 0 - print('-------------进行第%d次学习--------------'%rp) + print('-------------Learning Time %d--------------'%rp) for p in range(len(datas_train)): - #print('------------学习第%d个图像--------------'%p) + #print('------------Learning Image: %d--------------'%p) data_train = np.asmatrix(datas_train[p]) data_teach = np.asarray(datas_teach[p]) - data_focus1,data_conved1 = self.Convolute(data_train,self.conv1,self.w_conv1, + data_focus1,data_conved1 = self.convolute(data_train,self.conv1,self.w_conv1, self.thre_conv1,conv_step=self.step_conv1) - data_pooled1 = self.Pooling(data_conved1,self.size_pooling1) + data_pooled1 = self.pooling(data_conved1,self.size_pooling1) shape_featuremap1 = np.shape(data_conved1) ''' print(' -----original shape ', np.shape(data_train)) print(' ---- after convolution ',np.shape(data_conv1)) print(' -----after pooling ',np.shape(data_pooled1)) ''' - data_bp_input = self.Expand(data_pooled1) - # 计算第一层输入输出 + data_bp_input = self._expand(data_pooled1) bp_out1 = data_bp_input - # 计算第二层输入输出 + bp_net_j = np.dot(bp_out1,self.vji.T) - self.thre_bp2 bp_out2 = self.sig(bp_net_j) - # 计算第三层输入输出 bp_net_k = np.dot(bp_out2 ,self.wkj.T) - self.thre_bp3 bp_out3 = self.sig(bp_net_k) - # 计算一般化误差 + #--------------Model Leaning ------------------------ + # calcluate error and gradient--------------- pd_k_all = np.multiply((data_teach - bp_out3), np.multiply(bp_out3, (1 - bp_out3))) pd_j_all = np.multiply(np.dot(pd_k_all,self.wkj), np.multiply(bp_out2, (1 - bp_out2))) pd_i_all = np.dot(pd_j_all,self.vji) pd_conv1_pooled = pd_i_all / (self.size_pooling1*self.size_pooling1) pd_conv1_pooled = pd_conv1_pooled.T.getA().tolist() - pd_conv1_all = self.Getpd_From_Pool(data_conved1,pd_conv1_pooled,shape_featuremap1[0], + pd_conv1_all = self._calculate_gradient_from_pool(data_conved1,pd_conv1_pooled,shape_featuremap1[0], shape_featuremap1[1],self.size_pooling1) - - #卷积层1的权重和阈值修正,每个卷积核的权重需要修正 12*12(map) 次 - #修正量为featuremap中点的偏导值 乘以 前一层图像focus, 整个权重模板一起更新 + #weight and threshold learning process--------- + #convolution layer for k_conv in range(self.conv1[1]): - pd_conv_list = self.Expand_Mat(pd_conv1_all[k_conv]) + pd_conv_list = self._expand_mat(pd_conv1_all[k_conv]) delta_w = self.rate_weight * np.dot(pd_conv_list,data_focus1) self.w_conv1[k_conv] = self.w_conv1[k_conv] + delta_w.reshape((self.conv1[0],self.conv1[0])) self.thre_conv1[k_conv] = self.thre_conv1[k_conv] - np.sum(pd_conv1_all[k_conv]) * self.rate_thre - # 更新kj层的权重 - + #all connected layer self.wkj = self.wkj + pd_k_all.T * bp_out2 * self.rate_weight - # 更新ji层的权重 self.vji = self.vji + pd_j_all.T * bp_out1 * self.rate_weight - # 更新阈值 self.thre_bp3 = self.thre_bp3 - pd_k_all * self.rate_thre self.thre_bp2 = self.thre_bp2 - pd_j_all * self.rate_thre - # 计算总误差 + # calculate the sum error of all single image errors = np.sum(abs((data_teach - bp_out3))) alle = alle + errors #print(' ----Teach ',data_teach) @@ -307,24 +267,21 @@ def draw_error(): draw_error() return mse - def produce(self,datas_test): - #对验证和测试数据集进行输出 + def predict(self,datas_test): + #model predict produce_out = [] print('-------------------Start Testing-------------------------') print(' - - Shape: Test_Data ',np.shape(datas_test)) for p in range(len(datas_test)): - print('--------测试第%d个图像----------' % p) data_test = np.asmatrix(datas_test[p]) - data_focus1, data_conved1 = self.Convolute(data_test, self.conv1, self.w_conv1, + data_focus1, data_conved1 = self.convolute(data_test, self.conv1, self.w_conv1, self.thre_conv1, conv_step=self.step_conv1) - data_pooled1 = self.Pooling(data_conved1, self.size_pooling1) - data_bp_input = self.Expand(data_pooled1) - # 计算第一层输入输出 + data_pooled1 = self.pooling(data_conved1, self.size_pooling1) + data_bp_input = self._expand(data_pooled1) + bp_out1 = data_bp_input - # 计算第二层输入输出 bp_net_j = bp_out1 * self.vji.T - self.thre_bp2 bp_out2 = self.sig(bp_net_j) - # 计算第三层输入输出 bp_net_k = bp_out2 * self.wkj.T - self.thre_bp3 bp_out3 = self.sig(bp_net_k) produce_out.extend(bp_out3.getA().tolist()) @@ -332,12 +289,17 @@ def produce(self,datas_test): return np.asarray(res) def convolution(self,data): - #返回卷积和池化后的数据,用于查看图像 + #return the data of image after convoluting process so we can check it out data_test = np.asmatrix(data) - data_focus1, data_conved1 = self.Convolute(data_test, self.conv1, self.w_conv1, + data_focus1, data_conved1 = self.convolute(data_test, self.conv1, self.w_conv1, self.thre_conv1, conv_step=self.step_conv1) - data_pooled1 = self.Pooling(data_conved1, self.size_pooling1) + data_pooled1 = self.pooling(data_conved1, self.size_pooling1) return data_conved1,data_pooled1 +if __name__ == '__main__': + pass + ''' + I will put the example on other file + ''' \ No newline at end of file From 42c5863f4e35c382c67660e5626fb3e19a1afa41 Mon Sep 17 00:00:00 2001 From: Daniel K Date: Thu, 28 Sep 2017 10:40:22 -0400 Subject: [PATCH 11/59] Merged Graphs --- {Graphs => data_structures/Graph}/Breadth_First_Search.py | 0 {Graphs => data_structures/Graph}/Deep_First_Search.py | 0 {Graphs => data_structures/Graph}/Graph_list.py | 0 {Graphs => data_structures/Graph}/Graph_matrix.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {Graphs => data_structures/Graph}/Breadth_First_Search.py (100%) rename {Graphs => data_structures/Graph}/Deep_First_Search.py (100%) rename {Graphs => data_structures/Graph}/Graph_list.py (100%) rename {Graphs => data_structures/Graph}/Graph_matrix.py (100%) diff --git a/Graphs/Breadth_First_Search.py b/data_structures/Graph/Breadth_First_Search.py similarity index 100% rename from Graphs/Breadth_First_Search.py rename to data_structures/Graph/Breadth_First_Search.py diff --git a/Graphs/Deep_First_Search.py b/data_structures/Graph/Deep_First_Search.py similarity index 100% rename from Graphs/Deep_First_Search.py rename to data_structures/Graph/Deep_First_Search.py diff --git a/Graphs/Graph_list.py b/data_structures/Graph/Graph_list.py similarity index 100% rename from Graphs/Graph_list.py rename to data_structures/Graph/Graph_list.py diff --git a/Graphs/Graph_matrix.py b/data_structures/Graph/Graph_matrix.py similarity index 100% rename from Graphs/Graph_matrix.py rename to data_structures/Graph/Graph_matrix.py From 1958cf25c5e636e695a7cbed529a013f3a4704cd Mon Sep 17 00:00:00 2001 From: theycallmemac Date: Thu, 28 Sep 2017 20:54:15 +0100 Subject: [PATCH 12/59] added timsort.py --- sorts/timsort.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 sorts/timsort.py diff --git a/sorts/timsort.py b/sorts/timsort.py new file mode 100644 index 000000000000..04360e2560f1 --- /dev/null +++ b/sorts/timsort.py @@ -0,0 +1,68 @@ +def binary_search(the_array, item, start, end): + if start == end: + if the_array[start] > item: + return start + else: + return start + 1 + if start > end: + return start + + mid = (start + end)/ 2 + if the_array[mid] < item: + return binary_search(the_array, item, mid + 1, end) + elif the_array[mid] > item: + return binary_search(the_array, item, start, mid - 1) + else: + return mid + + +""" +Insertion sort that the heap sort uses if the array size is small or if +the size of the "run" is small +""" +def insertion_sort(the_array): + l = len(the_array) + for index in range(1, l): + value = the_array[index] + pos = binary_search(the_array, value, 0, index - 1) + the_array = the_array[:pos] + [value] + the_array[pos:index] + the_array[index+1:] + return the_array + +def merge(left, right): + """Takes two sorted lists and returns a single sorted list by comparing the + elements one at a time. + [1, 2, 3, 4, 5, 6] + """ + if not left: + return right + if not right: + return left + if left[0] < right[0]: + return [left[0]] + merge(left[1:], right) + return [right[0]] + merge(left, right[1:]) + + +def timsort(the_array): + runs, sorted_runs = [], [] + l = len(the_array) + new_run = [the_array[0]] + for i in range(1, l): + if i == l-1: + new_run.append(the_array[i]) + runs.append(new_run) + break + if the_array[i] < the_array[i-1]: + if not new_run: + runs.append([the_array[i-1]]) + new_run.append(the_array[i]) + else: + runs.append(new_run) + new_run = [] + else: + new_run.append(the_array[i]) + for each in runs: + sorted_runs.append(insertion_sort(each)) + sorted_array = [] + for run in sorted_runs: + sorted_array = merge(sorted_array, run) +print(sorted_array) From 8bae14ba1cd3d6bcd5764dc4561088abe5c4b747 Mon Sep 17 00:00:00 2001 From: Anup Kumar Panwar <1anuppanwar@gmail.com> Date: Fri, 29 Sep 2017 11:22:32 +0530 Subject: [PATCH 13/59] Update .travis.yml --- .travis.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe3ec15a6cff..1e0ad55bb43f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,19 @@ language: python python: + - "2.6" + - "2.7" - "3.2" - "3.3" - "3.4" - "3.5" + - "3.5-dev" # 3.5 development branch - "3.6" - - "3.6-dev" - -install: - - if [ "$TRAVIS_PYTHON_VERSION" == "3.2" ]; then travis_retry pip install coverage==3.7.1; fi - - if [ "$TRAVIS_PYTHON_VERSION" != "3.2" ]; then travis_retry pip install coverage; fi - - "pip install pytest pytest-cov" -script: py.test --doctest-modules --cov ./ + - "3.6-dev" # 3.6 development branch + - "3.7-dev" # 3.7 development branch + - "nightly" + +install: + - pip install -r requirements.txt + +script: + - py.test From aa8485b4dff800b7cc5d65f8a84fb7bc71f9e0a1 Mon Sep 17 00:00:00 2001 From: Anup Kumar Panwar <1anuppanwar@gmail.com> Date: Fri, 29 Sep 2017 11:28:07 +0530 Subject: [PATCH 14/59] Delete .travis.yml --- .travis.yml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1e0ad55bb43f..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: python -python: - - "2.6" - - "2.7" - - "3.2" - - "3.3" - - "3.4" - - "3.5" - - "3.5-dev" # 3.5 development branch - - "3.6" - - "3.6-dev" # 3.6 development branch - - "3.7-dev" # 3.7 development branch - - "nightly" - -install: - - pip install -r requirements.txt - -script: - - py.test From edcf6d54b6304d3e3bead3b1d2d7d14d04b70aab Mon Sep 17 00:00:00 2001 From: KuLi Date: Fri, 29 Sep 2017 23:47:24 +0200 Subject: [PATCH 15/59] #130 fixed radix sort for python 3 --- sorts/radix_sort.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index 82f8a38b451c..f19bc10e814e 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -2,19 +2,19 @@ def radixsort(lst): RADIX = 10 maxLength = False tmp , placement = -1, 1 - + while not maxLength: maxLength = True # declare and initialize buckets buckets = [list() for _ in range( RADIX )] - + # split lst between lists for i in lst: - tmp = i / placement + tmp = i // placement buckets[tmp % RADIX].append( i ) if maxLength and tmp > 0: maxLength = False - + # empty lists into lst array a = 0 for b in range( RADIX ): @@ -22,6 +22,6 @@ def radixsort(lst): for i in buck: lst[a] = i a += 1 - + # move to next placement *= RADIX From 4d4b0ff31a88d13e42021687b8a0cd3e5db09d78 Mon Sep 17 00:00:00 2001 From: malikshubham827 Date: Sun, 1 Oct 2017 00:06:03 +0530 Subject: [PATCH 16/59] Added Dijkstra Algorithm --- data_structures/Graph/dijkstra_algorithm.py | 211 ++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 data_structures/Graph/dijkstra_algorithm.py diff --git a/data_structures/Graph/dijkstra_algorithm.py b/data_structures/Graph/dijkstra_algorithm.py new file mode 100644 index 000000000000..c43ff37f5336 --- /dev/null +++ b/data_structures/Graph/dijkstra_algorithm.py @@ -0,0 +1,211 @@ +# Title: Dijkstra's Algorithm for finding single source shortest path from scratch +# Author: Shubham Malik +# References: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + +import math +import sys +# For storing the vertex set to retreive node with the lowest distance + + +class PriorityQueue: + # Based on Min Heap + def __init__(self): + self.cur_size = 0 + self.array = [] + self.pos = {} # To store the pos of node in array + + def isEmpty(self): + return self.cur_size == 0 + + def min_heapify(self, idx): + lc = self.left(idx) + rc = self.right(idx) + if lc < self.cur_size and self.array(lc)[0] < self.array(idx)[0]: + smallest = lc + else: + smallest = idx + if rc < self.cur_size and self.array(rc)[0] < self.array(smallest)[0]: + smallest = rc + if smallest != idx: + self.swap(idx, smallest) + self.min_heapify(smallest) + + def insert(self, tup): + # Inserts a node into the Priority Queue + self.pos[tup[1]] = self.cur_size + self.cur_size += 1 + self.array.append((sys.maxsize, tup[1])) + self.decrease_key((sys.maxsize, tup[1]), tup[0]) + + def extract_min(self): + # Removes and returns the min element at top of priority queue + min_node = self.array[0][1] + self.array[0] = self.array[self.cur_size - 1] + self.cur_size -= 1 + self.min_heapify(1) + del self.pos[min_node] + return min_node + + def left(self, i): + # returns the index of left child + return 2 * i + 1 + + def right(self, i): + # returns the index of right child + return 2 * i + 2 + + def par(self, i): + # returns the index of parent + return math.floor(i / 2) + + def swap(self, i, j): + # swaps array elements at indices i and j + # update the pos{} + self.pos[self.array[i][1]] = j + self.pos[self.array[j][1]] = i + temp = self.array[i] + self.array[i] = self.array[j] + self.array[j] = temp + + def decrease_key(self, tup, new_d): + idx = self.pos[tup[1]] + # assuming the new_d is atmost old_d + self.array[idx] = (new_d, tup[1]) + while idx > 0 and self.array[self.par(idx)][0] > self.array[idx][0]: + self.swap(idx, self.par(idx)) + idx = self.par(idx) + + +class Graph: + def __init__(self, num): + self.adjList = {} # To store graph: u -> (v,w) + self.num_nodes = num # Number of nodes in graph + # To store the distance from source vertex + self.dist = [0] * self.num_nodes + self.par = [-1] * self.num_nodes # To store the path + + def add_edge(self, u, v, w): + # Edge going from node u to v and v to u with weight w + # u (w)-> v, v (w) -> u + # Check if u already in graph + if u in self.adjList.keys(): + self.adjList[u].append((v, w)) + else: + self.adjList[u] = [(v, w)] + + # Assuming undirected graph + if v in self.adjList.keys(): + self.adjList[v].append((u, w)) + else: + self.adjList[v] = [(u, w)] + + def show_graph(self): + # u -> v(w) + for u in self.adjList: + print(u, '->', ' -> '.join(str("{}({})".format(v, w)) + for v, w in self.adjList[u])) + + def dijkstra(self, src): + # Flush old junk values in par[] + self.par = [-1] * self.num_nodes + # src is the source node + self.dist[src] = 0 + Q = PriorityQueue() + Q.insert((0, src)) # (dist from src, node) + for u in self.adjList.keys(): + if u != src: + self.dist[u] = sys.maxsize # Infinity + self.par[u] = -1 + + while not Q.isEmpty(): + u = Q.extract_min() # Returns node with the min dist from source + # Update the distance of all the neighbours of u and + # if their prev dist was INFINITY then push them in Q + for v, w in self.adjList[u]: + new_dist = self.dist[u] + w + if self.dist[v] > new_dist: + if self.dist[v] == sys.maxsize: + Q.insert((new_dist, v)) + else: + Q.decrease_key((self.dist[v], v), new_dist) + self.dist[v] = new_dist + self.par[v] = u + + # Show the shortest distances from src + self.show_distances(src) + + def show_distances(self, src): + print("Distance from node: {}".format(src)) + for u in range(self.num_nodes): + print('Node {} has distance: {}'.format(u, self.dist[u])) + + def show_path(self, src, dest): + # To show the shortest path from src to dest + # WARNING: Use it *after* calling dijkstra + path = [] + cost = 0 + temp = dest + # Backtracking from dest to src + while self.par[temp] != -1: + path.append(temp) + if temp != src: + for v, w in self.adjList[temp]: + if v == self.par[temp]: + cost += w + break + temp = self.par[temp] + path.append(src) + path.reverse() + + print('----Path to reach {} from {}----'.format(dest, src)) + for u in path: + print('{}'.format(u), end=' ') + if u != dest: + print('-> ', end='') + + print('\nTotal cost of path: ', cost) + + +if __name__ == '__main__': + graph = Graph(9) + graph.add_edge(0, 1, 4) + graph.add_edge(0, 7, 8) + graph.add_edge(1, 2, 8) + graph.add_edge(1, 7, 11) + graph.add_edge(2, 3, 7) + graph.add_edge(2, 8, 2) + graph.add_edge(2, 5, 4) + graph.add_edge(3, 4, 9) + graph.add_edge(3, 5, 14) + graph.add_edge(4, 5, 10) + graph.add_edge(5, 6, 2) + graph.add_edge(6, 7, 1) + graph.add_edge(6, 8, 6) + graph.add_edge(7, 8, 7) + graph.show_graph() + graph.dijkstra(0) + graph.show_path(0, 4) + +# OUTPUT +# 0 -> 1(4) -> 7(8) +# 1 -> 0(4) -> 2(8) -> 7(11) +# 7 -> 0(8) -> 1(11) -> 6(1) -> 8(7) +# 2 -> 1(8) -> 3(7) -> 8(2) -> 5(4) +# 3 -> 2(7) -> 4(9) -> 5(14) +# 8 -> 2(2) -> 6(6) -> 7(7) +# 5 -> 2(4) -> 3(14) -> 4(10) -> 6(2) +# 4 -> 3(9) -> 5(10) +# 6 -> 5(2) -> 7(1) -> 8(6) +# Distance from node: 0 +# Node 0 has distance: 0 +# Node 1 has distance: 4 +# Node 2 has distance: 12 +# Node 3 has distance: 19 +# Node 4 has distance: 21 +# Node 5 has distance: 11 +# Node 6 has distance: 9 +# Node 7 has distance: 8 +# Node 8 has distance: 14 +# ----Path to reach 4 from 0---- +# 0 -> 7 -> 6 -> 5 -> 4 +# Total cost of path: 21 From 2480eacdcc5927933b9f2d6de8a9f93ecaa6687b Mon Sep 17 00:00:00 2001 From: Juan Antonio Date: Sun, 1 Oct 2017 14:50:45 +0200 Subject: [PATCH 17/59] Adding Euclidean GCD algorithm --- other/euclidean_gcd.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 other/euclidean_gcd.py diff --git a/other/euclidean_gcd.py b/other/euclidean_gcd.py new file mode 100644 index 000000000000..13378379f286 --- /dev/null +++ b/other/euclidean_gcd.py @@ -0,0 +1,18 @@ +# https://en.wikipedia.org/wiki/Euclidean_algorithm + +def euclidean_gcd(a, b): + while b: + t = b + b = a % b + a = t + return a + +def main(): + print("GCD(3, 5) = " + str(euclidean_gcd(3, 5))) + print("GCD(5, 3) = " + str(euclidean_gcd(5, 3))) + print("GCD(1, 3) = " + str(euclidean_gcd(1, 3))) + print("GCD(3, 6) = " + str(euclidean_gcd(3, 6))) + print("GCD(6, 3) = " + str(euclidean_gcd(6, 3))) + +if __name__ == '__main__': + main() From a97ab2f4e433e41a38fd28307a02f412c4fb3a01 Mon Sep 17 00:00:00 2001 From: James Mc Dermott Date: Sun, 1 Oct 2017 22:13:54 +0100 Subject: [PATCH 18/59] Update timsort.py --- sorts/timsort.py | 85 ++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/sorts/timsort.py b/sorts/timsort.py index 04360e2560f1..8c75b5191328 100644 --- a/sorts/timsort.py +++ b/sorts/timsort.py @@ -1,68 +1,81 @@ -def binary_search(the_array, item, start, end): +def binary_search(lst, item, start, end): if start == end: - if the_array[start] > item: + if lst[start] > item: return start else: return start + 1 if start > end: return start - mid = (start + end)/ 2 - if the_array[mid] < item: - return binary_search(the_array, item, mid + 1, end) - elif the_array[mid] > item: - return binary_search(the_array, item, start, mid - 1) + mid = (start + end) // 2 + if lst[mid] < item: + return binary_search(lst, item, mid + 1, end) + elif lst[mid] > item: + return binary_search(lst, item, start, mid - 1) else: return mid -""" -Insertion sort that the heap sort uses if the array size is small or if -the size of the "run" is small -""" -def insertion_sort(the_array): - l = len(the_array) - for index in range(1, l): - value = the_array[index] - pos = binary_search(the_array, value, 0, index - 1) - the_array = the_array[:pos] + [value] + the_array[pos:index] + the_array[index+1:] - return the_array +def insertion_sort(lst): + length = len(lst) + + for index in range(1, length): + value = lst[index] + pos = binary_search(lst, value, 0, index - 1) + lst = lst[:pos] + [value] + lst[pos:index] + lst[index+1:] + + return lst + def merge(left, right): - """Takes two sorted lists and returns a single sorted list by comparing the - elements one at a time. - [1, 2, 3, 4, 5, 6] - """ if not left: return right + if not right: return left + if left[0] < right[0]: return [left[0]] + merge(left[1:], right) + return [right[0]] + merge(left, right[1:]) -def timsort(the_array): +def timsort(lst): runs, sorted_runs = [], [] - l = len(the_array) - new_run = [the_array[0]] - for i in range(1, l): - if i == l-1: - new_run.append(the_array[i]) + length = len(lst) + new_run = [lst[0]] + sorted_array = [] + + for i in range(1, length): + if i == length - 1: + new_run.append(lst[i]) runs.append(new_run) break - if the_array[i] < the_array[i-1]: + + if lst[i] < lst[i - 1]: if not new_run: - runs.append([the_array[i-1]]) - new_run.append(the_array[i]) + runs.append([lst[i - 1]]) + new_run.append(lst[i]) else: runs.append(new_run) new_run = [] else: - new_run.append(the_array[i]) - for each in runs: - sorted_runs.append(insertion_sort(each)) - sorted_array = [] + new_run.append(lst[i]) + + for run in runs: + sorted_runs.append(insertion_sort(run)) + for run in sorted_runs: sorted_array = merge(sorted_array, run) -print(sorted_array) + + return sorted_array + + +def main(): + + lst = [5,9,10,3,-4,5,178,92,46,-18,0,7] + sorted_lst = timsort(lst) + print(sorted_lst) + +if __name__ == '__main__': + main() From 6903d95b41206d757540f48230e245e7f28b8667 Mon Sep 17 00:00:00 2001 From: Rafael Leyva Ruiz Date: Mon, 2 Oct 2017 16:32:59 +0200 Subject: [PATCH 19/59] AVL done --- data_structures/AVL/AVL.py | 173 +++++++++++++------------------------ 1 file changed, 59 insertions(+), 114 deletions(-) diff --git a/data_structures/AVL/AVL.py b/data_structures/AVL/AVL.py index 0c34cb597eb6..9717f1b6eff7 100644 --- a/data_structures/AVL/AVL.py +++ b/data_structures/AVL/AVL.py @@ -7,34 +7,42 @@ class Node: def __init__(self, label): self.label = label + self._parent = None + self._left = None + self._right = None self.height = 0 @property def right(self): - return self.right + return self._right @right.setter def right(self, node): - node.parent = self - self.right = node + if node is not None: + node._parent = self + self._right = node @property def left(self): - return self.left + return self._left @left.setter def left(self, node): - node.parent = self - self.left = node + if node is not None: + node._parent = self + self._left = node @property def parent(self): - return self.parent + return self._parent @parent.setter def parent(self, node): - self.parent = node - self.height = self.parent.height + 1 + if node is not None: + self._parent = node + self.height = self.parent.height + 1 + else: + self.height = 0 class AVL: @@ -45,7 +53,7 @@ def __init__(self): def insert(self, value): node = Node(value) - + if self.root is None: self.root = node self.root.height = 0 @@ -65,65 +73,72 @@ def insert(self, value): else: curr_node = curr_node.right else: + node.height = dad_node.height + dad_node.height += 1 if node.label < dad_node.label: dad_node.left = node else: dad_node.right = node - - self.rebalance(dad_node) + self.rebalance(node) self.size += 1 break def rebalance(self, node): - height_right = 0 - height_left = 0 n = node + while n is not None: - height_right = 0 - height_left = 0 + height_right = n.height + height_left = n.height - if node.getRight() is not None: - height_right = node.getRight().getHeight() + if n.right is not None: + height_right = n.right.height - if node.getLeft() is not None: - height_left = node.getLeft().getHeight() + if n.left is not None: + height_left = n.left.height if abs(height_left - height_right) > 1: if height_left > height_right: - # left_child = node.getRight() - if (): + left_child = n.left + if left_child is not None: + h_right = (right_child.right.height + if (right_child.right is not None) else 0) + h_left = (right_child.left.height + if (right_child.left is not None) else 0) + if (h_left > h_right): self.rotate_left(n) break else: self.double_rotate_right(n) break else: - right_child = node.right + right_child = n.right if right_child is not None: h_right = (right_child.right.height if (right_child.right is not None) else 0) h_left = (right_child.left.height if (right_child.left is not None) else 0) - if (h_left > h_right): self.double_rotate_left(n) break else: self.rotate_right(n) break - n = n.getParent() + n = n.parent def rotate_left(self, node): - pass + aux = node.parent.label + node.parent.label = node.label + node.parent.right = Node(aux) + node.parent.right.height = node.parent.height + 1 + node.parent.left = node.right - def rotate_right(self, node): - aux = node.parent - node.parent = node - node.left = aux - print(node.parent.label) - print(node.parent.right.label) - print(node.parent.left.label) + def rotate_right(self, node): + aux = node.parent.label + node.parent.label = node.label + node.parent.left = Node(aux) + node.parent.left.height = node.parent.height + 1 + node.parent.right = node.right def double_rotate_left(self, node): self.rotate_right(node.getRight().getRight()) @@ -140,96 +155,26 @@ def empty(self): def preShow(self, curr_node): if curr_node is not None: - self.preShow(curr_node.getLeft()) - print(curr_node.getLabel(), end=" ") - self.preShow(curr_node.getRight()) + self.preShow(curr_node.left) + print(curr_node.label, end=" ") + self.preShow(curr_node.right) - def preorden(self, curr_node): + def preorder(self, curr_node): if curr_node is not None: - self.preShow(curr_node.getLeft()) - self.preShow(curr_node.getRight()) - print(curr_node.getLabel(), end=" ") + self.preShow(curr_node.left) + self.preShow(curr_node.right) + print(curr_node.label, end=" ") def getRoot(self): return self.root t = AVL() -# t.insert(1) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(2) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(3) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# print(t.getRoot().getHeight()) -# print(t.getRoot().getRight().getHeight()) t.insert(1) t.insert(2) t.insert(3) -# t.insert(4) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) +# t.preShow(t.root) # print("\n") +# t.insert(4) # t.insert(5) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(6) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(7) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(8) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(9) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(10) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(11) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(12) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(13) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(14) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) -# print("\n") -# t.insert(15) -# t.preShow(t.getRoot()) -# print("\n") -# t.preorden(t.getRoot()) +# t.preShow(t.root) +# t.preorden(t.root) From 07fb7d695ac946ad1de8ebaa12df3c99dec331a8 Mon Sep 17 00:00:00 2001 From: Anurag Kumar Date: Mon, 2 Oct 2017 21:13:43 +0530 Subject: [PATCH 20/59] added k means clustering algorithm, usage doc inside. --- machine_learning/k_means_clust.py | 172 ++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 machine_learning/k_means_clust.py diff --git a/machine_learning/k_means_clust.py b/machine_learning/k_means_clust.py new file mode 100644 index 000000000000..c19832726aef --- /dev/null +++ b/machine_learning/k_means_clust.py @@ -0,0 +1,172 @@ +'''README, Author - Anurag Kumar(mailto:anuragkumarak95@gmail.com) + +Requirements: + - sklearn + - numpy + - matplotlib + +Python: + - 3.5 + +Inputs: + - X , a 2D numpy array of features. + - k , number of clusters to create. + - initial_centroids , initial centroid values generated by utility function(mentioned in usage). + - maxiter , maximum number of iterations to process. + - heterogeneity , empty list that will be filled with hetrogeneity values if passed to kmeans func. + +Usage: + 1. define 'k' value, 'X' features array and 'hetrogeneity' empty list + + 2. create initial_centroids, + initial_centroids = get_initial_centroids( + X, + k, + seed=0 # seed value for initial centroid generation, None for randomness(default=None) + ) + + 3. find centroids and clusters using kmeans function. + + centroids, cluster_assignment = kmeans( + X, + k, + initial_centroids, + maxiter=400, + record_heterogeneity=heterogeneity, + verbose=True # whether to print logs in console or not.(default=False) + ) + + + 4. Plot the loss function, hetrogeneity values for every iteration saved in hetrogeneity list. + plot_heterogeneity( + heterogeneity, + k + ) + + 5. Have fun.. + +''' +from sklearn.metrics import pairwise_distances +import numpy as np + +TAG = 'K-MEANS-CLUST/ ' + +def get_initial_centroids(data, k, seed=None): + '''Randomly choose k data points as initial centroids''' + if seed is not None: # useful for obtaining consistent results + np.random.seed(seed) + n = data.shape[0] # number of data points + + # Pick K indices from range [0, N). + rand_indices = np.random.randint(0, n, k) + + # Keep centroids as dense format, as many entries will be nonzero due to averaging. + # As long as at least one document in a cluster contains a word, + # it will carry a nonzero weight in the TF-IDF vector of the centroid. + centroids = data[rand_indices,:] + + return centroids + +def centroid_pairwise_dist(X,centroids): + return pairwise_distances(X,centroids,metric='euclidean') + +def assign_clusters(data, centroids): + + # Compute distances between each data point and the set of centroids: + # Fill in the blank (RHS only) + distances_from_centroids = centroid_pairwise_dist(data,centroids) + + # Compute cluster assignments for each data point: + # Fill in the blank (RHS only) + cluster_assignment = np.argmin(distances_from_centroids,axis=1) + + return cluster_assignment + +def revise_centroids(data, k, cluster_assignment): + new_centroids = [] + for i in range(k): + # Select all data points that belong to cluster i. Fill in the blank (RHS only) + member_data_points = data[cluster_assignment==i] + # Compute the mean of the data points. Fill in the blank (RHS only) + centroid = member_data_points.mean(axis=0) + new_centroids.append(centroid) + new_centroids = np.array(new_centroids) + + return new_centroids + +def compute_heterogeneity(data, k, centroids, cluster_assignment): + + heterogeneity = 0.0 + for i in range(k): + + # Select all data points that belong to cluster i. Fill in the blank (RHS only) + member_data_points = data[cluster_assignment==i, :] + + if member_data_points.shape[0] > 0: # check if i-th cluster is non-empty + # Compute distances from centroid to data points (RHS only) + distances = pairwise_distances(member_data_points, [centroids[i]], metric='euclidean') + squared_distances = distances**2 + heterogeneity += np.sum(squared_distances) + + return heterogeneity + +from matplotlib import pyplot as plt +def plot_heterogeneity(heterogeneity, k): + plt.figure(figsize=(7,4)) + plt.plot(heterogeneity, linewidth=4) + plt.xlabel('# Iterations') + plt.ylabel('Heterogeneity') + plt.title('Heterogeneity of clustering over time, K={0:d}'.format(k)) + plt.rcParams.update({'font.size': 16}) + plt.show() + +def kmeans(data, k, initial_centroids, maxiter=500, record_heterogeneity=None, verbose=False): + '''This function runs k-means on given data and initial set of centroids. + maxiter: maximum number of iterations to run.(default=500) + record_heterogeneity: (optional) a list, to store the history of heterogeneity as function of iterations + if None, do not store the history. + verbose: if True, print how many data points changed their cluster labels in each iteration''' + centroids = initial_centroids[:] + prev_cluster_assignment = None + + for itr in range(maxiter): + if verbose: + print(itr, end='') + + # 1. Make cluster assignments using nearest centroids + cluster_assignment = assign_clusters(data,centroids) + + # 2. Compute a new centroid for each of the k clusters, averaging all data points assigned to that cluster. + centroids = revise_centroids(data,k, cluster_assignment) + + # Check for convergence: if none of the assignments changed, stop + if prev_cluster_assignment is not None and \ + (prev_cluster_assignment==cluster_assignment).all(): + break + + # Print number of new assignments + if prev_cluster_assignment is not None: + num_changed = np.sum(prev_cluster_assignment!=cluster_assignment) + if verbose: + print(' {0:5d} elements changed their cluster assignment.'.format(num_changed)) + + # Record heterogeneity convergence metric + if record_heterogeneity is not None: + # YOUR CODE HERE + score = compute_heterogeneity(data,k,centroids,cluster_assignment) + record_heterogeneity.append(score) + + prev_cluster_assignment = cluster_assignment[:] + + return centroids, cluster_assignment + +# Mock test below +if False: # change to true to run this test case. + import sklearn.datasets as ds + dataset = ds.load_iris() + k = 3 + heterogeneity = [] + initial_centroids = get_initial_centroids(dataset['data'], k, seed=0) + centroids, cluster_assignment = kmeans(dataset['data'], k, initial_centroids, maxiter=400, + record_heterogeneity=heterogeneity, verbose=True) + plot_heterogeneity(heterogeneity, k) \ No newline at end of file From 9ba6426aad2fee8b4676da0e04079194d197485c Mon Sep 17 00:00:00 2001 From: rudrasohan Date: Tue, 3 Oct 2017 20:29:29 +0530 Subject: [PATCH 21/59] Added A* Algorithm --- Graphs/A*.py | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Graphs/A*.py diff --git a/Graphs/A*.py b/Graphs/A*.py new file mode 100644 index 000000000000..21f346225633 --- /dev/null +++ b/Graphs/A*.py @@ -0,0 +1,101 @@ + +grid = [[0, 1, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0],#0 are free path whereas 1's are obstacles + [0, 1, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0]] + +''' +heuristic = [[9, 8, 7, 6, 5, 4], + [8, 7, 6, 5, 4, 3], + [7, 6, 5, 4, 3, 2], + [6, 5, 4, 3, 2, 1], + [5, 4, 3, 2, 1, 0]]''' + +init = [0, 0] +goal = [len(grid)-1, len(grid[0])-1] +cost = 1 + +#the cost map which pushes the path closer to the goal +heuristic = [[0 for row in range(len(grid[0]))] for col in range(len(grid))] +for i in range(len(grid)): + for j in range(len(grid[0])): + heuristic[i][j] = abs(i - goal[0]) + abs(j - goal[1]) + if grid[i][j] == 1: + heuristic[i][j] = 99 #added extra penalty in the heuristic map + + +#the actions we can take +delta = [[-1, 0 ], # go up + [ 0, -1], # go left + [ 1, 0 ], # go down + [ 0, 1 ]] # go right + + +#function to search the path +def search(grid,init,goal,cost,heuristic): + + closed = [[0 for col in range(len(grid[0]))] for row in range(len(grid))]# the referrence grid + closed[init[0]][init[1]] = 1 + action = [[0 for col in range(len(grid[0]))] for row in range(len(grid))]#the action grid + + x = init[0] + y = init[1] + g = 0 + f = g + heuristic[init[0]][init[0]] + cell = [[f, g, x, y]] + + found = False # flag that is set when search is complete + resign = False # flag set if we can't find expand + + while not found and not resign: + if len(cell) == 0: + resign = True + return "FAIL" + else: + cell.sort()#to choose the least costliest action so as to move closer to the goal + cell.reverse() + next = cell.pop() + x = next[2] + y = next[3] + g = next[1] + f = next[0] + + + if x == goal[0] and y == goal[1]: + found = True + else: + for i in range(len(delta)):#to try out different valid actions + x2 = x + delta[i][0] + y2 = y + delta[i][1] + if x2 >= 0 and x2 < len(grid) and y2 >=0 and y2 < len(grid[0]): + if closed[x2][y2] == 0 and grid[x2][y2] == 0: + g2 = g + cost + f2 = g2 + heuristic[x2][y2] + cell.append([f2, g2, x2, y2]) + closed[x2][y2] = 1 + action[x2][y2] = i + invpath = [] + x = goal[0] + y = goal[1] + invpath.append([x, y])#we get the reverse path from here + while x != init[0] or y != init[1]: + x2 = x - delta[action[x][y]][0] + y2 = y - delta[action[x][y]][1] + x = x2 + y = y2 + invpath.append([x, y]) + + path = [] + for i in range(len(invpath)): + path.append(invpath[len(invpath) - 1 - i]) + print "ACTION MAP" + for i in range(len(action)): + print action[i] + + return path + +a = search(grid,init,goal,cost,heuristic) +for i in range(len(a)): + print a[i] + From 271cc48a2bf7057c1aaf24b792691e2d9e4a881e Mon Sep 17 00:00:00 2001 From: Sohan Rudra Date: Tue, 3 Oct 2017 21:10:34 +0530 Subject: [PATCH 22/59] Update A*.py --- Graphs/A*.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graphs/A*.py b/Graphs/A*.py index 21f346225633..2ca9476e57a3 100644 --- a/Graphs/A*.py +++ b/Graphs/A*.py @@ -13,7 +13,7 @@ [5, 4, 3, 2, 1, 0]]''' init = [0, 0] -goal = [len(grid)-1, len(grid[0])-1] +goal = [len(grid)-1, len(grid[0])-1] #all coordinates are given in format [y,x] cost = 1 #the cost map which pushes the path closer to the goal From 46b82fa249a0cb4811b3bfcbe99b68c32e33181f Mon Sep 17 00:00:00 2001 From: rajnishyadav321 Date: Thu, 5 Oct 2017 01:40:12 +0530 Subject: [PATCH 23/59] Added Next Greater Element Element NGE 4 --> 5 5 --> 25 2 --> 25 25 --> -1 --- data_structures/Stacks/next.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 data_structures/Stacks/next.py diff --git a/data_structures/Stacks/next.py b/data_structures/Stacks/next.py new file mode 100644 index 000000000000..9765900c06d7 --- /dev/null +++ b/data_structures/Stacks/next.py @@ -0,0 +1,16 @@ +# Function to print element and NGE pair for all elements of list +def printNGE(arr): + + for i in range(0, len(arr), 1): + + next = -1 + for j in range(i+1, len(arr), 1): + if arr[i] < arr[j]: + next = arr[j] + break + + print(str(arr[i]) + " -- " + str(next)) + +# Driver program to test above function +arr = [11,13,21,3] +printNGE(arr) From 17e1a92f499bb3d4f8ccabe084934f76d048a92a Mon Sep 17 00:00:00 2001 From: Chris McLennon Date: Thu, 5 Oct 2017 22:24:02 -0500 Subject: [PATCH 24/59] Refactor Stack --- .../Stacks/Balanced_Parentheses.py | 27 -------- .../Stacks/Infix_To_Postfix_Conversion.py | 48 ------------- data_structures/Stacks/Stack.py | 50 -------------- .../Stacks/balanced_parentheses.py | 21 ++++++ .../Stacks/infix_to_postfix_conversion.py | 62 +++++++++++++++++ data_structures/Stacks/stack.py | 68 +++++++++++++++++++ 6 files changed, 151 insertions(+), 125 deletions(-) delete mode 100644 data_structures/Stacks/Balanced_Parentheses.py delete mode 100644 data_structures/Stacks/Infix_To_Postfix_Conversion.py delete mode 100644 data_structures/Stacks/Stack.py create mode 100644 data_structures/Stacks/balanced_parentheses.py create mode 100644 data_structures/Stacks/infix_to_postfix_conversion.py create mode 100644 data_structures/Stacks/stack.py diff --git a/data_structures/Stacks/Balanced_Parentheses.py b/data_structures/Stacks/Balanced_Parentheses.py deleted file mode 100644 index 6b7740380841..000000000000 --- a/data_structures/Stacks/Balanced_Parentheses.py +++ /dev/null @@ -1,27 +0,0 @@ -# Author: OMKAR PATHAK - -import Stack - -def parseParenthesis(string): - balanced = 1 - index = 0 - myStack = Stack.Stack(len(string)) - while (index < len(string)) and (balanced == 1): - check = string[index] - if check == '(': - myStack.push(check) - else: - if myStack.isEmpty(): - balanced = 0 - else: - myStack.pop() - index += 1 - - if balanced == 1 and myStack.isEmpty(): - return True - else: - return False - -if __name__ == '__main__': - print(parseParenthesis('((()))')) # True - print(parseParenthesis('((())')) # False diff --git a/data_structures/Stacks/Infix_To_Postfix_Conversion.py b/data_structures/Stacks/Infix_To_Postfix_Conversion.py deleted file mode 100644 index e33926a3d14c..000000000000 --- a/data_structures/Stacks/Infix_To_Postfix_Conversion.py +++ /dev/null @@ -1,48 +0,0 @@ -# Author: OMKAR PATHAK - -import Stack - -def isOperand(char): - return (ord(char) >= ord('a') and ord(char) <= ord('z')) or (ord(char) >= ord('A') and ord(char) <= ord('Z')) - -def precedence(char): - if char == '+' or char == '-': - return 1 - elif char == '*' or char == '/': - return 2 - elif char == '^': - return 3 - else: - return -1 - -def infixToPostfix(myExp, myStack): - postFix = [] - for i in range(len(myExp)): - if (isOperand(myExp[i])): - postFix.append(myExp[i]) - elif(myExp[i] == '('): - myStack.push(myExp[i]) - elif(myExp[i] == ')'): - topOperator = myStack.pop() - while(not myStack.isEmpty() and topOperator != '('): - postFix.append(topOperator) - topOperator = myStack.pop() - else: - while (not myStack.isEmpty()) and (precedence(myExp[i]) <= precedence(myStack.peek())): - postFix.append(myStack.pop()) - myStack.push(myExp[i]) - - while(not myStack.isEmpty()): - postFix.append(myStack.pop()) - return ' '.join(postFix) - -if __name__ == '__main__': - myExp = 'a+b*(c^d-e)^(f+g*h)-i' - myExp = [i for i in myExp] - print('Infix:',' '.join(myExp)) - myStack = Stack.Stack(len(myExp)) - print('Postfix:',infixToPostfix(myExp, myStack)) - - # OUTPUT: - # Infix: a + b * ( c ^ d - e ) ^ ( f + g * h ) - i - # Postfix: a b c d ^ e - f g h * + ^ * + i - diff --git a/data_structures/Stacks/Stack.py b/data_structures/Stacks/Stack.py deleted file mode 100644 index 41bbdc9d2e7e..000000000000 --- a/data_structures/Stacks/Stack.py +++ /dev/null @@ -1,50 +0,0 @@ -# Author: OMKAR PATHAK - -class Stack(object): - def __init__(self, limit = 10): - self.stack = [] - self.limit = limit - - # for printing the stack contents - def __str__(self): - return ' '.join([str(i) for i in self.stack]) - - # for pushing an element on to the stack - def push(self, data): - if len(self.stack) >= self.limit: - print('Stack Overflow') - else: - self.stack.append(data) - - # for popping the uppermost element - def pop(self): - if len(self.stack) <= 0: - return -1 - else: - return self.stack.pop() - - # for peeking the top-most element of the stack - def peek(self): - if len(self.stack) <= 0: - return -1 - else: - return self.stack[len(self.stack) - 1] - - # to check if stack is empty - def isEmpty(self): - return self.stack == [] - - # for checking the size of stack - def size(self): - return len(self.stack) - -if __name__ == '__main__': - myStack = Stack() - for i in range(10): - myStack.push(i) - print(myStack) - myStack.pop() # popping the top element - print(myStack) - myStack.peek() # printing the top element - myStack.isEmpty() - myStack.size() diff --git a/data_structures/Stacks/balanced_parentheses.py b/data_structures/Stacks/balanced_parentheses.py new file mode 100644 index 000000000000..1c9a84843fa3 --- /dev/null +++ b/data_structures/Stacks/balanced_parentheses.py @@ -0,0 +1,21 @@ +from Stack import Stack + +__author__ = 'Omkar Pathak' + + +def balanced_parentheses(parentheses): + """ Use a stack to check if a string of parentheses are balanced.""" + stack = Stack(len(parentheses)) + for parenthesis in parentheses: + if parenthesis == '(': + stack.push(parenthesis) + elif parenthesis == ')': + stack.pop() + return not stack.is_empty() + + +if __name__ == '__main__': + examples = ['((()))', '((())'] + print('Balanced parentheses demonstration:\n') + for example in examples: + print(example + ': ' + str(balanced_parentheses(example))) diff --git a/data_structures/Stacks/infix_to_postfix_conversion.py b/data_structures/Stacks/infix_to_postfix_conversion.py new file mode 100644 index 000000000000..f0a8fd072c3e --- /dev/null +++ b/data_structures/Stacks/infix_to_postfix_conversion.py @@ -0,0 +1,62 @@ +import string + +from Stack import Stack + +__author__ = 'Omkar Pathak' + + +def is_operand(char): + return char in string.ascii_letters or char in string.digits + + +def precedence(char): + """ Return integer value representing an operator's precedence, or + order of operation. + + https://en.wikipedia.org/wiki/Order_of_operations + """ + dictionary = {'+': 1, '-': 1, + '*': 2, '/': 2, + '^': 3} + return dictionary.get(char, -1) + + +def infix_to_postfix(expression): + """ Convert infix notation to postfix notation using the Shunting-yard + algorithm. + + https://en.wikipedia.org/wiki/Shunting-yard_algorithm + https://en.wikipedia.org/wiki/Infix_notation + https://en.wikipedia.org/wiki/Reverse_Polish_notation + """ + stack = Stack(len(expression)) + postfix = [] + for char in expression: + if is_operand(char): + postfix.append(char) + elif char not in {'(', ')'}: + while (not stack.is_empty() + and precedence(char) <= precedence(stack.peek())): + postfix.append(stack.pop()) + stack.push(char) + elif char == '(': + stack.push(char) + elif char == ')': + while not stack.is_empty() and stack.peek() != '(': + postfix.append(stack.pop()) + # Pop '(' from stack. If there is no '(', there is a mismatched + # parentheses. + if stack.peek() != '(': + raise ValueError('Mismatched parentheses') + stack.pop() + while not stack.is_empty(): + postfix.append(stack.pop()) + return ' '.join(postfix) + + +if __name__ == '__main__': + expression = 'a+b*(c^d-e)^(f+g*h)-i' + + print('Infix to Postfix Notation demonstration:\n') + print('Infix notation: ' + expression) + print('Postfix notation: ' + infix_to_postfix(expression)) diff --git a/data_structures/Stacks/stack.py b/data_structures/Stacks/stack.py new file mode 100644 index 000000000000..0b100abf3cd7 --- /dev/null +++ b/data_structures/Stacks/stack.py @@ -0,0 +1,68 @@ +__author__ = 'Omkar Pathak' + + +class Stack(object): + """ A stack is an abstract data type that serves as a collection of + elements with two principal operations: push() and pop(). push() adds an + element to the top of the stack, and pop() removes an element from the top + of a stack. The order in which elements come off of a stack are + Last In, First Out (LIFO). + + https://en.wikipedia.org/wiki/Stack_(abstract_data_type) + """ + + def __init__(self, limit=10): + self.stack = [] + self.limit = limit + + def __bool__(self): + return not bool(self.stack) + + def __str__(self): + return str(self.stack) + + def push(self, data): + """ Push an element to the top of the stack.""" + if len(self.stack) >= self.limit: + raise StackOverflowError + self.stack.append(data) + + def pop(self): + """ Pop an element off of the top of the stack.""" + if self.stack: + return self.stack.pop() + else: + raise IndexError('pop from an empty stack') + + def peek(self): + """ Peek at the top-most element of the stack.""" + if self.stack: + return self.stack[-1] + + def is_empty(self): + """ Check if a stack is empty.""" + return not bool(self.stack) + + def size(self): + """ Return the size of the stack.""" + return len(self.stack) + + +class StackOverflowError(BaseException): + pass + + +if __name__ == '__main__': + stack = Stack() + for i in range(10): + stack.push(i) + + print('Stack demonstration:\n') + print('Initial stack: ' + str(stack)) + print('pop(): ' + str(stack.pop())) + print('After pop(), the stack is now: ' + str(stack)) + print('peek(): ' + str(stack.peek())) + stack.push(100) + print('After push(100), the stack is now: ' + str(stack)) + print('is_empty(): ' + str(stack.is_empty())) + print('size(): ' + str(stack.size())) From e8d0c7e54a2ea80fd42f482a5a80ac0dd2bffa2b Mon Sep 17 00:00:00 2001 From: aravindiiitb Date: Fri, 6 Oct 2017 12:11:19 +0530 Subject: [PATCH 25/59] Added Code in Dynamic Programming section for Longest Strictly Increasing Subsequence in O(nlogn) time --- ...longest_increasing_subsequence_O(nlogn).py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 dynamic_programming/longest_increasing_subsequence_O(nlogn).py diff --git a/dynamic_programming/longest_increasing_subsequence_O(nlogn).py b/dynamic_programming/longest_increasing_subsequence_O(nlogn).py new file mode 100644 index 000000000000..3ebb4a137b6b --- /dev/null +++ b/dynamic_programming/longest_increasing_subsequence_O(nlogn).py @@ -0,0 +1,40 @@ +############################# +# Author: Aravind Kashyap +# File: lis.py +# comments: This programme outputs the Longest Strictly Increasing Subsequence in O(NLogN) +# Where N is the Number of elements in the list +############################# +def CeilIndex(v,l,r,key): + while r-l > 1: + m = (l + r)/2 + if v[m] >= key: + r = m + else: + l = m + + return r + + +def LongestIncreasingSubsequenceLength(v): + if(len(v) == 0): + return 0 + + tail = [0]*len(v) + length = 1 + + tail[0] = v[0] + + for i in range(1,len(v)): + if v[i] < tail[0]: + tail[0] = v[i] + elif v[i] > tail[length-1]: + tail[length] = v[i] + length += 1 + else: + tail[CeilIndex(tail,-1,length-1,v[i])] = v[i] + + return length + + +v = [2, 5, 3, 7, 11, 8, 10, 13, 6] +print LongestIncreasingSubsequenceLength(v) From 2a916b010b9ccb2aee2d8f6a7cfffd45b6a3cbc9 Mon Sep 17 00:00:00 2001 From: b1o0d4x3 Date: Fri, 6 Oct 2017 15:24:56 +0530 Subject: [PATCH 26/59] Delete P01_BreadthFirstSearch.py --- .../Graph/P01_BreadthFirstSearch.py | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 data_structures/Graph/P01_BreadthFirstSearch.py diff --git a/data_structures/Graph/P01_BreadthFirstSearch.py b/data_structures/Graph/P01_BreadthFirstSearch.py deleted file mode 100644 index 16b1b20074c1..000000000000 --- a/data_structures/Graph/P01_BreadthFirstSearch.py +++ /dev/null @@ -1,61 +0,0 @@ -# Author: OMKAR PATHAK - -class Graph(): - def __init__(self): - self.vertex = {} - - # for printing the Graph vertexes - def printGraph(self): - for i in self.vertex.keys(): - print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]])) - - # for adding the edge beween two vertexes - def addEdge(self, fromVertex, toVertex): - # check if vertex is already present, - if fromVertex in self.vertex.keys(): - self.vertex[fromVertex].append(toVertex) - else: - # else make a new vertex - self.vertex[fromVertex] = [toVertex] - - def BFS(self, startVertex): - # Take a list for stoting already visited vertexes - visited = [False] * len(self.vertex) - - # create a list to store all the vertexes for BFS - queue = [] - - # mark the source node as visited and enqueue it - visited[startVertex] = True - queue.append(startVertex) - - while queue: - startVertex = queue.pop(0) - print(startVertex, end = ' ') - - # mark all adjacent nodes as visited and print them - for i in self.vertex[startVertex]: - if visited[i] == False: - queue.append(i) - visited[i] = True - -if __name__ == '__main__': - g = Graph() - g.addEdge(0, 1) - g.addEdge(0, 2) - g.addEdge(1, 2) - g.addEdge(2, 0) - g.addEdge(2, 3) - g.addEdge(3, 3) - - g.printGraph() - print('BFS:') - g.BFS(2) - - # OUTPUT: - # 0  ->  1 -> 2 - # 1  ->  2 - # 2  ->  0 -> 3 - # 3  ->  3 - # BFS: - # 2 0 3 1 From d33044eb058b0fd5e04aef5620996cbe110589bf Mon Sep 17 00:00:00 2001 From: b1o0d4x3 Date: Fri, 6 Oct 2017 15:25:25 +0530 Subject: [PATCH 27/59] Delete P02_DepthFirstSearch.py --- data_structures/Graph/P02_DepthFirstSearch.py | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 data_structures/Graph/P02_DepthFirstSearch.py diff --git a/data_structures/Graph/P02_DepthFirstSearch.py b/data_structures/Graph/P02_DepthFirstSearch.py deleted file mode 100644 index 94ef3cb86571..000000000000 --- a/data_structures/Graph/P02_DepthFirstSearch.py +++ /dev/null @@ -1,61 +0,0 @@ -# Author: OMKAR PATHAK - -class Graph(): - def __init__(self): - self.vertex = {} - - # for printing the Graph vertexes - def printGraph(self): - print(self.vertex) - for i in self.vertex.keys(): - print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]])) - - # for adding the edge beween two vertexes - def addEdge(self, fromVertex, toVertex): - # check if vertex is already present, - if fromVertex in self.vertex.keys(): - self.vertex[fromVertex].append(toVertex) - else: - # else make a new vertex - self.vertex[fromVertex] = [toVertex] - - def DFS(self): - # visited array for storing already visited nodes - visited = [False] * len(self.vertex) - - # call the recursive helper function - for i in range(len(self.vertex)): - if visited[i] == False: - self.DFSRec(i, visited) - - def DFSRec(self, startVertex, visited): - # mark start vertex as visited - visited[startVertex] = True - - print(startVertex, end = ' ') - - # Recur for all the vertexes that are adjacent to this node - for i in self.vertex.keys(): - if visited[i] == False: - self.DFSRec(i, visited) - -if __name__ == '__main__': - g = Graph() - g.addEdge(0, 1) - g.addEdge(0, 2) - g.addEdge(1, 2) - g.addEdge(2, 0) - g.addEdge(2, 3) - g.addEdge(3, 3) - - g.printGraph() - print('DFS:') - g.DFS() - - # OUTPUT: - # 0  ->  1 -> 2 - # 1  ->  2 - # 2  ->  0 -> 3 - # 3  ->  3 - # DFS: - # 0 1 2 3 From 014786e340622f28cbd10dd901f1ce723cb20a19 Mon Sep 17 00:00:00 2001 From: KyleScharnhorst Date: Sat, 7 Oct 2017 06:47:50 -0700 Subject: [PATCH 28/59] Fix: typo in multiple files. --- dynamic_programming/fibonacci.py | 2 +- searches/binary_search.py | 2 +- searches/linear_search.py | 2 +- sorts/bogosort.py | 2 +- sorts/bubble_sort.py | 2 +- sorts/cocktail_shaker_sort.py | 2 +- sorts/gnome_sort.py | 2 +- sorts/insertion_sort.py | 2 +- sorts/merge_sort.py | 2 +- sorts/quick_sort.py | 2 +- sorts/selection_sort.py | 2 +- sorts/shell_sort.py | 2 +- traverals/binary_tree_traversals.py | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dynamic_programming/fibonacci.py b/dynamic_programming/fibonacci.py index 692cb756abff..5eaa81b3e7c7 100644 --- a/dynamic_programming/fibonacci.py +++ b/dynamic_programming/fibonacci.py @@ -30,7 +30,7 @@ def get(self, sequence_no=None): import sys print("\n********* Fibonacci Series Using Dynamic Programming ************\n") - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/searches/binary_search.py b/searches/binary_search.py index 13b54f4985a2..ce9584aa8f0b 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -137,7 +137,7 @@ def __assert_sorted(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/searches/linear_search.py b/searches/linear_search.py index 24479e45b6af..ce8098b1addc 100644 --- a/searches/linear_search.py +++ b/searches/linear_search.py @@ -41,7 +41,7 @@ def linear_search(sequence, target): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/bogosort.py b/sorts/bogosort.py index 2512dab51761..ce1982c53218 100644 --- a/sorts/bogosort.py +++ b/sorts/bogosort.py @@ -41,7 +41,7 @@ def isSorted(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/bubble_sort.py b/sorts/bubble_sort.py index 54d69e5ba389..d26adc89cd5e 100644 --- a/sorts/bubble_sort.py +++ b/sorts/bubble_sort.py @@ -41,7 +41,7 @@ def bubble_sort(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/cocktail_shaker_sort.py b/sorts/cocktail_shaker_sort.py index a2122463274e..c09d64408aff 100644 --- a/sorts/cocktail_shaker_sort.py +++ b/sorts/cocktail_shaker_sort.py @@ -23,7 +23,7 @@ def cocktail_shaker_sort(unsorted): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/gnome_sort.py b/sorts/gnome_sort.py index b353e31aab56..4f04ff38429c 100644 --- a/sorts/gnome_sort.py +++ b/sorts/gnome_sort.py @@ -21,7 +21,7 @@ def gnome_sort(unsorted): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/insertion_sort.py b/sorts/insertion_sort.py index caaa9305c968..33bd27c8f476 100644 --- a/sorts/insertion_sort.py +++ b/sorts/insertion_sort.py @@ -41,7 +41,7 @@ def insertion_sort(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/merge_sort.py b/sorts/merge_sort.py index 92a6780165ac..ca8dbc33c1e5 100644 --- a/sorts/merge_sort.py +++ b/sorts/merge_sort.py @@ -64,7 +64,7 @@ def merge_sort(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/quick_sort.py b/sorts/quick_sort.py index 8974e1bd8484..52e37b5877b1 100644 --- a/sorts/quick_sort.py +++ b/sorts/quick_sort.py @@ -42,7 +42,7 @@ def quick_sort(ARRAY): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/selection_sort.py b/sorts/selection_sort.py index 14bc804637c5..752496e98487 100644 --- a/sorts/selection_sort.py +++ b/sorts/selection_sort.py @@ -44,7 +44,7 @@ def selection_sort(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/sorts/shell_sort.py b/sorts/shell_sort.py index fdb98a570d9f..de3d84f72db2 100644 --- a/sorts/shell_sort.py +++ b/sorts/shell_sort.py @@ -45,7 +45,7 @@ def shell_sort(collection): if __name__ == '__main__': import sys - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input diff --git a/traverals/binary_tree_traversals.py b/traverals/binary_tree_traversals.py index 9cf118899059..9d14a1e7e070 100644 --- a/traverals/binary_tree_traversals.py +++ b/traverals/binary_tree_traversals.py @@ -84,7 +84,7 @@ def level_order(node): import sys print("\n********* Binary Tree Traversals ************\n") - # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin # otherwise 2.x's input builtin function is too "smart" if sys.version_info.major < 3: input_function = raw_input From b695175da3d6abac684a5385f5036046bb86abf8 Mon Sep 17 00:00:00 2001 From: Chinmoy Das Date: Sun, 8 Oct 2017 12:42:13 +0530 Subject: [PATCH 29/59] binary exponentiation --- other/binary_exponentiation.java | 77 ++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 other/binary_exponentiation.java diff --git a/other/binary_exponentiation.java b/other/binary_exponentiation.java new file mode 100644 index 000000000000..56461fc8136b --- /dev/null +++ b/other/binary_exponentiation.java @@ -0,0 +1,77 @@ +/** +* Binary Exponentiation +* This is a method to find a^b in a time complexity of O(log b) +* This is one of the most commonly used methods of finding powers. +* Also useful in cases where solution to (a^b)%c is required, +* where a,b,c can be numbers over the computers calculation limits. +*/ + +/** + * @author chinmoy159 + * @version 1.0 dated 10/08/2017 + */ +public class bin_expo +{ + /** + * function :- b_expo (int a, int b) + * returns a^b + */ + public static int b_expo(int a, int b) + { + /* + * iterative solution + */ + int res; + for (res = 1; b > 0; a *=a, b >>= 1) { + if ((b&1) == 1) { + res *= a; + } + } + return res; + /* + * recursive solution + if (b == 0) { + return 1; + } + if (b == 1) { + return a; + } + if ((b & 1) == 1) { + return a * b_expo(a*a, b >> 1); + } else { + return b_expo (a*a, b >> 1); + } + */ + } + /** + * function :- b_expo (long a, long b, long c) + * return (a^b)%c + */ + public static long b_expo(long a, long b, long c) + { + /* + * iterative solution + */ + long res; + for (res = 1l; b > 0; a *=a, b >>= 1) { + if ((b&1) == 1) { + res = ((res%c) * (a%c)) % c; + } + } + return res; + /* + * recursive solution + if (b == 0) { + return 1; + } + if (b == 1) { + return a; + } + if ((b & 1) == 1) { + return ((a%c) * (b_expo(a*a, b >> 1)%c))%c; + } else { + return b_expo (a*a, b >> 1)%c; + } + */ + } +} From 677dfe93bb25d5a4faed94ac90388c1bcd82228f Mon Sep 17 00:00:00 2001 From: Chinmoy Das Date: Sun, 8 Oct 2017 12:58:59 +0530 Subject: [PATCH 30/59] Delete binary_exponentiation.java --- other/binary_exponentiation.java | 77 -------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 other/binary_exponentiation.java diff --git a/other/binary_exponentiation.java b/other/binary_exponentiation.java deleted file mode 100644 index 56461fc8136b..000000000000 --- a/other/binary_exponentiation.java +++ /dev/null @@ -1,77 +0,0 @@ -/** -* Binary Exponentiation -* This is a method to find a^b in a time complexity of O(log b) -* This is one of the most commonly used methods of finding powers. -* Also useful in cases where solution to (a^b)%c is required, -* where a,b,c can be numbers over the computers calculation limits. -*/ - -/** - * @author chinmoy159 - * @version 1.0 dated 10/08/2017 - */ -public class bin_expo -{ - /** - * function :- b_expo (int a, int b) - * returns a^b - */ - public static int b_expo(int a, int b) - { - /* - * iterative solution - */ - int res; - for (res = 1; b > 0; a *=a, b >>= 1) { - if ((b&1) == 1) { - res *= a; - } - } - return res; - /* - * recursive solution - if (b == 0) { - return 1; - } - if (b == 1) { - return a; - } - if ((b & 1) == 1) { - return a * b_expo(a*a, b >> 1); - } else { - return b_expo (a*a, b >> 1); - } - */ - } - /** - * function :- b_expo (long a, long b, long c) - * return (a^b)%c - */ - public static long b_expo(long a, long b, long c) - { - /* - * iterative solution - */ - long res; - for (res = 1l; b > 0; a *=a, b >>= 1) { - if ((b&1) == 1) { - res = ((res%c) * (a%c)) % c; - } - } - return res; - /* - * recursive solution - if (b == 0) { - return 1; - } - if (b == 1) { - return a; - } - if ((b & 1) == 1) { - return ((a%c) * (b_expo(a*a, b >> 1)%c))%c; - } else { - return b_expo (a*a, b >> 1)%c; - } - */ - } -} From a36ca7c42f800ff24db287e72ab58f0230b4482c Mon Sep 17 00:00:00 2001 From: Chinmoy Das Date: Sun, 8 Oct 2017 12:59:18 +0530 Subject: [PATCH 31/59] Create binary_exponentiation.py --- other/binary_exponentiation.py | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 other/binary_exponentiation.py diff --git a/other/binary_exponentiation.py b/other/binary_exponentiation.py new file mode 100644 index 000000000000..57b218b5509f --- /dev/null +++ b/other/binary_exponentiation.py @@ -0,0 +1,49 @@ +""" +* Binary Exponentiation +* This is a method to find a^b in a time complexity of O(log b) +* This is one of the most commonly used methods of finding powers. +* Also useful in cases where solution to (a^b)%c is required, +* where a,b,c can be numbers over the computers calculation limits. +* Done using iteration, can also be done using recursion + +* @author chinmoy159 +* @version 1.0 dated 10/08/2017 +""" + + +def b_expo(a, b): + res = 1 + while b > 0: + if b&1: + res *= a + + a *= a + b >>= 1 + + return res + + +def b_expo(a, b, c): + res = 1 + while b > 0: + if b&1: + res = ((res%c) * (a%c)) % c + + a *= a + b >>= 1 + + return res + +""" +* Wondering how this method works ! +* It's pretty simple. +* Let's say you need to calculate a ^ b +* RULE 1 : a ^ b = (a*a) ^ (b/2) ---- example : 4 ^ 4 = (4*4) ^ (4/2) = 16 ^ 2 +* RULE 2 : IF b is ODD, then ---- a ^ b = a * (a ^ (b - 1)) :: where (b - 1) is even. +* Once b is even, repeat the process to get a ^ b +* Repeat the process till b = 1 OR b = 0, because a^1 = a AND a^0 = 1 +* +* As far as the modulo is concerned, +* the fact : (a*b) % c = ((a%c) * (b%c)) % c +* Now apply RULE 1 OR 2 whichever is required. +""" From f4c6578ece43ef1ebcdfcab448c326f72a40763c Mon Sep 17 00:00:00 2001 From: Chinmoy Das Date: Sun, 8 Oct 2017 13:00:13 +0530 Subject: [PATCH 32/59] Binary Exponentiation for a^b --- other/binary_exponentiation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/binary_exponentiation.py b/other/binary_exponentiation.py index 57b218b5509f..964a646f882b 100644 --- a/other/binary_exponentiation.py +++ b/other/binary_exponentiation.py @@ -1,5 +1,5 @@ """ -* Binary Exponentiation +* Binary Exponentiation for Powers * This is a method to find a^b in a time complexity of O(log b) * This is one of the most commonly used methods of finding powers. * Also useful in cases where solution to (a^b)%c is required, From f5917f589c6fe27a642cbf94ef6e230a40ab18f0 Mon Sep 17 00:00:00 2001 From: Chinmoy Das Date: Sun, 8 Oct 2017 13:10:05 +0530 Subject: [PATCH 33/59] Binary Exponentiation for Multiplication --- other/binary_exponentiation_2.py | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 other/binary_exponentiation_2.py diff --git a/other/binary_exponentiation_2.py b/other/binary_exponentiation_2.py new file mode 100644 index 000000000000..217a616c99fb --- /dev/null +++ b/other/binary_exponentiation_2.py @@ -0,0 +1,50 @@ +""" +* Binary Exponentiation with Multiplication +* This is a method to find a*b in a time complexity of O(log b) +* This is one of the most commonly used methods of finding result of multiplication. +* Also useful in cases where solution to (a*b)%c is required, +* where a,b,c can be numbers over the computers calculation limits. +* Done using iteration, can also be done using recursion + +* @author chinmoy159 +* @version 1.0 dated 10/08/2017 +""" + + +def b_expo(a, b): + res = 0 + while b > 0: + if b&1: + res += a + + a += a + b >>= 1 + + return res + + +def b_expo_mod(a, b, c): + res = 0 + while b > 0: + if b&1: + res = ((res%c) + (a%c)) % c + + a += a + b >>= 1 + + return res + + +""" +* Wondering how this method works ! +* It's pretty simple. +* Let's say you need to calculate a ^ b +* RULE 1 : a * b = (a+a) * (b/2) ---- example : 4 * 4 = (4+4) * (4/2) = 8 * 2 +* RULE 2 : IF b is ODD, then ---- a * b = a + (a * (b - 1)) :: where (b - 1) is even. +* Once b is even, repeat the process to get a * b +* Repeat the process till b = 1 OR b = 0, because a*1 = a AND a*0 = 0 +* +* As far as the modulo is concerned, +* the fact : (a+b) % c = ((a%c) + (b%c)) % c +* Now apply RULE 1 OR 2, whichever is required. +""" From 0393c5ad38d66d19cc7366b4bafd62cd984b049d Mon Sep 17 00:00:00 2001 From: Chinmoy Das Date: Sun, 8 Oct 2017 13:12:33 +0530 Subject: [PATCH 34/59] Update binary_exponentiation.py --- other/binary_exponentiation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/binary_exponentiation.py b/other/binary_exponentiation.py index 964a646f882b..1a30fb8fd266 100644 --- a/other/binary_exponentiation.py +++ b/other/binary_exponentiation.py @@ -23,7 +23,7 @@ def b_expo(a, b): return res -def b_expo(a, b, c): +def b_expo_mod(a, b, c): res = 1 while b > 0: if b&1: From 7447a9f9c7bdef4ceef3a93cee110525f683927d Mon Sep 17 00:00:00 2001 From: Uday Patel Date: Mon, 9 Oct 2017 03:19:39 +0100 Subject: [PATCH 35/59] Added Ternary Search Algorithm --- searches/ternary_search.py | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 searches/ternary_search.py diff --git a/searches/ternary_search.py b/searches/ternary_search.py new file mode 100644 index 000000000000..3b1c75314f4e --- /dev/null +++ b/searches/ternary_search.py @@ -0,0 +1,112 @@ +''' +This is a type of divide and conquer algorithm which divides the search space into +3 parts and finds the target value based on the property of the array or list +(usually monotonic property). + +Time Complexity : O(log3 N) +Space Complexity : O(1) +''' + +import sys + +# This is the precision for this function which can be altered. +# It is recommended for users to keep this number greater than or equal to 10. +precision = 10 + +# This is the linear search that will occur after the search space has become smaller. +def lin_search(left, right, A, target): + for i in range(left, right+1): + if(A[i] == target): + return i + +# This is the iterative method of the ternary search algorithm. +def ite_ternary_search(A, target): + left = 0 + right = len(A) - 1; + while(True): + if(left Date: Mon, 9 Oct 2017 12:36:33 -0500 Subject: [PATCH 36/59] Implementation of a regression tree in python I've implemented a basic decision tree in python as an example of how they work. Although the class I've created only works on one dimensional data sets, the reader should be able to generalize it to higher dimensions should they need to. --- machine_learning/decision_tree.py | 136 ++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 machine_learning/decision_tree.py diff --git a/machine_learning/decision_tree.py b/machine_learning/decision_tree.py new file mode 100644 index 000000000000..dfc2e16761fb --- /dev/null +++ b/machine_learning/decision_tree.py @@ -0,0 +1,136 @@ +""" +Implementation of a basic regression decision tree. +Input data set: The input data set must be 1-dimensional with continuous labels. +Output: The decision tree maps a real number input to a real number output. +""" + +import numpy as np + +class Decision_Tree: + def __init__(self, depth = 5, min_leaf_size = 5): + self.depth = depth + self.decision_boundary = 0 + self.left = None + self.right = None + self.min_leaf_size = min_leaf_size + self.prediction = None + + def mean_squared_error(self, labels, prediction): + """ + mean_squared_error: + @param labels: a one dimensional numpy array + @param prediction: a floating point value + return value: mean_squared_error calculates the error if prediction is used to estimate the labels + """ + if labels.ndim != 1: + print("Error: Input labels must be one dimensional") + + return np.mean((labels - prediction) ** 2) + + def train(self, X, y): + """ + train: + @param X: a one dimensional numpy array + @param y: a one dimensional numpy array. + The contents of y are the labels for the corresponding X values + + train does not have a return value + """ + + """ + this section is to check that the inputs conform to our dimensionality constraints + """ + if X.ndim != 1: + print("Error: Input data set must be one dimensional") + return + if len(X) != len(y): + print("Error: X and y have different lengths") + return + if y.ndim != 1: + print("Error: Data set labels must be one dimensional") + + if len(X) < 2 * self.min_leaf_size: + self.prediction = np.mean(y) + + if self.depth == 1: + self.prediction = np.mean(y) + + best_split = 0 + min_error = self.mean_squared_error(X,np.mean(y)) * 2 + + + """ + loop over all possible splits for the decision tree. find the best split. + if no split exists that is less than 2 * error for the entire array + then the data set is not split and the average for the entire array is used as the predictor + """ + for i in range(len(X)): + if len(X[:i]) < self.min_leaf_size: + continue + elif len(X[i:]) < self.min_leaf_size: + continue + else: + error_left = self.mean_squared_error(X[:i], np.mean(y[:i])) + error_right = self.mean_squared_error(X[i:], np.mean(y[i:])) + error = error_left + error_right + if error < min_error: + best_split = i + min_error = error + + if best_split != 0: + left_X = X[:best_split] + left_y = y[:best_split] + right_X = X[best_split:] + right_y = y[best_split:] + + self.decision_boundary = X[best_split] + self.left = Decision_Tree(depth = self.depth - 1, min_leaf_size = self.min_leaf_size) + self.right = Decision_Tree(depth = self.depth - 1, min_leaf_size = self.min_leaf_size) + self.left.train(left_X, left_y) + self.right.train(right_X, right_y) + else: + self.prediction = np.mean(y) + + return + + def predict(self, x): + """ + predict: + @param x: a floating point value to predict the label of + the prediction function works by recursively calling the predict function + of the appropriate subtrees based on the tree's decision boundary + """ + if self.prediction is not None: + return self.prediction + elif self.left or self.right is not None: + if x >= self.decision_boundary: + return self.right.predict(x) + else: + return self.left.predict(x) + else: + print("Error: Decision tree not yet trained") + return None + +def main(): + """ + In this demonstration we're generating a sample data set from the sin function in numpy. + We then train a decision tree on the data set and use the decision tree to predict the + label of 10 different test values. Then the mean squared error over this test is displayed. + """ + X = np.arange(-1., 1., 0.005) + y = np.sin(X) + + tree = Decision_Tree(depth = 10, min_leaf_size = 10) + tree.train(X,y) + + test_cases = (np.random.rand(10) * 2) - 1 + predictions = np.array([tree.predict(x) for x in test_cases]) + avg_error = np.mean((predictions - test_cases) ** 2) + + print("Test values: " + str(test_cases)) + print("Predictions: " + str(predictions)) + print("Average error: " + str(avg_error)) + + +if __name__ == '__main__': + main() \ No newline at end of file From 37967bd0cf9bb8b70126d2b9d763869f327021de Mon Sep 17 00:00:00 2001 From: Nathan Berger Date: Mon, 9 Oct 2017 12:42:51 -0500 Subject: [PATCH 37/59] Fixed case where function didn't return where it should I added these return statements so that invalid inputs or valid end cases would no longer continue running through the rest of the function. --- machine_learning/decision_tree.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/machine_learning/decision_tree.py b/machine_learning/decision_tree.py index dfc2e16761fb..51f600cace41 100644 --- a/machine_learning/decision_tree.py +++ b/machine_learning/decision_tree.py @@ -48,12 +48,15 @@ def train(self, X, y): return if y.ndim != 1: print("Error: Data set labels must be one dimensional") + return if len(X) < 2 * self.min_leaf_size: self.prediction = np.mean(y) + return if self.depth == 1: self.prediction = np.mean(y) + return best_split = 0 min_error = self.mean_squared_error(X,np.mean(y)) * 2 From cb3ff4a8f8fbcab28fc3bb08f32fcd5444886f8a Mon Sep 17 00:00:00 2001 From: fickleEfrit Date: Mon, 9 Oct 2017 17:26:27 -0400 Subject: [PATCH 38/59] Create quick_select.py --- searches/quick_select.py | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 searches/quick_select.py diff --git a/searches/quick_select.py b/searches/quick_select.py new file mode 100644 index 000000000000..e5e2ce99c682 --- /dev/null +++ b/searches/quick_select.py @@ -0,0 +1,47 @@ +import collections +import sys +import random +import time +import math +""" +A python implementation of the quick select algorithm, which is efficient for calculating the value that would appear in the index of a list if it would be sorted, even if it is not already sorted +https://en.wikipedia.org/wiki/Quickselect +""" +def _partition(data, pivot): + """ + Three way partition the data into smaller, equal and greater lists, + in relationship to the pivot + :param data: The data to be sorted (a list) + :param pivot: The value to partition the data on + :return: Three list: smaller, equal and greater + """ + less, equal, greater = [], [], [] + for element in data: + if element.address < pivot.address: + less.append(element) + elif element.address > pivot.address: + greater.append(element) + else: + equal.append(element) + return less, equal, greater + + def quickSelect(list, k): + #k = len(list) // 2 when trying to find the median (index that value would be when list is sorted) + smaller = [] + larger = [] + pivot = random.randint(0, len(list) - 1) + pivot = list[pivot] + count = 0 + smaller, equal, larger =_partition(list, pivot) + count = len(equal) + m = len(smaller) + + #k is the pivot + if m <= k < m + count: + return pivot + # must be in smaller + elif m > k: + return quickSelect(smaller, k) + #must be in larger + else: + return quickSelect(larger, k - (m + count)) From dc5e86b7013cb02ceb0a11f32afb4a2b8f7d3ae1 Mon Sep 17 00:00:00 2001 From: Alvin Nguyen Date: Mon, 9 Oct 2017 17:00:37 -0700 Subject: [PATCH 39/59] Fixed compilation errors, fixes for readability/convention, changed double equals to boolean equality operator 'is' --- data_structures/Graph/Breadth_First_Search.py | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/data_structures/Graph/Breadth_First_Search.py b/data_structures/Graph/Breadth_First_Search.py index 1a3fdfd4d90f..9cb2348560b2 100644 --- a/data_structures/Graph/Breadth_First_Search.py +++ b/data_structures/Graph/Breadth_First_Search.py @@ -1,9 +1,9 @@ class GRAPH: """docstring for GRAPH""" def __init__(self, nodes): - self.nodes=nodes - self.graph=[[0]*nodes for i in range (nodes)] - self.visited=[0]*nodes + self.nodes = nodes + self.graph = [[0]*nodes for i in range (nodes)] + self.visited = [0]*nodes def show(self): @@ -23,7 +23,7 @@ def bfs(self,v): v = queue[0] for u in range(self.vertex): if self.graph[v][u] == 1: - if visited[u]== False: + if visited[u] is False: visited[u] = True queue.append(u) print('%d visited' % (u +1)) @@ -41,30 +41,32 @@ def bfs(self,v): g.add_edge(5,9) g.add_edge(6,10) g.bfs(4) -======= - print self.graph + +print(self.graph) def add_edge(self, i, j): self.graph[i][j]=1 self.graph[j][i]=1 - def bfs(self,s): - queue=[s] - self.visited[s]=1 - while len(queue)!=0: - x=queue.pop(0) + def bfs(self, s): + queue = [s] + self.visited[s] = 1 + while len(queue)!= 0: + x = queue.pop(0) print(x) - for i in range(0,self.nodes): - if self.graph[x][i]==1 and self.visited[i]==0: + for i in range(0, self.nodes): + if self.graph[x][i] == 1 and self.visited[i] == 0: queue.append(i) - self.visited[i]=1 + self.visited[i] = 1 -n=int(input("Enter the number of Nodes : ")) -g=GRAPH(n) -e=int(input("Enter the no of edges : ")) +n = int(input("Enter the number of Nodes : ")) +g = GRAPH(n) +e = int(input("Enter the no of edges : ")) print("Enter the edges (u v)") -for i in range(0,e): - u,v=map(int, raw_input().split()) - g.add_edge(u,v) -s=int(input("Enter the source node :")) + +for i in range(0, e): + u ,v = map(int, raw_input().split()) + g.add_edge(u, v) + +s = int(input("Enter the source node :")) g.bfs(s) From ab058ab0b51486f892a1b59a22631eff5083c241 Mon Sep 17 00:00:00 2001 From: Alvin Nguyen Date: Mon, 9 Oct 2017 17:05:14 -0700 Subject: [PATCH 40/59] changed rigt->right, a typo fix. --- data_structures/Binary Tree/binary_seach_tree.py | 6 +++--- data_structures/Graph/Breadth_First_Search.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data_structures/Binary Tree/binary_seach_tree.py b/data_structures/Binary Tree/binary_seach_tree.py index 1dac948ae3c5..0b17265344e3 100644 --- a/data_structures/Binary Tree/binary_seach_tree.py +++ b/data_structures/Binary Tree/binary_seach_tree.py @@ -8,7 +8,7 @@ class Node: def __init__(self, label): self.label = label self.left = None - self.rigt = None + self.right = None def getLabel(self): return self.label @@ -23,10 +23,10 @@ def setLeft(self, left): self.left = left def getRight(self): - return self.rigt + return self.right def setRight(self, right): - self.rigt = right + self.right = right class BinarySearchTree: diff --git a/data_structures/Graph/Breadth_First_Search.py b/data_structures/Graph/Breadth_First_Search.py index 9cb2348560b2..92a6e819b00c 100644 --- a/data_structures/Graph/Breadth_First_Search.py +++ b/data_structures/Graph/Breadth_First_Search.py @@ -67,6 +67,6 @@ def bfs(self, s): for i in range(0, e): u ,v = map(int, raw_input().split()) g.add_edge(u, v) - + s = int(input("Enter the source node :")) g.bfs(s) From 8f71b309953fec9da78ef64ea8cc2e7314ec1b6f Mon Sep 17 00:00:00 2001 From: TaylorL19 Date: Tue, 10 Oct 2017 11:57:16 -0500 Subject: [PATCH 41/59] Fixed binary search to correctly recurse to left half and right half --- searches/binary_search.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 13b54f4985a2..8dc3008daae3 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -110,9 +110,9 @@ def binary_search_by_recursion(sorted_collection, item, left, right): if sorted_collection[midpoint] == item: return midpoint elif sorted_collection[midpoint] > item: - return binary_search_by_recursion(sorted_collection, item, left, right-1) + return binary_search_by_recursion(sorted_collection, item, left, midpoint-1) else: - return binary_search_by_recursion(sorted_collection, item, left+1, right) + return binary_search_by_recursion(sorted_collection, item, midpoint+1, right) def __assert_sorted(collection): """Check if collection is sorted, if not - raises :py:class:`ValueError` From 875c6cde16e21684b96ad5545c68ac1667b157bc Mon Sep 17 00:00:00 2001 From: Tobias Date: Tue, 10 Oct 2017 21:46:07 -0700 Subject: [PATCH 42/59] Add Linear Congruential Generator --- other/LinearCongruentialGenerator.py | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 other/LinearCongruentialGenerator.py diff --git a/other/LinearCongruentialGenerator.py b/other/LinearCongruentialGenerator.py new file mode 100644 index 000000000000..b1eaa6119754 --- /dev/null +++ b/other/LinearCongruentialGenerator.py @@ -0,0 +1,34 @@ +__author__ = "Tobias Carryer" + +from time import time + +class LinearCongruentialGenerator(object): + """ + A pseudorandom number generator. + """ + + def __init__( self, multiplier, increment, modulo, seed=int(time()) ): + """ + These parameters are saved and used when nextNumber() is called. + + modulo is the largest number that can be generated (exclusive). The most + efficent values are powers of 2. 2^32 is a common value. + """ + self.multiplier = multiplier + self.increment = increment + self.modulo = modulo + self.seed = seed + + def next_number( self ): + """ + The smallest number that can be generated is zero. + The largest number that can be generated is modulo-1. modulo is set in the constructor. + """ + self.seed = (self.multiplier * self.seed + self.increment) % self.modulo + return self.seed + +if __name__ == "__main__": + # Show the LCG in action. + lcg = LinearCongruentialGenerator(1664525, 1013904223, 2<<31) + while True : + print lcg.next_number() \ No newline at end of file From a07baadf04d3b1db9051f2ed2353abc83b35a732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kilian=20Rue=C3=9F?= Date: Thu, 12 Oct 2017 21:35:23 +0200 Subject: [PATCH 43/59] Added fastfibonacci.py --- dynamic_programming/fastfibonacci.py | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 dynamic_programming/fastfibonacci.py diff --git a/dynamic_programming/fastfibonacci.py b/dynamic_programming/fastfibonacci.py new file mode 100644 index 000000000000..5957fbe0d354 --- /dev/null +++ b/dynamic_programming/fastfibonacci.py @@ -0,0 +1,42 @@ +""" +This program calculates the nth Fibonacci number in O(log(n)). +It's possible to calculate F(1000000) in less than a second. +""" +import sys + + +# returns F(n) +def fibonacci(n: int): + if n < 0: + raise ValueError("Negative arguments are not supported") + return _fib(n)[0] + + +# returns (F(n), F(n-1)) +def _fib(n: int): + if n == 0: + # (F(0), F(1)) + return (0, 1) + else: + # F(2n) = F(n)[2F(n+1) − F(n)] + # F(2n+1) = F(n+1)^2+F(n)^2 + a, b = _fib(n // 2) + c = a * (b * 2 - a) + d = a * a + b * b + if n % 2 == 0: + return (c, d) + else: + return (d, c + d) + + +if __name__ == "__main__": + args = sys.argv[1:] + if len(args) != 1: + print("Too few or too much parameters given.") + exit(1) + try: + n = int(args[0]) + except ValueError: + print("Could not convert data to an integer.") + exit(1) + print("F(%d) = %d" % (n, fibonacci(n))) From 86a5b0345fdbdf9931f00a26d80c61f6cf23c957 Mon Sep 17 00:00:00 2001 From: Corey Hu Date: Thu, 12 Oct 2017 23:56:14 -0700 Subject: [PATCH 44/59] Recursive solution to insert_tail in singly_LinkedList --- .../LinkedList/singly_LinkedList.py | 37 +++++++------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/data_structures/LinkedList/singly_LinkedList.py b/data_structures/LinkedList/singly_LinkedList.py index 941e8a0faaa8..c9a3cec27fdc 100644 --- a/data_structures/LinkedList/singly_LinkedList.py +++ b/data_structures/LinkedList/singly_LinkedList.py @@ -3,22 +3,15 @@ def __int__(self,data): self.data=data#given data self.next=None#given next to None class Linked_List: + pass - def insert_tail(Head,data):#insert the data at tail - tamp=Head#create a tamp as a head - if(tamp==None):#if linkedlist is empty - newNod=Node()#create newNode Node type and given data and next - newNod.data=data - newNod.next=None - Head=newNod + + def insert_tail(Head,data): + if(Head.next is None): + Head.next = Node(data) else: - while tamp.next!=None:#find the last Node - tamp=tamp.next - newNod = Node()#create a new node - newNod.data = data - newNod.next = None - tamp.next=newNod#put the newnode into last node - return Head#return first node of linked list + insert_tail(Head.next, data) + def insert_head(Head,data): tamp = Head if (tamp == None): @@ -32,16 +25,18 @@ def insert_head(Head,data): newNod.next = Head#put the Head at NewNode Next Head=newNod#make a NewNode to Head return Head - def Print(Head):#print every node data - tamp=Node() + + def printList(Head):#print every node data tamp=Head while tamp!=None: print(tamp.data) tamp=tamp.next + def delete_head(Head):#delete from head if Head!=None: Head=Head.next return Head#return new Head + def delete_tail(Head):#delete from tail if Head!=None: tamp = Node() @@ -50,12 +45,6 @@ def delete_tail(Head):#delete from tail tamp = tamp.next tamp.next=None#delete the last element by give next None to 2nd last Element return Head - def isEmpty(Head): - if(Head==None):#check Head is None or Not - return True#return Ture if list is empty - else: - return False#check False if it's not empty - - - + def isEmpty(Head): + return Head is None #Return if Head is none \ No newline at end of file From e0211794da527caaa0e3621fa4a8ae60eed3c547 Mon Sep 17 00:00:00 2001 From: nandujkishor Date: Fri, 13 Oct 2017 20:33:40 +0530 Subject: [PATCH 45/59] Changed the typographical error (#132) Changed the typo in line 113 and 115 regarding recursive binary search algorithm, found by a user who commented in comments. --- searches/binary_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 8dc3008daae3..5ef0a03215db 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -113,7 +113,7 @@ def binary_search_by_recursion(sorted_collection, item, left, right): return binary_search_by_recursion(sorted_collection, item, left, midpoint-1) else: return binary_search_by_recursion(sorted_collection, item, midpoint+1, right) - + def __assert_sorted(collection): """Check if collection is sorted, if not - raises :py:class:`ValueError` From 81ab3249d418396a3f7e8d35514e9fe8c9bb412b Mon Sep 17 00:00:00 2001 From: Sachin Arora Date: Fri, 13 Oct 2017 20:45:39 +0530 Subject: [PATCH 46/59] Revert "There were 2 codes for BFS and DFS in data-structure/Graph." (#163) --- .../Graph/P01_BreadthFirstSearch.py | 61 +++++++++++++++++++ data_structures/Graph/P02_DepthFirstSearch.py | 61 +++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 data_structures/Graph/P01_BreadthFirstSearch.py create mode 100644 data_structures/Graph/P02_DepthFirstSearch.py diff --git a/data_structures/Graph/P01_BreadthFirstSearch.py b/data_structures/Graph/P01_BreadthFirstSearch.py new file mode 100644 index 000000000000..16b1b20074c1 --- /dev/null +++ b/data_structures/Graph/P01_BreadthFirstSearch.py @@ -0,0 +1,61 @@ +# Author: OMKAR PATHAK + +class Graph(): + def __init__(self): + self.vertex = {} + + # for printing the Graph vertexes + def printGraph(self): + for i in self.vertex.keys(): + print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]])) + + # for adding the edge beween two vertexes + def addEdge(self, fromVertex, toVertex): + # check if vertex is already present, + if fromVertex in self.vertex.keys(): + self.vertex[fromVertex].append(toVertex) + else: + # else make a new vertex + self.vertex[fromVertex] = [toVertex] + + def BFS(self, startVertex): + # Take a list for stoting already visited vertexes + visited = [False] * len(self.vertex) + + # create a list to store all the vertexes for BFS + queue = [] + + # mark the source node as visited and enqueue it + visited[startVertex] = True + queue.append(startVertex) + + while queue: + startVertex = queue.pop(0) + print(startVertex, end = ' ') + + # mark all adjacent nodes as visited and print them + for i in self.vertex[startVertex]: + if visited[i] == False: + queue.append(i) + visited[i] = True + +if __name__ == '__main__': + g = Graph() + g.addEdge(0, 1) + g.addEdge(0, 2) + g.addEdge(1, 2) + g.addEdge(2, 0) + g.addEdge(2, 3) + g.addEdge(3, 3) + + g.printGraph() + print('BFS:') + g.BFS(2) + + # OUTPUT: + # 0  ->  1 -> 2 + # 1  ->  2 + # 2  ->  0 -> 3 + # 3  ->  3 + # BFS: + # 2 0 3 1 diff --git a/data_structures/Graph/P02_DepthFirstSearch.py b/data_structures/Graph/P02_DepthFirstSearch.py new file mode 100644 index 000000000000..94ef3cb86571 --- /dev/null +++ b/data_structures/Graph/P02_DepthFirstSearch.py @@ -0,0 +1,61 @@ +# Author: OMKAR PATHAK + +class Graph(): + def __init__(self): + self.vertex = {} + + # for printing the Graph vertexes + def printGraph(self): + print(self.vertex) + for i in self.vertex.keys(): + print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]])) + + # for adding the edge beween two vertexes + def addEdge(self, fromVertex, toVertex): + # check if vertex is already present, + if fromVertex in self.vertex.keys(): + self.vertex[fromVertex].append(toVertex) + else: + # else make a new vertex + self.vertex[fromVertex] = [toVertex] + + def DFS(self): + # visited array for storing already visited nodes + visited = [False] * len(self.vertex) + + # call the recursive helper function + for i in range(len(self.vertex)): + if visited[i] == False: + self.DFSRec(i, visited) + + def DFSRec(self, startVertex, visited): + # mark start vertex as visited + visited[startVertex] = True + + print(startVertex, end = ' ') + + # Recur for all the vertexes that are adjacent to this node + for i in self.vertex.keys(): + if visited[i] == False: + self.DFSRec(i, visited) + +if __name__ == '__main__': + g = Graph() + g.addEdge(0, 1) + g.addEdge(0, 2) + g.addEdge(1, 2) + g.addEdge(2, 0) + g.addEdge(2, 3) + g.addEdge(3, 3) + + g.printGraph() + print('DFS:') + g.DFS() + + # OUTPUT: + # 0  ->  1 -> 2 + # 1  ->  2 + # 2  ->  0 -> 3 + # 3  ->  3 + # DFS: + # 0 1 2 3 From 974acef310bc70dc634b651d9e8ea502ae09ad04 Mon Sep 17 00:00:00 2001 From: Sachin Arora Date: Fri, 13 Oct 2017 21:03:16 +0530 Subject: [PATCH 47/59] Deleting duplicate BFS and DFS files. (#164) * Deleting duplicate file BFS. * deleting duplicate file DFS. * Rename P01_BreadthFirstSearch.py to BreadthFirstSearch.py * Rename P02_DepthFirstSearch.py to DepthFirstSearch.py --- ...thFirstSearch.py => BreadthFirstSearch.py} | 0 data_structures/Graph/Breadth_First_Search.py | 72 ------------------- data_structures/Graph/Deep_First_Search.py | 32 --------- ...epthFirstSearch.py => DepthFirstSearch.py} | 0 4 files changed, 104 deletions(-) rename data_structures/Graph/{P01_BreadthFirstSearch.py => BreadthFirstSearch.py} (100%) delete mode 100644 data_structures/Graph/Breadth_First_Search.py delete mode 100644 data_structures/Graph/Deep_First_Search.py rename data_structures/Graph/{P02_DepthFirstSearch.py => DepthFirstSearch.py} (100%) diff --git a/data_structures/Graph/P01_BreadthFirstSearch.py b/data_structures/Graph/BreadthFirstSearch.py similarity index 100% rename from data_structures/Graph/P01_BreadthFirstSearch.py rename to data_structures/Graph/BreadthFirstSearch.py diff --git a/data_structures/Graph/Breadth_First_Search.py b/data_structures/Graph/Breadth_First_Search.py deleted file mode 100644 index 92a6e819b00c..000000000000 --- a/data_structures/Graph/Breadth_First_Search.py +++ /dev/null @@ -1,72 +0,0 @@ -class GRAPH: - """docstring for GRAPH""" - def __init__(self, nodes): - self.nodes = nodes - self.graph = [[0]*nodes for i in range (nodes)] - self.visited = [0]*nodes - - - def show(self): - - for i in self.graph: - for j in i: - print(j, end=' ') - print(' ') - def bfs(self,v): - - visited = [False]*self.vertex - visited[v - 1] = True - print('%d visited' % (v)) - - queue = [v - 1] - while len(queue) > 0: - v = queue[0] - for u in range(self.vertex): - if self.graph[v][u] == 1: - if visited[u] is False: - visited[u] = True - queue.append(u) - print('%d visited' % (u +1)) - queue.pop(0) - -g = Graph(10) - -g.add_edge(1,2) -g.add_edge(1,3) -g.add_edge(1,4) -g.add_edge(2,5) -g.add_edge(3,6) -g.add_edge(3,7) -g.add_edge(4,8) -g.add_edge(5,9) -g.add_edge(6,10) -g.bfs(4) - -print(self.graph) - - def add_edge(self, i, j): - self.graph[i][j]=1 - self.graph[j][i]=1 - - def bfs(self, s): - queue = [s] - self.visited[s] = 1 - while len(queue)!= 0: - x = queue.pop(0) - print(x) - for i in range(0, self.nodes): - if self.graph[x][i] == 1 and self.visited[i] == 0: - queue.append(i) - self.visited[i] = 1 - -n = int(input("Enter the number of Nodes : ")) -g = GRAPH(n) -e = int(input("Enter the no of edges : ")) -print("Enter the edges (u v)") - -for i in range(0, e): - u ,v = map(int, raw_input().split()) - g.add_edge(u, v) - -s = int(input("Enter the source node :")) -g.bfs(s) diff --git a/data_structures/Graph/Deep_First_Search.py b/data_structures/Graph/Deep_First_Search.py deleted file mode 100644 index 656ddfbafd34..000000000000 --- a/data_structures/Graph/Deep_First_Search.py +++ /dev/null @@ -1,32 +0,0 @@ -class GRAPH: - """docstring for GRAPH""" - def __init__(self, nodes): - self.nodes=nodes - self.graph=[[0]*nodes for i in range (nodes)] - self.visited=[0]*nodes - - - def show(self): - print self.graph - - def add_edge(self, i, j): - self.graph[i][j]=1 - self.graph[j][i]=1 - - def dfs(self,s): - self.visited[s]=1 - print(s) - for i in range(0,self.nodes): - if self.visited[i]==0 and self.graph[s][i]==1: - self.dfs(i) - - -n=int(input("Enter the number of Nodes : ")) -g=GRAPH(n) -e=int(input("Enter the no of edges : ")) -print("Enter the edges (u v)") -for i in range(0,e): - u,v=map(int, raw_input().split()) - g.add_edge(u,v) -s=int(input("Enter the source node :")) -g.dfs(s) diff --git a/data_structures/Graph/P02_DepthFirstSearch.py b/data_structures/Graph/DepthFirstSearch.py similarity index 100% rename from data_structures/Graph/P02_DepthFirstSearch.py rename to data_structures/Graph/DepthFirstSearch.py From 35d38737168ebfe4eb54e829f98dc31296aa52dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Sat, 14 Oct 2017 03:07:02 +0000 Subject: [PATCH 48/59] Add counting sort --- sorts/counting_sort.py | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 sorts/counting_sort.py diff --git a/sorts/counting_sort.py b/sorts/counting_sort.py new file mode 100644 index 000000000000..13e4554aeb4c --- /dev/null +++ b/sorts/counting_sort.py @@ -0,0 +1,72 @@ +""" +This is pure python implementation of counting sort algorithm +For doctests run following command: +python -m doctest -v counting_sort.py +or +python3 -m doctest -v counting_sort.py +For manual testing run: +python counting_sort.py +""" + +from __future__ import print_function + + +def counting_sort(collection): + """Pure implementation of counting sort algorithm in Python + :param collection: some mutable ordered collection with heterogeneous + comparable items inside + :return: the same collection ordered by ascending + Examples: + >>> counting_sort([0, 5, 3, 2, 2]) + [0, 2, 2, 3, 5] + >>> counting_sort([]) + [] + >>> counting_sort([-2, -5, -45]) + [-45, -5, -2] + """ + # if the collection is empty, returns empty + if collection == []: + return [] + + # get some information about the collection + coll_len = len(collection) + coll_max = max(collection) + coll_min = min(collection) + + # create the counting array + counting_arr_length = coll_max + 1 - coll_min + counting_arr = [0] * counting_arr_length + + # count how much a number appears in the collection + for number in collection: + counting_arr[number - coll_min] += 1 + + # sum each position with it's predecessors. now, counting_arr[i] tells + # us how many elements <= i has in the collection + for i in range(1, counting_arr_length): + counting_arr[i] = counting_arr[i] + counting_arr[i-1] + + # create the output collection + ordered = [0] * coll_len + + # place the elements in the output, respecting the original order (stable + # sort) from end to begin, updating counting_arr + for i in reversed(range(0, coll_len)): + ordered[counting_arr[collection[i] - coll_min]-1] = collection[i] + counting_arr[collection[i] - coll_min] -= 1 + + return ordered + + +if __name__ == '__main__': + import sys + # For python 2.x and 3.x compatibility: 3.x has not raw_input builtin + # otherwise 2.x's input builtin function is too "smart" + if sys.version_info.major < 3: + input_function = raw_input + else: + input_function = input + + user_input = input_function('Enter numbers separated by a comma:\n') + unsorted = [int(item) for item in user_input.split(',')] + print(counting_sort(unsorted)) From eb8375d13801eb812a76aa689b062a4d66d410ea Mon Sep 17 00:00:00 2001 From: Harshil Date: Sat, 14 Oct 2017 09:54:52 +0530 Subject: [PATCH 49/59] Commented travis tag Commented travis tag untill we find suitable travis.yml --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9589bccd9307..d77e17e751e8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# The Algorithms - Python [![Build Status](https://travis-ci.org/TheAlgorithms/Python.svg)](https://travis-ci.org/TheAlgorithms/Python) +# The Algorithms - Python ### All algorithms implemented in Python (for education) From d7fccf50690f84e0e3072b3c0fc7e159031078e8 Mon Sep 17 00:00:00 2001 From: yeggasd Date: Sun, 15 Oct 2017 00:44:53 +0800 Subject: [PATCH 50/59] Updated README.md Added Vigenere Cipher description --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d77e17e751e8..70077e98fd5a 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,13 @@ The method is named after **Julius Caesar**, who used it in his private correspo The encryption step performed by a Caesar cipher is often incorporated as part of more complex schemes, such as the Vigenère cipher, and still has modern application in the ROT13 system. As with all single-alphabet substitution ciphers, the Caesar cipher is easily broken and in modern practice offers essentially no communication security. ###### Source: [Wikipedia](https://en.wikipedia.org/wiki/Caesar_cipher) +### Vigenère +The **Vigenère cipher** is a method of encrypting alphabetic text by using a series of **interwoven Caesar ciphers** based on the letters of a keyword. It is **a form of polyalphabetic substitution**.
+The Vigenère cipher has been reinvented many times. The method was originally described by Giovan Battista Bellaso in his 1553 book La cifra del. Sig. Giovan Battista Bellaso; however, the scheme was later misattributed to Blaise de Vigenère in the 19th century, and is now widely known as the "Vigenère cipher".
+Though the cipher is easy to understand and implement, for three centuries it resisted all attempts to break it; this earned it the description **le chiffre indéchiffrable**(French for 'the indecipherable cipher'). +Many people have tried to implement encryption schemes that are essentially Vigenère ciphers. Friedrich Kasiski was the first to publish a general method of deciphering a Vigenère cipher in 1863. +###### Source: [Wikipedia](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) + ### Transposition In cryptography, a **transposition cipher** is a method of encryption by which the positions held by units of plaintext (which are commonly characters or groups of characters) are shifted according to a regular system, so that the ciphertext constitutes a permutation of the plaintext. That is, the order of the units is changed (the plaintext is reordered).
Mathematically a bijective function is used on the characters' positions to encrypt and an inverse function to decrypt. From d70b9268fe2d05f5ff6197b957b98f935fb13e91 Mon Sep 17 00:00:00 2001 From: Sarbajit Saha Date: Sun, 15 Oct 2017 21:25:54 +0530 Subject: [PATCH 51/59] fixed spelling of coma to comma --- searches/binary_search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/searches/binary_search.py b/searches/binary_search.py index 340649e4f577..c54aa96a1c5d 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -144,7 +144,7 @@ def __assert_sorted(collection): else: input_function = input - user_input = input_function('Enter numbers separated by coma:\n') + user_input = input_function('Enter numbers separated by comma:\n') collection = [int(item) for item in user_input.split(',')] try: __assert_sorted(collection) From 6d192700c686a9d432c7ec0369fcc0cacb5875bd Mon Sep 17 00:00:00 2001 From: Sarbajit Saha Date: Sun, 15 Oct 2017 21:41:10 +0530 Subject: [PATCH 52/59] added interpolation search --- searches/interpolation_search.py | 102 +++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 searches/interpolation_search.py diff --git a/searches/interpolation_search.py b/searches/interpolation_search.py new file mode 100644 index 000000000000..068d9c554f43 --- /dev/null +++ b/searches/interpolation_search.py @@ -0,0 +1,102 @@ +""" +This is pure python implementation of interpolation search algorithm +""" +from __future__ import print_function +import bisect + + +def interpolation_search(sorted_collection, item): + """Pure implementation of interpolation search algorithm in Python + Be careful collection must be sorted, otherwise result will be + unpredictable + :param sorted_collection: some sorted collection with comparable items + :param item: item value to search + :return: index of found item or None if item is not found + """ + left = 0 + right = len(sorted_collection) - 1 + + while left <= right: + point = left + ((item - sorted_collection[left]) * (right - left)) // (sorted_collection[right] - sorted_collection[left]) + + #out of range check + if point<0 or point>=len(sorted_collection): + return None + + current_item = sorted_collection[point] + if current_item == item: + return point + else: + if item < current_item: + right = point - 1 + else: + left = point + 1 + return None + + +def interpolation_search_by_recursion(sorted_collection, item, left, right): + + """Pure implementation of interpolation search algorithm in Python by recursion + Be careful collection must be sorted, otherwise result will be + unpredictable + First recursion should be started with left=0 and right=(len(sorted_collection)-1) + :param sorted_collection: some sorted collection with comparable items + :param item: item value to search + :return: index of found item or None if item is not found + """ + point = left + ((item - sorted_collection[left]) * (right - left)) // (sorted_collection[right] - sorted_collection[left]) + + #out of range check + if point<0 or point>=len(sorted_collection): + return None + + if sorted_collection[point] == item: + return point + elif sorted_collection[point] > item: + return interpolation_search_by_recursion(sorted_collection, item, left, point-1) + else: + return interpolation_search_by_recursion(sorted_collection, item, point+1, right) + +def __assert_sorted(collection): + """Check if collection is sorted, if not - raises :py:class:`ValueError` + :param collection: collection + :return: True if collection is sorted + :raise: :py:class:`ValueError` if collection is not sorted + Examples: + >>> __assert_sorted([0, 1, 2, 4]) + True + >>> __assert_sorted([10, -1, 5]) + Traceback (most recent call last): + ... + ValueError: Collection must be sorted + """ + if collection != sorted(collection): + raise ValueError('Collection must be sorted') + return True + + +if __name__ == '__main__': + import sys + # For python 2.x and 3.x compatibility: 3.x has no raw_input builtin + # otherwise 2.x's input builtin function is too "smart" + if sys.version_info.major < 3: + input_function = raw_input + else: + input_function = input + + user_input = input_function('Enter numbers separated by comma:\n') + collection = [int(item) for item in user_input.split(',')] + try: + __assert_sorted(collection) + except ValueError: + sys.exit('Sequence must be sorted to apply interpolation search') + + target_input = input_function( + 'Enter a single number to be found in the list:\n' + ) + target = int(target_input) + result = interpolation_search(collection, target) + if result is not None: + print('{} found at positions: {}'.format(target, result)) + else: + print('Not found') \ No newline at end of file From cf7d2cbec6cf29d1bbb455ac2366746a0605441a Mon Sep 17 00:00:00 2001 From: agdenadel Date: Mon, 16 Oct 2017 20:20:00 -0400 Subject: [PATCH 53/59] Fix typo in traversals --- {traverals => traversals}/binary_tree_traversals.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {traverals => traversals}/binary_tree_traversals.py (100%) diff --git a/traverals/binary_tree_traversals.py b/traversals/binary_tree_traversals.py similarity index 100% rename from traverals/binary_tree_traversals.py rename to traversals/binary_tree_traversals.py From 0dcf27f3f2558e144b1076b09f5c1bfcfb2f8d9d Mon Sep 17 00:00:00 2001 From: Vishal Gupta Date: Fri, 20 Oct 2017 13:47:09 +0530 Subject: [PATCH 54/59] Added basic-graphs.py with common graph algorithms --- Graphs/basic-graphs.py | 267 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 Graphs/basic-graphs.py diff --git a/Graphs/basic-graphs.py b/Graphs/basic-graphs.py new file mode 100644 index 000000000000..fc78e565274d --- /dev/null +++ b/Graphs/basic-graphs.py @@ -0,0 +1,267 @@ +# Accept No. of Nodes and edges +n, m = map(int, raw_input().split(" ")) + +# Initialising Dictionary of edges +g = {} +for i in xrange(n): + g[i + 1] = [] + +""" +-------------------------------------------------------------------------------- + Accepting edges of Unweighted Directed Graphs +-------------------------------------------------------------------------------- +""" +for _ in xrange(m): + x, y = map(int, raw_input().split(" ")) + g[x].append(y) + +""" +-------------------------------------------------------------------------------- + Accepting edges of Unweighted Undirected Graphs +-------------------------------------------------------------------------------- +""" +for _ in xrange(m): + x, y = map(int, raw_input().split(" ")) + g[x].append(y) + g[y].append(x) + +""" +-------------------------------------------------------------------------------- + Accepting edges of Weighted Undirected Graphs +-------------------------------------------------------------------------------- +""" +for _ in xrange(m): + x, y, r = map(int, raw_input().split(" ")) + g[x].append([y, r]) + g[y].append([x, r]) + +""" +-------------------------------------------------------------------------------- + Depth First Search. + Args : G - Dictionary of edges + s - Starting Node + Vars : vis - Set of visited nodes + S - Traversal Stack +-------------------------------------------------------------------------------- +""" + + +def dfs(G, s): + vis, S = set([s]), [s] + print s + while S: + flag = 0 + for i in G[S[-1]]: + if i not in vis: + S.append(i) + vis.add(i) + flag = 1 + print i + break + if not flag: + S.pop() + + +""" +-------------------------------------------------------------------------------- + Breadth First Search. + Args : G - Dictionary of edges + s - Starting Node + Vars : vis - Set of visited nodes + Q - Traveral Stack +-------------------------------------------------------------------------------- +""" +from collections import deque + + +def bfs(G, s): + vis, Q = set([s]), deque([s]) + print s + while Q: + u = Q.popleft() + for v in G[u]: + if v not in vis: + vis.add(v) + Q.append(v) + print v + + +""" +-------------------------------------------------------------------------------- + Dijkstra's shortest path Algorithm + Args : G - Dictionary of edges + s - Starting Node + Vars : dist - Dictionary storing shortest distance from s to every other node + known - Set of knows nodes + path - Preceding node in path +-------------------------------------------------------------------------------- +""" + + +def dijk(G, s): + dist, known, path = {s: 0}, set(), {s: 0} + while True: + if len(known) == len(G) - 1: + break + mini = 100000 + for i in dist: + if i not in known and dist[i] < mini: + mini = dist[i] + u = i + known.add(u) + for v in G[u]: + if v[0] not in known: + if dist[u] + v[1] < dist.get(v[0], 100000): + dist[v[0]] = dist[u] + v[1] + path[v[0]] = u + for i in dist: + if i != s: + print dist[i] + + +""" +-------------------------------------------------------------------------------- + Topological Sort +-------------------------------------------------------------------------------- +""" +from collections import deque + + +def topo(G, ind=None, Q=[1]): + if ind == None: + ind = [0] * (len(G) + 1) # SInce oth Index is ignored + for u in G: + for v in G[u]: + ind[v] += 1 + Q = deque() + for i in G: + if ind[i] == 0: + Q.append(i) + if len(Q) == 0: + return + v = Q.popleft() + print v + for w in G[v]: + ind[w] -= 1 + if ind[w] == 0: + Q.append(w) + topo(G, ind, Q) + + +""" +-------------------------------------------------------------------------------- + Reading an Adjacency matrix +-------------------------------------------------------------------------------- +""" + + +def adjm(): + n, a = input(), [] + for i in xrange(n): + a.append(map(int, raw_input().split())) + return a, n + + +""" +-------------------------------------------------------------------------------- + Floyd Warshall's algorithm + Args : G - Dictionary of edges + s - Starting Node + Vars : dist - Dictionary storing shortest distance from s to every other node + known - Set of knows nodes + path - Preceding node in path + +-------------------------------------------------------------------------------- +""" + + +def floy((A, n)): + dist = list(A) + path = [[0] * n for i in xrange(n)] + for k in xrange(n): + for i in xrange(n): + for j in xrange(n): + if dist[i][j] > dist[i][k] + dist[k][j]: + dist[i][j] = dist[i][k] + dist[k][j] + path[i][k] = k + print dist + + +""" +-------------------------------------------------------------------------------- + Prim's MST Algorithm + Args : G - Dictionary of edges + s - Starting Node + Vars : dist - Dictionary storing shortest distance from s to nearest node + known - Set of knows nodes + path - Preceding node in path +-------------------------------------------------------------------------------- +""" + + +def prim(G, s): + dist, known, path = {s: 0}, set(), {s: 0} + while True: + if len(known) == len(G) - 1: + break + mini = 100000 + for i in dist: + if i not in known and dist[i] < mini: + mini = dist[i] + u = i + known.add(u) + for v in G[u]: + if v[0] not in known: + if v[1] < dist.get(v[0], 100000): + dist[v[0]] = v[1] + path[v[0]] = u + + +""" +-------------------------------------------------------------------------------- + Accepting Edge list + Vars : n - Number of nodes + m - Number of edges + Returns : l - Edge list + n - Number of Nodes +-------------------------------------------------------------------------------- +""" + + +def edglist(): + n, m = map(int, raw_input().split(" ")) + l = [] + for i in xrange(m): + l.append(map(int, raw_input().split(' '))) + return l, n + + +""" +-------------------------------------------------------------------------------- + Kruskal's MST Algorithm + Args : E - Edge list + n - Number of Nodes + Vars : s - Set of all nodes as unique disjoint sets (initially) +-------------------------------------------------------------------------------- +""" + + +def krusk((E, n)): + # Sort edges on the basis of distance + E.sort(reverse=True, key=lambda x: x[2]) + s = [set([i]) for i in range(1, n + 1)] + while True: + if len(s) == 1: + break + print s + x = E.pop() + for i in xrange(len(s)): + if x[0] in s[i]: + break + for j in xrange(len(s)): + if x[1] in s[j]: + if i == j: + break + s[j].update(s[i]) + s.pop(i) + break From edaa2c15889b250c777f583fda5725cf073b18f2 Mon Sep 17 00:00:00 2001 From: Sarot Busala Date: Fri, 20 Oct 2017 16:26:07 +0700 Subject: [PATCH 55/59] Floyd Warshall Algorithm upload simple Floyd-Warshall Algorithm (No path stored) --- dynamic_programming/FloydWarshall.py | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 dynamic_programming/FloydWarshall.py diff --git a/dynamic_programming/FloydWarshall.py b/dynamic_programming/FloydWarshall.py new file mode 100644 index 000000000000..bf77141244e9 --- /dev/null +++ b/dynamic_programming/FloydWarshall.py @@ -0,0 +1,37 @@ +import math + +class Graph: + + def __init__(self, N = 0): # a graph with Node 0,1,...,N-1 + self.N = N + self.W = [[math.inf for j in range(0,N)] for i in range(0,N)] # adjacency matrix for weight + self.dp = [[math.inf for j in range(0,N)] for i in range(0,N)] # dp[i][j] stores minimum distance from i to j + + def addEdge(self, u, v, w): + self.dp[u][v] = w; + + def floyd_warshall(self): + for k in range(0,self.N): + for i in range(0,self.N): + for j in range(0,self.N): + self.dp[i][j] = min(self.dp[i][j], self.dp[i][k] + self.dp[k][j]) + + def showMin(self, u, v): + return self.dp[u][v] + +if __name__ == '__main__': + graph = Graph(5) + graph.addEdge(0,2,9) + graph.addEdge(0,4,10) + graph.addEdge(1,3,5) + graph.addEdge(2,3,7) + graph.addEdge(3,0,10) + graph.addEdge(3,1,2) + graph.addEdge(3,2,1) + graph.addEdge(3,4,6) + graph.addEdge(4,1,3) + graph.addEdge(4,2,4) + graph.addEdge(4,3,9) + graph.floyd_warshall() + graph.showMin(1,4) + graph.showMin(0,3) From d68d0ef05c024cb90f96b379c1206b3487847cbc Mon Sep 17 00:00:00 2001 From: Sarot Busala Date: Fri, 20 Oct 2017 16:45:17 +0700 Subject: [PATCH 56/59] Add Fenwick Tree Add Fenwick Tree (Binary Index Tree) --- data_structures/Binary Tree/FenwickTree.py | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 data_structures/Binary Tree/FenwickTree.py diff --git a/data_structures/Binary Tree/FenwickTree.py b/data_structures/Binary Tree/FenwickTree.py new file mode 100644 index 000000000000..02e2d61515a9 --- /dev/null +++ b/data_structures/Binary Tree/FenwickTree.py @@ -0,0 +1,28 @@ +class FenwickTree: + + def __init__(self, SIZE): # create fenwick tree with size SIZE + self.Size = SIZE + self.ft = [0 for i in range (0,SIZE)] + + def update(self, i, val): # update data (adding) in index i in O(lg N) + while (i < self.Size): + self.ft[i] += val + i += i & (-i) + + def query(self, i): # query cumulative data from index 0 to i in O(lg N) + ret = 0 + while (i > 0): + ret += self.ft[i] + i -= i & (-i) + return ret + +if __name__ == '__main__': + f = FenwickTree(100) + f.update(1,20) + f.update(4,4) + print (f.query(1)) + print (f.query(3)) + print (f.query(4)) + f.update(2,-5) + print (f.query(1)) + print (f.query(3)) From 29f8e5edd87bfbcb1e2af1fd6c6a2610fbd28e49 Mon Sep 17 00:00:00 2001 From: Vishal Kumar Date: Fri, 20 Oct 2017 16:10:33 +0530 Subject: [PATCH 57/59] Create Arrays "Arrays implementation" using python programming. --- data_structures/Arrays | 1 + 1 file changed, 1 insertion(+) create mode 100644 data_structures/Arrays diff --git a/data_structures/Arrays b/data_structures/Arrays new file mode 100644 index 000000000000..03eaefac17fa --- /dev/null +++ b/data_structures/Arrays @@ -0,0 +1 @@ +Arrays implimentation using python programming. From e7e8558b639ba235585303a74b32273a48d8f8a8 Mon Sep 17 00:00:00 2001 From: Sarot Busala Date: Fri, 20 Oct 2017 18:24:11 +0700 Subject: [PATCH 58/59] Add Segment Tree Add simple Segment Tree (No optimization) --- data_structures/Binary Tree/SegmentTree.py | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 data_structures/Binary Tree/SegmentTree.py diff --git a/data_structures/Binary Tree/SegmentTree.py b/data_structures/Binary Tree/SegmentTree.py new file mode 100644 index 000000000000..cf47ca7d7bf6 --- /dev/null +++ b/data_structures/Binary Tree/SegmentTree.py @@ -0,0 +1,64 @@ +import math + +class SegmentTree: + + def __init__(self, N): + self.N = N + self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N + + def left(self, idx): + return idx*2 + + def right(self, idx): + return idx*2 + 1 + + def build(self, idx, l, r, A): + if l==r: + self.st[idx] = A[l-1] + else : + mid = (l+r)//2 + self.build(self.left(idx),l,mid, A) + self.build(self.right(idx),mid+1,r, A) + self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)]) + + def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b] + if r < a or l > b: + return True + if l == r : + self.st[idx] = val + return True + mid = (l+r)//2 + self.update(self.left(idx),l,mid,a,b,val) + self.update(self.right(idx),mid+1,r,a,b,val) + self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)]) + return True + + def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b] + if r < a or l > b: + return -math.inf + if l >= a and r <= b: + return self.st[idx] + mid = (l+r)//2 + q1 = self.query(self.left(idx),l,mid,a,b) + q2 = self.query(self.right(idx),mid+1,r,a,b) + return max(q1,q2) + + def showData(self): + showList = [] + for i in range(1,N+1): + showList += [self.query(1, 1, self.N, i, i)] + print (showList) + + +if __name__ == '__main__': + A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8] + N = 15 + segt = SegmentTree(N) + segt.build(1,1,N,A) + print (segt.query(1,1,N,4,6)) + print (segt.query(1,1,N,7,11)) + print (segt.query(1,1,N,7,12)) + segt.update(1,1,N,1,3,111) + print (segt.query(1,1,N,1,15)) + segt.update(1,1,N,7,8,235) + segt.showData() From 2617de848ea6f8e209c871dd1ac488401f1aace7 Mon Sep 17 00:00:00 2001 From: Sarot Busala Date: Fri, 20 Oct 2017 18:47:06 +0700 Subject: [PATCH 59/59] Add Lazy Segment Tree Add Lazy Segment Tree with Lazy Approach --- .../Binary Tree/LazySegmentTree.py | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 data_structures/Binary Tree/LazySegmentTree.py diff --git a/data_structures/Binary Tree/LazySegmentTree.py b/data_structures/Binary Tree/LazySegmentTree.py new file mode 100644 index 000000000000..bbd880a06fe8 --- /dev/null +++ b/data_structures/Binary Tree/LazySegmentTree.py @@ -0,0 +1,90 @@ +import math + +class SegmentTree: + + def __init__(self, N): + self.N = N + self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N + self.lazy = [0 for i in range(0,4*N)] # create array to store lazy update + self.flag = [0 for i in range(0,4*N)] # flag for lazy update + + def left(self, idx): + return idx*2 + + def right(self, idx): + return idx*2 + 1 + + def build(self, idx, l, r, A): + if l==r: + self.st[idx] = A[l-1] + else : + mid = (l+r)//2 + self.build(self.left(idx),l,mid, A) + self.build(self.right(idx),mid+1,r, A) + self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)]) + + # update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) for each update) + def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b] + if self.flag[idx] == True: + self.st[idx] = self.lazy[idx] + self.flag[idx] = False + if l!=r: + self.lazy[self.left(idx)] = self.lazy[idx] + self.lazy[self.right(idx)] = self.lazy[idx] + self.flag[self.left(idx)] = True + self.flag[self.right(idx)] = True + + if r < a or l > b: + return True + if l >= a and r <= b : + self.st[idx] = val + if l!=r: + self.lazy[self.left(idx)] = val + self.lazy[self.right(idx)] = val + self.flag[self.left(idx)] = True + self.flag[self.right(idx)] = True + return True + mid = (l+r)//2 + self.update(self.left(idx),l,mid,a,b,val) + self.update(self.right(idx),mid+1,r,a,b,val) + self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)]) + return True + + # query with O(lg N) + def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b] + if self.flag[idx] == True: + self.st[idx] = self.lazy[idx] + self.flag[idx] = False + if l != r: + self.lazy[self.left(idx)] = self.lazy[idx] + self.lazy[self.right(idx)] = self.lazy[idx] + self.flag[self.left(idx)] = True + self.flag[self.right(idx)] = True + if r < a or l > b: + return -math.inf + if l >= a and r <= b: + return self.st[idx] + mid = (l+r)//2 + q1 = self.query(self.left(idx),l,mid,a,b) + q2 = self.query(self.right(idx),mid+1,r,a,b) + return max(q1,q2) + + def showData(self): + showList = [] + for i in range(1,N+1): + showList += [self.query(1, 1, self.N, i, i)] + print (showList) + + +if __name__ == '__main__': + A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8] + N = 15 + segt = SegmentTree(N) + segt.build(1,1,N,A) + print (segt.query(1,1,N,4,6)) + print (segt.query(1,1,N,7,11)) + print (segt.query(1,1,N,7,12)) + segt.update(1,1,N,1,3,111) + print (segt.query(1,1,N,1,15)) + segt.update(1,1,N,7,8,235) + segt.showData()