Commit 45e2fdd2 authored by Siu, Pui Chung's avatar Siu, Pui Chung
Browse files

Upload New File

parent f7b4d79c
#!/usr/bin/env python3
"""
Author: Siu Pui Chung
Student nr: 1047527
Script to: algorithms in bioinformatics assignment 3
Usage: Contains function that answers to assignment 3, eulerian cycle
and paths
"""
# Import statements
# Implement your functions here
def find_all_vertex(graph):
"""
Description: find all vertex, including those with only in or out edges
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: vertex list, list that contains all vertex
"""
vertex_list = []
for vertex in graph.keys():
if vertex not in vertex_list:
vertex_list.append(vertex)
for neighbour in graph[vertex]:
if neighbour not in vertex_list:
vertex_list.append(neighbour)
return vertex_list
def in_out_vertex_dict(graph):
"""
Description: find out in and out degrees of each vertex
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: vertex dict, dictionary with keys as vertex and values as
[number of in degree, number of out degree]
"""
vertex_dict = {keys:[0, 0] for keys in find_all_vertex(graph)}
for vertex in graph.keys():
neighbours = graph[vertex]
vertex_dict[vertex][0] += len(neighbours)
for neighbour in neighbours:
vertex_dict[neighbour][1] += 1
return vertex_dict
def is_eulerian(graph):
"""
Description: analyse if the graph has a eulerian cycle
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: boolean, boolean value, true when graph contains eulerian cycle
"""
boolean = True
vertex_dict = in_out_vertex_dict(graph)
for vertex in vertex_dict.keys():
if vertex_dict[vertex][0] != vertex_dict[vertex][1]:
boolean = False
return boolean
def has_eulerian_path(graph):
"""
Description: analyse if the graph has a eulerian path
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: 0 when no eulerian path, 1 when all vertices are balanced,
2 when 2 odd vertices are presented
"""
vertex_dict = in_out_vertex_dict(graph)
vertex_state_list = [0 for keys in vertex_dict]
for counter, vertex in enumerate(vertex_dict):
vertex_state_list[counter] = abs(vertex_dict[vertex][0] - \
vertex_dict[vertex][1])
if vertex_state_list.count(1) == 2 and vertex_state_list.count(0)\
==(len(vertex_state_list) - 2):
return 2 #when 2 odd vertices
elif vertex_state_list.count(0) == len(vertex_state_list):
return 1 #when all vertices are balanced
else:
return 0 #when no eulerian_path found
def odd_vertices(graph):
"""
Description: find out odd vertices
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: odd_vertice_list, list of odd vertices
"""
odd_vertice_list = []
vertex_dict = in_out_vertex_dict(graph)
vertex_state_list = [0 for keys in vertex_dict]
for counter, vertex in enumerate(vertex_dict):
vertex_state_list[counter] = abs(vertex_dict[vertex][0] - vertex_dict[vertex][1])
if vertex_state_list[counter] % 2 == 1:
odd_vertice_list.append(vertex)
return odd_vertice_list
def full_vertex_dict(graph):
"""
Description: graph representation with single degree vertexs as keys
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: vertex_dict, dictionary with all vertexes as keys and their
outgoing edges destination vertex as values
"""
vertex_dict = {keys:[] for keys in find_all_vertex(graph)}
for vertex in graph.keys():
if graph[vertex] != []:
neighbours = graph[vertex]
vertex_dict[vertex] = neighbours
return vertex_dict
def find_eulerian_cycle(graph):
"""
Description: find eulerain cycle within a graph
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: path, eulerian cycle found
graph, remaining unused edges represented in a graph
"""
graph = full_vertex_dict(graph)
start_vertex = ""
num_odd_vertices = has_eulerian_path(graph)
if num_odd_vertices == 2:
start_vertex = odd_vertices(graph)[0]
elif num_odd_vertices == 1:
start_vertex = [vertex for vertex in graph.keys()][0]
stack, path = [], []
stack.append(start_vertex)
while stack:
#establish vertex as current vertex from list stack
vertex = stack.pop(-1)
#add current vertex to visited vertice list path
path.append(vertex)
#for each neighbour of current vertex as long as there are neigbours
if graph[vertex] != []:
next_vertex = graph[vertex][0]
#add next_vertex to top of stack
stack.append(next_vertex)
#remove edge from vertex to next_vertex
del graph[vertex][0]
return path, graph
def find_eulerian_path(graph):
"""
Description: find eulerian path within a graph
Input: graph, dictionary of vertex list with keys being start vertex
and values being end vertex
Output: main_path, eulerian path of the graph
"""
paths = []
while graph != {}:
path, graph = find_eulerian_cycle(graph)
#remove start vertexs that has no more out edges
graph = dict([(k,v) for k,v in graph.items() if len(v)>0])
paths.append(path)
print("all cycles", paths)
i = 1
while i < len(paths):
main_path = paths[0]
slice_pt = main_path.index(paths[i][0])
#slice insertion to combine current path with main path
main_path[slice_pt:slice_pt] = paths[i][:-1]
i += 1
return main_path
def seqtograph(spectrum):
"""
Description: convert spectrum sequence into graph format
Input: spectrum, DNA sequences with codons, first two nucleotide
connects to another codon's last two nucleotide
Output: graph_spectrum, representation of the spectrum as a dictionary
"""
graph_spectrum = {}
for tuples in spectrum:
if tuples[0:2] not in graph_spectrum.keys():
graph_spectrum[tuples[0:2]] = [tuples[1:3]]
else:
graph_spectrum[tuples[0:2]].append(tuples[1:3])
return graph_spectrum
if __name__ == "__main__":
graph_822 = {'J':['D'],'D':['E'],'I':['H'],'H':['F'],'F':['G','C'],\
'E':['I','A'],'G':['J'],'C':['A'],'A':['F','B'],'B':['E']}
# A SLIGHTLY BIGGER GRAPH, NEEDED FOR Q8
bigger_graph = {1:[2], 2:[4], 7:[3,11],\
4:[1,5,10],5:[6],6:[3],3:[8,9],\
8:[4],9:[7,4],\
10:[9],11:[12],12:[7]}
# SPECTRUM FROM FIG 8.20
s = ['ATG','TGG','TGC','GTG','GGC','GCA','GCG','CGT']
print("Q3")
print(find_eulerian_path(graph_822))
print("Q4")
#i dont know why but i need to reassign graph_822 before running, i
# thought the local variable wont change
graph_822 = {'J':['D'],'D':['E'],'I':['H'],'H':['F'],'F':['G','C'],\
'E':['I','A'],'G':['J'],'C':['A'],'A':['F','B'],'B':['E']}
print(find_eulerian_path(graph_822))
graph_822 = {'J':['D'],'D':['E'],'I':['H'],'H':['F'],'F':['G','C'],\
'E':['I','A'],'G':['J'],'C':['A'],'A':['F','B'],'B':['E']}
print(find_eulerian_path(graph_822))
graph_822 = {'J':['D'],'D':['E'],'I':['H'],'H':['F'],'F':['G','C'],\
'E':['I','A'],'G':['J'],'C':['A'],'A':['F','B'],'B':['E']}
print(find_eulerian_path(graph_822))
print("Q5")
for k, v in seqtograph(s).items():
print(k, v)
print("Q8")
print(find_eulerian_path(bigger_graph))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment