Check if graph is Bipartite - python

so I need to check if a Graph is Bipartite using Numpy arrays and Python 2
This is the code that I've developed to check the graph:
from __future__ import print_function
import numpy as np
class grafo:
visited = []
def __init__(self, n):
self.vertices = []
self.adjacency = np.zeros((n,n))
self.visited.append(True)
self.size = n
self.color = [-1] * self.size
self.color.append(0)
def isBipartita(self):
finalRes = str()
init = 0
self.color[init] = 1
self.visited.append(init)
while self.visited:
i = self.visited.pop()
print("[FIRST CHECK] adyacencia[" + str(i)+"][" + str(i) + "] == 1?")
if self.adjacency[i][i] == 1: //HERE IT CORRUPTS AT SOME POINT
finalRes = "NO"
print("True")
return finalRes;
for f in range(self.size):
print("[SECOND CHECK] adyacencia[" + str(i)+"][" + str(f) + "] == 1 and color[" + str(f) +"] == -1")
if self.adjacency[i][f] == 1 and self.color[f] == -1:
print("True")
self.color[f] = 1 - self.color[i]
self.visited.append(f)
else:
print("[THIRD CHECK] adyacencia[" + str(i)+"][" + str(f) + "] == 1 and color[" + str(f) +"] == color[" + str(i) +"]")
if self.adjacency[i][f] == 1 and self.color[f] == self.color[i]:
print("True")
finalRes = "NO"
return finalRes
finalRes = "YES"
return finalRes
def __str__(self):
return str(self.adjacency)
#PROGRAM
lenV = raw_input("") #This is the length of the Adjacency array for the graph
lenV = int(lenV)
inputs = []
for i in range(0, lenV):
inputs.append(raw_input())
print("\n-> Inputs:")
print(inputs)
print("\n-> List with Inputs Values:")
tempVal = list()
for numC in inputs:
tempVal.append(numC)
print(tempVal)
print("\n-> Split and get into array:")
G = grafo(lenV)
for x in range(0,lenV):
tempList = list(tempVal[x])
print(tempList)
for y in range(0, lenV):
G.adjacency[x][y] = tempList[y]
print("\n-> Array to check:")
print(G)
print("\n")
print(G.isBipartita())
The problem is in the class "grafo", in the isBipartita method; at some point while checking, the numpy integer array returns a boolean and gives a ValueError as an output.
This are some examples that I've used to test this:
TEST CASES
3
011
101
110
4
0101
1010
0101
1010
and this is the output that I get:
/** LIKE 20 SUCCESSFUL CHECKS LATER **/
[SECOND CHECK] adyacencia[1][3] == 1 and color[3] == -1
[THIRD CHECK] adyacencia[1][3] == 1 and color[3] == color[1]
[FIRST CHECK] adyacencia[True][True] == 1?
Traceback (most recent call last):
File "bipartitaChecker.py", line 76, in <module>
print(G.isBipartita())
File "bipartitaChecker.py", line 23, in isBipartita
if self.adjacency[i][i] == 1:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
As you can see, before the Traceback call, the last "[FIRST CHECK]" has adyacencia[True][True], and this is not intended to be this way... I have done research on the ValueError, but everything leads me to a point where only in some foreign cases this error is presented, but in my case it shouldn't be causing it...
I don't know what is happening?!
I'll appreciate any help.

Related

Usage: align <input file> Error in python

Code implements the dynamic programming solution for global pairwise alignment of two sequences. Trying to perform a semi-global alignment between the SARS-CoV-2 reference genome and the first read in the Nanopore sample. The length of the reference genome is 29903 base pairs and the length of the first Nanopore read is 1246 base pairs. When I run the following code, I get this message in my terminal:
import sys
import numpy as np
GAP = -2
MATCH = 5
MISMATCH = -3
MAXLENGTH_A = 29904
MAXLENGTH_B = 1247
# insert sequence files
A = open("SARS-CoV-2 reference genome.txt", "r")
B = open("Nanopore.txt", "r")
def max(A, B, C):
if (A >= B and A >= C):
return A
elif (B >= A and B >= C):
return B
else:
return C
def Tmax(A, B, C):
if (A > B and A > C):
return 'D'
elif (B > A and B > C):
return 'L'
else:
return 'U'
def m(p, q):
if (p == q):
return MATCH
else:
return MISMATCH
def append(st, c):
return c + "".join(i for i in st)
if __name__ == "__main__":
if (len(sys.argv) != 2):
print("Usage: align <input file>")
sys.exit()
if (not os.path.isfile(sys.argv[1])):
print("input file not found.")
sys.exit()
S = np.empty([MAXLENGTH_A, MAXLENGTH_B], dtype = int)
T = np.empty([MAXLENGTH_A, MAXLENGTH_B], dtype = str)
with open(sys.argv[1], "r") as file:
A = str(A.readline())[:-1]
B = str(B.readline())[:-1]
print("Sequence A:",A)
print("Sequence B:",B)
N = len(A)
M = len(B)
S[0][0] = 0
T[0][0] = 'D'
for i in range(0, N + 1):
S[i][0] = GAP * i
T[i][0] = 'U'
for i in range(0, M + 1):
S[0][i] = GAP * i
T[0][i] = 'L'
for i in range(1, N + 1):
for j in range(1, M + 1):
S[i][j] = max(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP)
T[i][j] = Tmax(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP)
print("The score of the alignment is :",S[N][M])
i, j = N, M
RA = RB = RM = ""
while (i != 0 or j != 0):
if (T[i][j]=='D'):
RA = append(RA,A[i-1])
RB = append(RB,B[j-1])
if (A[i-1] == B[j-1]):
RM = append(RM,'|')
else:
RM = append(RM,'*')
i -= 1
j -= 1
elif (T[i][j]=='L'):
RA = append(RA,'-')
RB = append(RB,B[j-1])
RM = append(RM,' ')
j -= 1
elif (T[i][j]=='U'):
RA = append(RA,A[i-1])
RB = append(RB,'-')
RM = append(RM,' ')
i -= 1
print(RA)
print(RM)
print(RB)
This has nothing to do with python. The error message comes this line:
if (len(sys.argv) != 2):
print("Usage: align <input file>")
The code expects to be called with exactly one argument, the input file:
align path/to/input/file
You provided a different number of arguments, probably zero.

Make a binary tree using lists

I am trying to make a binary tree using lists, but it is showing me this error, can you help me with this?
class BT:
def __init__(self, lp , data , rp):
self.LeftPointer = lp
self.data = data
self.RightPointer = rp
def insert(x):
#current_position
c = 0
#temporary_position
t = 0
while True:
if dsBT[c].data == None :
dsBT[c].data = x
break
elif x > dsBT[c].data:
if dsBT[c].RightPointer == 0:
t = c
while dsBT[t].data != None :
t += 1
dsBT[t].data = x
dsBT[c].RightPointer = t
break
else:
c = dsBT[c].RightPointer
else:
if dsBT[c].LeftPointer == 0:
t = c
while dsBT[t].data != None:
t += 1
dsBT[t].data = x
dsBT[c].LeftPointer = t
break
else:
c = dsBT[c].LeftPointer
**this part is for printing out the data **
dsBT = []
for j in range(2):
dsBT.append(BT( None ,None , None ))
for h in range(len(dsBT)):
#video game name
vgm = input(str("enter the game name:\n"))
insert(vgm)
for i in range(len(dsBT)):
print(dsBT[i].LeftPointer , dsBT[i].data ,dsBT[i].RightPointer)
the error it is showing:
enter the game name:
sarim
enter the game name:
dasr
Traceback (most recent call last):
File "C:\Users\workm\Desktop\Sarim\untitled0.py", line 44, in <module>
insert(vgm)
File "C:\Users\workm\Desktop\Sarim\untitled0.py", line 14, in insert
if dsBT[c].data == None :
TypeError: list indices must be integers or slices, not NoneType

Python: pop() returning py list, not my object

