Skip to content

Commit

Permalink
Extra Algorithms added
Browse files Browse the repository at this point in the history
  • Loading branch information
FarhanKasmani committed Oct 2, 2018
1 parent 0e76ee9 commit a7948f1
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 0 deletions.
44 changes: 44 additions & 0 deletions Graphs/ArticulationPoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Finding Articulation Points in Undirected Graph
def computeAP(l):
n = len(l)
outEdgeCount = 0
low = [0] * n
visited = [False] * n
isArt = [False] * n

def dfs(root, at, parent, outEdgeCount):
if parent == root:
outEdgeCount += 1
visited[at] = True
low[at] = at

for to in l[at]:
if to == parent:
pass
elif not visited[to]:
outEdgeCount = dfs(root, to, at, outEdgeCount)
low[at] = min(low[at], low[to])

# AP found via bridge
if at < low[to]:
isArt[at] = True
# AP found via cycle
if at == low[to]:
isArt[at] = True
else:
low[at] = min(low[at], to)
return outEdgeCount

for i in range(n):
if not visited[i]:
outEdgeCount = 0
outEdgeCount = dfs(i, i, -1, outEdgeCount)
isArt[i] = (outEdgeCount > 1)

for x in range(len(isArt)):
if isArt[x] == True:
print(x, end=" ")

# Adjacency list of graph
l = {0:[1,2], 1:[0,2], 2:[0,1,3,5], 3:[2,4], 4:[3], 5:[2,6,8], 6:[5,7], 7:[6,8], 8:[5,7]}
computeAP(l)
43 changes: 43 additions & 0 deletions Graphs/CheckBipartiteGraph_BFS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Check whether Graph is Bipartite or Not using BFS

# A Bipartite Graph is a graph whose vertices can be divided into two independent sets,
# U and V such that every edge (u, v) either connects a vertex from U to V or a vertex
# from V to U. In other words, for every edge (u, v), either u belongs to U and v to V,
# or u belongs to V and v to U. We can also say that there is no edge that connects
# vertices of same set.
def checkBipartite(l):
queue = []
visited = [False] * len(l)
color = [-1] * len(l)

def bfs():
while(queue):
u = queue.pop(0)
visited[u] = True

for neighbour in l[u]:

if neighbour == u:
return False

if color[neighbour] == -1:
color[neighbour] = 1 - color[u]
queue.append(neighbour)

elif color[neighbour] == color[u]:
return False

return True

for i in range(len(l)):
if not visited[i]:
queue.append(i)
color[i] = 0
if bfs() == False:
return False

return True

# Adjacency List of graph
l = {0:[1,3], 1:[0,2], 2:[1,3], 3:[0,2]}
print(checkBipartite(l))
31 changes: 31 additions & 0 deletions Graphs/FindingBridges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Finding Bridges in Undirected Graph
def computeBridges(l):
id = 0
n = len(l) # No of vertices in graph
low = [0] * n
visited = [False] * n

def dfs(at, parent, bridges, id):
visited[at] = True
low[at] = id
id += 1
for to in l[at]:
if to == parent:
pass
elif not visited[to]:
dfs(to, at, bridges, id)
low[at] = min(low[at], low[to])
if at < low[to]:
bridges.append([at, to])
else:
# This edge is a back edge and cannot be a bridge
low[at] = min(low[at], to)

bridges = []
for i in range(n):
if (not visited[i]):
dfs(i, -1, bridges, id)
print(bridges)

l = {0:[1,2], 1:[0,2], 2:[0,1,3,5], 3:[2,4], 4:[3], 5:[2,6,8], 6:[5,7], 7:[6,8], 8:[5,7]}
computeBridges(l)
30 changes: 30 additions & 0 deletions Graphs/KahnsAlgorithm_long.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Finding longest distance in Directed Acyclic Graph using KahnsAlgorithm
def longestDistance(l):
indegree = [0] * len(l)
queue = []
longDist = [1] * len(l)

for key, values in l.items():
for i in values:
indegree[i] += 1

for i in range(len(indegree)):
if indegree[i] == 0:
queue.append(i)

while(queue):
vertex = queue.pop(0)
for x in l[vertex]:
indegree[x] -= 1

if longDist[vertex] + 1 > longDist[x]:
longDist[x] = longDist[vertex] + 1

if indegree[x] == 0:
queue.append(x)

print(max(longDist))

# Adjacency list of Graph
l = {0:[2,3,4], 1:[2,7], 2:[5], 3:[5,7], 4:[7], 5:[6], 6:[7], 7:[]}
longestDistance(l)
32 changes: 32 additions & 0 deletions Graphs/KahnsAlgorithm_topo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Kahn's Algorithm is used to find Topological ordering of Directed Acyclic Graph using BFS
def topologicalSort(l):
indegree = [0] * len(l)
queue = []
topo = []
cnt = 0

for key, values in l.items():
for i in values:
indegree[i] += 1

for i in range(len(indegree)):
if indegree[i] == 0:
queue.append(i)

while(queue):
vertex = queue.pop(0)
cnt += 1
topo.append(vertex)
for x in l[vertex]:
indegree[x] -= 1
if indegree[x] == 0:
queue.append(x)

if cnt != len(l):
print("Cycle exists")
else:
print(topo)

# Adjacency List of Graph
l = {0:[1,2], 1:[3], 2:[3], 3:[4,5], 4:[], 5:[]}
topologicalSort(l)
111 changes: 111 additions & 0 deletions Graphs/MinimumSpanningTree_Prims.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import sys
from collections import defaultdict

def PrimsAlgorithm(l):

nodePosition = []
def getPosition(vertex):
return nodePosition[vertex]

def setPosition(vertex, pos):
nodePosition[vertex] = pos

def topToBottom(heap, start, size, positions):
if start > size // 2 - 1:
return
else:
if 2 * start + 2 >= size:
m = 2 * start + 1
else:
if heap[2 * start + 1] < heap[2 * start + 2]:
m = 2 * start + 1
else:
m = 2 * start + 2
if heap[m] < heap[start]:
temp, temp1 = heap[m], positions[m]
heap[m], positions[m] = heap[start], positions[start]
heap[start], positions[start] = temp, temp1

temp = getPosition(positions[m])
setPosition(positions[m], getPosition(positions[start]))
setPosition(positions[start], temp)

topToBottom(heap, m, size, positions)

# Update function if value of any node in min-heap decreases
def bottomToTop(val, index, heap, position):
temp = position[index]

while(index != 0):
if index % 2 == 0:
parent = int( (index-2) / 2 )
else:
parent = int( (index-1) / 2 )

if val < heap[parent]:
heap[index] = heap[parent]
position[index] = position[parent]
setPosition(position[parent], index)
else:
heap[index] = val
position[index] = temp
setPosition(temp, index)
break
index = parent
else:
heap[0] = val
position[0] = temp
setPosition(temp, 0)

def heapify(heap, positions):
start = len(heap) // 2 - 1
for i in range(start, -1, -1):
topToBottom(heap, i, len(heap), positions)

def deleteMinimum(heap, positions):
temp = positions[0]
heap[0] = sys.maxsize
topToBottom(heap, 0, len(heap), positions)
return temp

visited = [0 for i in range(len(l))]
Nbr_TV = [-1 for i in range(len(l))] # Neighboring Tree Vertex of selected vertex
# Minimum Distance of explored vertex with neighboring vertex of partial tree formed in graph
Distance_TV = [] # Heap of Distance of vertices from their neighboring vertex
Positions = []

for x in range(len(l)):
p = sys.maxsize
Distance_TV.append(p)
Positions.append(x)
nodePosition.append(x)

TreeEdges = []
visited[0] = 1
Distance_TV[0] = sys.maxsize
for x in l[0]:
Nbr_TV[ x[0] ] = 0
Distance_TV[ x[0] ] = x[1]
heapify(Distance_TV, Positions)

for i in range(1, len(l)):
vertex = deleteMinimum(Distance_TV, Positions)
if visited[vertex] == 0:
TreeEdges.append((Nbr_TV[vertex], vertex))
visited[vertex] = 1
for v in l[vertex]:
if visited[v[0]] == 0 and v[1] < Distance_TV[ getPosition(v[0]) ]:
Distance_TV[ getPosition(v[0]) ] = v[1]
bottomToTop(v[1], getPosition(v[0]), Distance_TV, Positions)
Nbr_TV[ v[0] ] = vertex
return TreeEdges

# < --------- Prims Algorithm --------- >
n = int(input("Enter number of vertices: "))
e = int(input("Enter number of edges: "))
adjlist = defaultdict(list)
for x in range(e):
l = [int(x) for x in input().split()]
adjlist[l[0]].append([ l[1], l[2] ])
adjlist[l[1]].append([ l[0], l[2] ])
print(PrimsAlgorithm(adjlist))
70 changes: 70 additions & 0 deletions Maths/BasicMaths.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import math

def primeFactors(n):
pf = []
while n % 2 == 0:
pf.append(2)
n = int(n / 2)

for i in range(3, int(math.sqrt(n))+1, 2):
while n % i == 0:
pf.append(i)
n = int(n / i)

if n > 2:
pf.append(n)

return pf

def numberOfDivisors(n):
div = 1

temp = 1
while n % 2 == 0:
temp += 1
n = int(n / 2)
div = div * (temp)

for i in range(3, int(math.sqrt(n))+1, 2):
temp = 1
while n % i == 0:
temp += 1
n = int(n / i)
div = div * (temp)

return div

def sumOfDivisors(n):
s = 1

temp = 1
while n % 2 == 0:
temp += 1
n = int(n / 2)
if temp > 1:
s *= (2**temp - 1) / (2 - 1)

for i in range(3, int(math.sqrt(n))+1, 2):
temp = 1
while n % i == 0:
temp += 1
n = int(n / i)
if temp > 1:
s *= (i**temp - 1) / (i - 1)

return s

def eulerPhi(n):
l = primeFactors(n)
l = set(l)
s = n
for x in l:
s *= (x - 1)/x
return s

print(primeFactors(100))
print(numberOfDivisors(100))
print(sumOfDivisors(100))
print(eulerPhi(100))


Loading

0 comments on commit a7948f1

Please sign in to comment.