I'm trying to code an exercise to solve the Queen Puzzle (yes, typical, I know) on Python. I've made a class called Queens for board state that takes in the length of each side and the list of queens, if any.
In the main program, I have a list of Queens called frontier, which is then popped one by one. However, the result I get from popping seems to be of type list, and not Queens as expected!
What is causing this, and how do I fix it?
Code snippet:
from queens import Queens
def search(n, debug=False, max=6):
frontier = [Queens(n, [])] # queue of states to explore
while frontier != []:
check = frontier.pop()
print(type(check))
if debug:
print(str(numSolutions) + " | Checking:")
print(check)
v = check.validate()
# EDIT: added more of the code; problem seems to arise here
if v == 0:
if debug:
print("Solution!")
numSolutions += 1
if n <= max:
solutions.append(check)
elif v > 0:
if debug:
print(str(v) + " more")
frontier.append(check.branch())
else:
if debug:
print("Invalid state")
pass
expected output:
<class 'queens.Queens'>
actual output:
<class 'queens.Queens'>
<class 'list'>
(yes, the one type statement printed 2 lines)
EDIT: Since there seems to be no problem with the main code, here's the file in which I defined the class:
import array
import copy
class Queens:
__slots__ = ["n", "qlist"]
def __init__(self, n, qa=None):
self.n = n # store for print function
if qa == None:
self.qlist = array.array("h")
elif type(qa) == list:
self.qlist = array.array("h", qa)
else:
assert type(qa) == array.array
self.qlist = qa # list of positions for each line
def __str__(self):
out = ""
for q in range(self.n):
if q == 0:
out += "|"
else:
out += "\n|"
for space in range(self.n):
if q < len(self.qlist) and space == self.qlist[q]:
out += "Q|"
else:
out += " |"
return out
def branch(self):
out = []
for x in range(self.n):
if x not in self.qlist:
qlist = copy.deepcopy(self.qlist)
qlist.append(x)
out.append(Queens(self.n, qlist))
return out
def validate(self):
for y in range(len(self.qlist)):
# don't need to check horizontal;
# data structure doesn't let you place them
# don't need to check vertical;
# branching eliminates those
# check diagonals
for y2 in range(len(self.qlist)):
if y != y2:
expected = self.qlist[y] - y + y2
if 0 <= expected < self.n and self.qlist[y2] == expected:
return -1
expected = self.qlist[y] + y - y2
if 0 <= expected < self.n and self.qlist[y2] == expected:
return -1
return self.n - len(self.qlist)
if __name__ == "__main__":
q = Queens(4)
print(q.validate())
q = Queens(4, [0, 1, 2])
print(q.validate())
I've figured it out. The problem happened only after frontier.append(check.branch()). branch() returns a list of queens. I thought I was appending several queens to frontier, but I was, in fact, appending a list of queens to frontier. Changing append to extend solved the issue.
When you append to your frontier the result of .branch(..) and you re-iterate you get an array back (list). Which is being printed after the loop continues to the next step.
def branch(self):
out = []
for x in range(self.n):
if x not in self.qlist:
qlist = copy.deepcopy(self.qlist)
qlist.append(x)
out.append(Queens(self.n, qlist))
return out

How to improve performance of this python code?

I am solving a puzzle (Finding if there exists an input for a given automata for which no matter what the starting state is, final state would be same everytime) and have written following python code. A few testcases are written in check method in the code. For these cases program is running fairly fast. However, for testcases where 50 lists(nodes) are present, the programis taking forever to execute. I am storing intermediate results to use further as well. Can someone please review the code and give suggestions on how to increase the performance of the code?
from itertools import product
from copy import deepcopy
class Node:
def __init__(self,id):
self.id = id
self.dict = {}
def __str__(self):
return str(id) + " : " + str(self.dict)
def __repr__(self):
return str(id) + " : " + str(self.dict)
def tryDelete(nodes,_len):
for id in nodes:
y = deepcopy(nodes)
x = y[id]
del y[id]
for id,node in y.items():
for input,result in node.dict.items():
if result == x:
if x.dict[input] == x:
node.dict[input] = node
else:
node.dict[input] = x.dict[input]
pass
if pathPossible(y,_len ,False) == -1:
return x.id
return -2
target = {}
def FindTarget(node,p):
if len(p) == 1:
return node.dict[p[0]]
if node not in target or p not in target[node]:
x = FindTarget(node,p[:-1]).dict[p[-1]]
if node not in target:
target[node] = {}
target[node][p] = x
return target[node][p]
def allSatisy(nodes,p):
x = None
for key,node in nodes.items():
if x is None:
x = FindTarget(node,p)
elif FindTarget(node,p) != x:
return False
return True
def allPossiblePaths(l,n):
#x = int(((l+1)*(l+2))/2)
for i in range(1, n+1):
for p in product(range(l),repeat=i):
yield p
def pathPossible(nodes,_len ,isItereate=True):
i = 1
isFound = False
for p in allPossiblePaths(_len,len(nodes)):
if allSatisy(nodes,p):
isFound = True
break
if isFound:
return -1
elif not isItereate:
return -2
else:
return tryDelete(nodes,_len)
def answer(li):
nodes = {}
for i in range(len(li)):
nodes[i] = Node(i)
for i in range(len(li)):
for j in range(len(li[i])):
nodes[i].dict[j] = nodes[li[i][j]]
return pathPossible(nodes,len(nodes[0].dict))
def check(li,ans):
# each item in the list is a node, each item i-th in the inner list tells to what node the transition happens for input i
x = answer(li)
print(str(li) + " : " + str(ans) + " : " + str(x))
def main():
check([[2,1],[2,0],[3,1],[1,0]],-1)
check([[1,2],[1,1],[2,2]],1)
check([[1,3,0],[1,0,2],[1,1,2],[3,3,3]],-1)
if __name__ == '__main__':
main()
UPDATE: I have done few code changes, but still this needs some review from you guys. Changed code:
from itertools import product
from copy import deepcopy
class Node:
def __init__(self,id):
self.id = id
self.dict = {}
def __str__(self):
return str(self.id) + " : " + str(self.dict)
def __repr__(self):
return str(self.id) + " : " + str(self.dict)
def tryDelete(nodes,_len):
for i in range(len(nodes)):
y = nodes[:]
x = y[i]
del y[i]
tNodes = []
for node in y:
for input,result in node.dict.items():
if result == x:
node.tDict = deepcopy(node.dict)
if x.dict[input] == x.id:
node.dict[input] = node
else:
node.dict[input] = x.dict[input]
if pathPossible(y,_len ,False) == -1:
return x.id
for n in tNodes:
n.dict = n.tDict
del n.tDict
return -2
target = {}
def FindTarget(node,p):
if len(p) == 1:
return node.dict[p[0]]
if node not in target or p not in target[node]:
x = Gnodes[FindTarget(node,p[:-1])].dict[p[-1]]
if node not in target:
target[node] = {}
target[node][p] = x
return target[node][p]
def allSatisy(nodes,p):
x = None
for node in nodes:
if x is None:
x = FindTarget(node,p)
elif FindTarget(node,p) != x:
return False
return True
def allPossiblePaths(l,n):
#x = int(((l+1)*(l+2))/2)
for i in range(1, n + 1):
for p in product(range(l),repeat=i):
yield p
def pathPossible(nodes,_len ,isItereate=True):
i = 1
isFound = False
for p in allPossiblePaths(_len,len(nodes)):
if allSatisy(nodes,p):
isFound = True
break
if isFound:
return -1
elif not isItereate:
return -2
else:
return tryDelete(nodes,_len)
Gnodes = []
def answer(li):
Gnodes[:] = []
for i in range(len(li)):
Gnodes.append(Node(i))#[i] = Node(i)
for i in range(len(li)):
for j in range(len(li[i])):
Gnodes[i].dict[j] = li[i][j]
return pathPossible(Gnodes,len(Gnodes[0].dict))
def check(li,ans):
x = answer(li)
print(str(li) + " : " + str(ans) + " : " + str(x))
def main():
check([[2,1],[2,0],[3,1],[1,0]],-1)
check([[1,2],[1,1],[2,2]],1)
check([[1,3,0],[1,0,2],[1,1,2],[3,3,3]],-1)
if __name__ == '__main__':
main()
There is a wonderful graph library called NetworkX. It deals with creating graphs and path finding. You specify what edges or paths exist in your Graph and you can find paths using a plethora of algorithms like breadth first search, or A*, and many others in the algorithms section. The best way to optimize your time is code reuse.
https://networkx.github.io

Recursive Path finding error

I'm working on an exercise where given a set of connections between two points (ie. 12 is a connection between 1 and 2 ect.). I decided to tackle the approach recursively in order to have it systematically check every path and return when it finds one that hits every node and starts and ends with one.
However upon debugging this it seems that as I pass down the adjMatrix further into the recursion it's also editing the upper levels and causing it not to search any further as it goes back up the tree. I think it has something to when I set newMatrix = adjMatrix, but I'm not exactly sure.
def checkio(teleports_string):
#return any route from 1 to 1 over all points
firstnode, secondnode, size = 0, 0, 8
#Makes the adjacency matrix
adjMatrix = [[0 for i in range(size)] for j in range(size)]
for x in teleports_string:
#Assigns Variables
if firstnode == 0 and x != ",":
#print("Node1:" + x)
firstnode = x
elif secondnode == 0 and x != ",":
#print("Node2:" + x)
secondnode = x
#Marks connections
if firstnode != 0 and secondnode != 0:
adjMatrix[int(firstnode) - 1][int(secondnode) - 1] = 1
adjMatrix[int(secondnode) - 1][int(firstnode) - 1] = 1
firstnode, secondnode = 0, 0
print(adjMatrix)
return findPath(adjMatrix, 1, "1")
def findPath(adjMatrix, currentnode, currentpath):
if isFinished(currentpath):
return currentpath
for x in range(0, 8):
if adjMatrix[currentnode - 1][x] == 1:
print(currentpath + "+" + str(x+1))
newMatrix = adjMatrix
newMatrix[currentnode - 1][x] = 0
newMatrix[x][currentnode - 1] = 0
temp = currentpath
temp += str(x+1)
newpath = findPath(newMatrix, x+1,temp)
print(newpath)
if isFinished(newpath):
print ("Returning: " + newpath)
return newpath
return ""
def isFinished(currentpath):
#Checks if node 1 is hit at least twice and each other node is hit at least once
if currentpath == "":
return False
for i in range(1, 9):
if i == 1 and currentpath.count(str(i)) < 2:
return False
elif currentpath.count(str(i)) < 1:
return False
#Checks if it starts and ends with 1
if not currentpath.startswith(str(1)) or not currentpath.endswith(str(1)):
return False
return True
#This part is using only for self-testing
if __name__ == "__main__":
def check_solution(func, teleports_str):
route = func(teleports_str)
teleports_map = [tuple(sorted([int(x), int(y)])) for x, y in teleports_str.split(",")]
if route[0] != '1' or route[-1] != '1':
print("The path must start and end at 1")
return False
ch_route = route[0]
for i in range(len(route) - 1):
teleport = tuple(sorted([int(route[i]), int(route[i + 1])]))
if not teleport in teleports_map:
print("No way from {0} to {1}".format(route[i], route[i + 1]))
return False
teleports_map.remove(teleport)
ch_route += route[i + 1]
for s in range(1, 9):
if not str(s) in ch_route:
print("You forgot about {0}".format(s))
return False
return True
assert check_solution(checkio, "13,14,23,25,34,35,47,56,58,76,68"), "Fourth"
The line
newMatrix = adjMatrix
merely creates another reference to your list. You'll need to actually create a new list object. As this is a matrix, do so for the contents:
newMatrix = [row[:] for row in adjMatrix]
This creates a new list of copies of your nested lists.

Categories