First Search Program - Artificial Intelligence for Robotics path printing - python

I'm new at Python programming and I'm doing my best to fully understand this code. Here we are printing the path for the First Search Program - Artificial Intelligence for Robotics algorithm. I know how the basic of these lines are working in general, but how they work here in this code. Could I get some clarification for this piece of code below, please?.
This is below the piece of code:
policy=[[' ' for row in range(len(grid[0]))] for col in range(len(grid))]
x=goal[0]
y=goal[1]
policy[x][y]='*'
while x !=init[0] or y !=init[1]:
x2=x-delta[action[x][y]][0]
y2=y-delta[action[x][y]][1]
policy[x2][y2]= delta_name[action[x][y]]
x=x2
y=y2
for i in range(len(policy)):
print(policy[i])
This is the code:
#grid format
# 0 = navigable space
# 1 = occupied space
grid = [[0,0,1,0,0,0],
[0,0,1,0,0,0],
[0,0,0,0,1,0],
[0,0,1,1,1,0],
[0,0,0,0,1,0]]
init = [0,0] #Start location is (0,0) which we put it in open list.
goal = [len(grid)-1,len(grid[0])-1] #Our goal in (4,5) and here are the coordinates of the cell.
#Below the four potential actions to the single field
delta = [[-1 , 0], #up by subtracting one from the first dimention, I mean the demension of (0,0)
[ 0 ,-1], #left
[ 1 , 0], #down
[ 0 , 1]] #right
delta_name = ['^','<','V','>'] #The name of above actions
cost = 1 #Each step costs you one
def search():
#open list elements are of the type [g,x,y]
#To check cells once they expanded and don't expand them again. We defined an array called closed
#and its size as our grid. It has two values 0 & 1. 0 means open and 1 means closed.
closed = [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
action=[[-1 for row in range(len(grid[0]))] for col in range(len(grid))]
#We initialize the starting location as checked
closed[init[0]][init[1]] = 1
# we assigned the cordinates and g value
x = init[0]
y = init[1]
g = 0
#our open list will contain our initial value
open = [[g, x, y]]
found = False #flag that is set when search complete
resign = False #Flag set if we can't find expand
#print('initial open list:')
#for i in range(len(open)):
#print(' ', open[i])
#print('----')
while found is False and resign is False:
#Check if we still have elements in the open list
if len(open) == 0: #If our open list is empty, there is nothing to expand.
resign = True
print('Fail')
print('############# Search terminated without success')
else:
#if there is still elements on our list
#remove node from list
open.sort() #sort elements in an increasing order from the smallest g value up
open.reverse() #reverse the list
next = open.pop() #remove the element with the smallest g value from the list
#print('list item')
#print('next')
#Then we assign the three values to x,y and g. Which is our expantion.
x = next[1]
y = next[2]
g = next[0]
#Check if we are done
if x == goal[0] and y == goal[1]:
found = True
print(next) #The three elements above this "if".
print('############## Search is success')
else:
#expand winning element and add to new open list
for i in range(len(delta)): #going through all our actions the four actions
#We apply the actions to x and y with additional delta to construct x2 and y2
x2 = x + delta[i][0]
y2 = y + delta[i][1]
#if x2 and y2 falls into the grid
if x2 >= 0 and x2 < len(grid) and y2 >=0 and y2 <= len(grid[0])-1:
#if x2 and y2 not checked yet and there is not obstacles
if closed[x2][y2] == 0 and grid[x2][y2] == 0:
g2 = g + cost #we increment the cose
open.append([g2,x2,y2]) #we add them to our open list
#print('append list item')
#print([g2,x2,y2])
#Then we check them to never expand again
closed[x2][y2] = 1
action[x2][y2]=i
policy=[[' ' for row in range(len(grid[0]))] for col in range(len(grid))]
x=goal[0]
y=goal[1]
policy[x][y]='*'
while x !=init[0] or y !=init[1]:
x2=x-delta[action[x][y]][0]
y2=y-delta[action[x][y]][1]
policy[x2][y2]= delta_name[action[x][y]]
x=x2
y=y2
for i in range(len(policy)):
print(policy[i])
search()

Related

Optimization of a Needleman Wunsch algorithm

For some Time, I've written a Needleman Wunsch algorithm for listening to NCBI data streams, but as I've been done with it i knew it could be done better but i by far to stupid to do so. If some of you know what I've done stupid overcomplicated, I would really like to know how to do it better.
At first I want to show you the full code to let you know about the context.
#!/usr/bin/env python
import pandas as pd #to create data frames
from numpy import full #to build the arrays
import subprocess
import os
from itertools import groupby
def needlemanWunsch(lista, listb, rowLen, colLen): #o(n*m)
levensteinTable = full([rowLen, colLen],0)
for j in range(0,colLen): #Fill out the first row
levensteinTable[0, j] = j
for i in range(0,rowLen): #Fill out the first column
levensteinTable[i, 0] = i
for i in range(1,rowLen): #Fill out the rest of the Board in dependency of several cases
for j in range (1,colLen): #traversing with a nested loop
levensteinTable[i,j]=min( #every Levenstein Score has to be the Minimum of three cases
(levensteinTable[i-1, j-1]+(0 if listb[j-1] == lista[i-1] else 1)), #in this part, the Delta of the two strings will be detected
(levensteinTable[i, j-1] +1), #The score of the left cell
(levensteinTable[i-1, j] +1) #The Score of the upper cell
)
return levensteinTable #the finished levenstein Table will be returned
upArrow = "\u2191"
right_arrow = "\u2192"
down_arrow = "\u2193"
leftArrow = "\u2190"
down_right_arrow = "\u2198"
upLeftArrow = "\u2196"
def needlemanWunschTraceBack(listx,listy,rows,columns, gapPenalty = -1, matchBonus = 1, mismatchPenalty = -1): #o(n*m)
#This algorithm will fill out the Penalty Scoreboard and the Arrow Score board
penaltyArray = full([rows, columns],0) #build up the penalty score Array
tracerArray = full([rows, columns],"-") #build up the Array for the traceback arrows
for row in range(rows): #filling the two arrays
for col in range(columns):
if row==0 and col==0: #the first cell
score = 0 #the first Cell doesn't have any alignment
arrow = "-" #no Alignment, no arrow
elif row==0 and col!=0: #the first Row
score = penaltyArray[row, col -1]+gapPenalty #every Cell in this row need his score
arrow = leftArrow #every Arrow in this row has to look up to the start of the array
elif row!=0 and col == 0: #the first column
score = penaltyArray[row-1, col]+gapPenalty #every Cell in this column need his score
arrow = upArrow #every Arrow in this row has to look up to the start of the array
else: #in this case, every other cell will be processed
fromLeftScore = penaltyArray[row,col-1] + gapPenalty #The score of the former left cell + gapPenalty
fromAboveScore = penaltyArray[row-1,col] + gapPenalty #The score of the former Above cell
diagonalLeftCellScore = penaltyArray[row-1,col-1] +(
matchBonus if(listx[row -1]==listy[col-1])else mismatchPenalty
) #if the alighment matches with the former diagonal left cell, it gets a match bonus, else a mismatchPenalty
score = max([fromLeftScore, fromAboveScore, diagonalLeftCellScore]) #The score of our Cell has to be the maximum of the three given scores
arrow =(leftArrow if score==fromLeftScore else upArrow if score==fromAboveScore else\
upLeftArrow if score==diagonalLeftCellScore else 0)
#the right arrow of every cell will be seperately detected
tracerArray[row, col]=arrow #the tracerArray gets the arrows
penaltyArray[row, col]=score #the penaltyArray gets the scores
return tracerArray, penaltyArray
def traceback_alignment(traceback_array,listC,listD,up_arrow = upArrow ,\
left_arrow=leftArrow,up_left_arrow=upLeftArrow,stop="-"): #o(n)
row = len(listC) #The Traceback Algo needs the sequences anyway
col = len(listD)
arrow = traceback_array[row,col] #to get the right arrow for the current position
alignedSeq1 = "" #to initiate the produced alignment upper line
alignedSeq2 = "" #to initiate the produced alignment under line
alignmentIndicator = "" #to indicate the alighment
while arrow != "-": #No Arrow, no interes
arrow = traceback_array[row,col] #the current position in the array inside the loop
print(f"Currently on row: {row} and col: {col}; Arrow: {arrow}") #Because you could get bored without visual process indication
if arrow == up_arrow: #up_arrow shows a gap in under sequence
alignedSeq2 = "-"+alignedSeq2
alignedSeq1 = listC[row-1] + alignedSeq1
alignmentIndicator = " "+alignmentIndicator #to show that here is no alignment
row -=1
elif arrow == up_left_arrow: #up_left_arrow shows that here is accordance between the sequences
alignedSeq1 = listC[row-1] + alignedSeq1
alignedSeq2 = listD[col-1] + alignedSeq2
if listC[row-1] == listD[col-1]:
alignmentIndicator = "|"+alignmentIndicator #visual indicator for accordance
else:
alignmentIndicator = " "+alignmentIndicator #visual indicator for no accordance
row -=1
col -=1
elif arrow == left_arrow:
alignedSeq1 = "-"+alignedSeq1
alignedSeq2 = listD[col-1] + alignedSeq2
alignmentIndicator = " "+alignmentIndicator #visual indicator for no accordance
col -=1
elif arrow == stop:
break
else:
raise ValueError(
f"Traceback array entry at {row},{col}: {arrow}" \
f"is not recognized as an up arrow ({up_arrow}),left_arrow ({left_arrow}), "\
f"up_left_arrow ({up_left_arrow}), or a stop ({stop})."
)
return f"{alignedSeq1}\n{alignmentIndicator}\n{alignedSeq2}"
def seqHandle(seq1, seq2): #to handle a two given Sequences o(n*m)
columnLabels = [label for label in "-"+seq1] #for the later buildet Dataframes
rowLabels = [label for label in "-"+seq2] ##for the later buildet Dataframes
nRows = len("-"+seq1) #Count of all rows
nColumns = len("-"+seq2) #Count of all columns
levensteinBoard = needlemanWunsch(seq1, seq2,nRows,nColumns) #to build the Board with the levensteinDistances
arrowArray, zuchtArray, = needlemanWunschTraceBack(seq1, seq2,nRows, nColumns) #Important for the traceback
levensteinDistance = levensteinBoard[len(seq1)][len(seq2)] #I'll explain the Levenstein Distance in the Readme
return (
f"This is our ScoreBoard with all the important distances\n"\
f"{pd.DataFrame(levensteinBoard, index=columnLabels, columns= rowLabels)}\n"\
f"The Levenstein Distance of{seq1} and {seq2} is {levensteinDistance}.\n"\
f"The trace back arrow board:\n{pd.DataFrame(arrowArray, index=columnLabels, columns= rowLabels)}\n"\
f"The Penalty Score Board:\n{pd.DataFrame(zuchtArray, index=columnLabels, columns= rowLabels)}\n"\
f"{traceback_alignment(arrowArray,seq1,seq2)}"), levensteinDistance
def fileProcessGenerator(fileE): #to iterate over a SequenceSummaryFile o(n)
with open(f'{os.getcwd()}/{fileE}', 'r') as fh: #to savely work with the given file
faiter = (x[1] for x in groupby(fh, lambda line: line[0] ==">")) #to group the single sequences to their related header Line
for header in faiter:
headerStr = header.__next__()[1:].strip() #to fetch the header line from the group
yield (
headerStr.strip().replace('>', '').split()[0], #name of the sequence
''.join(s.strip() for s in faiter.__next__())) #sequence
def FileOfSequencesAnalisis(fileName, OutputPath): #to analyse a SequenceSummaryFile o(n*m*a*b)
print(f"\n\n Warning: I'll proceed really a lot of Sequence combinations Sequences.\n\n This will take Time! Please stay patient")
processnumber = 1 #We want to know, in which process we are
levensteinDistanceCounter= 0 #To count all Levenstein distances so far
LevensteinDistancesAverage = 0 #to calculate the average of all levenstein distances so far
try: #because someone could try shit
for ff in fileProcessGenerator(fileName): #the main loop devines the sequence in the line
for fo in fileProcessGenerator(fileName): #the main loop devines the sequence in the column
if ff != fo: #nobody wants to know the levenstein Distance of two identical sequences
name, seqOne, = ff #to get the important stuff from the generator
namel, seqTwo, = fo
print(
f"processing for {name} and {namel} -Process Nr.{processnumber}\n"\
f"current average Levenstein Distances is {LevensteinDistancesAverage}") #to show, that the process works well
seqHandling, currentLevensteinDistance = seqHandle(seqOne, seqTwo) #to get the struff from seqHandle
with open(f"{OutputPath}/For_{name}_and_{namel}.txt", 'w') as bitch: #to savely save our Output to a file
bitch.write(f"Analysis for {name} and {namel}: \n{seqHandling}")
levensteinDistanceCounter += currentLevensteinDistance
LevensteinDistancesAverage = levensteinDistanceCounter/processnumber
processnumber += 1
except RuntimeError:
print("invalid File. Use a File with inherited fasta Sequences with a Header Line and Sequences")
print(f"I'm done. Here is the average Levenstein Distance of the analysed File:\n{LevensteinDistancesAverage}")
Now I'll show you, what I've been unsatisfied with
def needlemanWunsch(lista, listb, rowLen, colLen): #o(n*m)
levensteinTable = full([rowLen, colLen],0)
for j in range(0,colLen): #Fill out the first row
levensteinTable[0, j] = j
for i in range(0,rowLen): #Fill out the first column
levensteinTable[i, 0] = i
for i in range(1,rowLen): #Fill out the rest of the Board in dependency of several cases
for j in range (1,colLen): #traversing with a nested loop
levensteinTable[i,j]=min( #every Levenstein Score has to be the Minimum of three cases
(levensteinTable[i-1, j-1]+(0 if listb[j-1] == lista[i-1] else 1)), #in this part, the Delta of the two strings will be detected
(levensteinTable[i, j-1] +1), #The score of the left cell
(levensteinTable[i-1, j] +1) #The Score of the upper cell
)
return levensteinTable #the finished levenstein Table will be returned
I've tried to turn every for loop into a comprehension, but somehow there are things I don't know and even don't know for what kind of comprehension I need to search for.
II've tried to turn every for loop into a comprehension, but somehow there are things I don't know and even don't know for what kind of comprehension I need to search for.
from numpy import full #to build the arrays
def needlemanWunsch(lista, listb, rowLen, colLen): #o(n*m)
levensteinTable = full([rowLen, colLen],0)
#for j in range(0,colLen): #Fill out the first row
# levensteinTable[0, j] = j
levensteinTable[0, [j for j in range(0, colLen)]]
#for i in range(0,rowLen): #Fill out the first column
# levensteinTable[i, 0] = i
levensteinTable[[i for i in range(0, rowLen)], 0]
for i in range(1,rowLen): #Fill out the rest of the Board in dependency of several cases
for j in range (1,colLen): #traversing with a nested loop
levensteinTable[i,j]=min( #every Levenstein Score has to be the Minimum of three cases
(levensteinTable[i-1, j-1]+(0 if listb[j-1] == lista[i-1] else 1)), #in this part, the Delta of the two strings will be detected
(levensteinTable[i, j-1] +1), #The score of the left cell
(levensteinTable[i-1, j] +1) #The Score of the upper cell
)
return levensteinTable #the finished levenstein Table will be returned
seq1, seq2= "ATTACA","ATGCT"
nRows, nColumns = len("-"+seq1), len("-"+seq2)
print(needlemanWunsch(seq1, seq2, nRows, nColumns))
but Output of this is like:
[[0 0 0 0 0 0]
[0 0 1 1 1 1]
[0 1 0 1 2 1]
[0 1 1 1 2 2]
[0 0 1 2 2 3]
[0 1 1 2 2 3]
[0 0 1 2 3 3]]

I need to be able to 'rotate' a list thats in a 'square' looking formation into a diamond shape python

I am creating a word search solver and need a way to rotate the word search, which is in a list, so the left corner is the 'top' and the bottom right is at the 'bottom'
I have this:
Puzzle = ["FUNCTIONRRIRAI",
"RAIOONFRCCPWON",
"PTCSNOBEUITOLO",
"BNCACIANTOSLIH",
"RBYOLILYNREFBT",
"HYYNOGESTIBRIY",
"AATTSIONCMCENP",
"UORTENRRCBFVAU",
"CEBEECVWIERORI",
"PROCESSORTOPYF",
"OHCOMPUTERHSOS",
"YCYPRESREOSMRW",
"OATHBRMVTHHCTR",
"PGORWOOUIPSCHP"]
I need it in the formation of:
Puzzle = ["F","RU","PAN","BTIC",...]
so it appears that the word search has been rotated 45 degrees
any suggestions/help would be appreciated
Code for find_horizontal and words to find:
def load_words_to_find(file_name):
word_list = []
file = open(file_name, "r")
for line in file.readlines():
word_list.append(line)
word_list = list(map(lambda s: s.strip(), word_list))
return word_list
def find_horizontal(Puzzle, Words, ReplaceWith, Found):
# Parameters :- List:Puzzle, List:Words, Character:ReplaceWith, List:Found
# Return :- List:Outpuz, List:Found
# Find all words which are horizontally in place (left to right and right to left), return the puzzle and list of found words
rev = ''
Outpuz = Puzzle
for line in Puzzle:
rev = line[::-1]
for word in Words:
if word in line:
Found.append(word)
Puzzle[Puzzle.index(line)] = line.replace(word, ReplaceWith * len(word))
if word in rev:
Found.append(word)
Puzzle[Puzzle.index(line)] = line.replace(word[::-1], ReplaceWith * len(word))
else:
pass
print("Found: ", Found)
print(Outpuz)
return Outpuz, Found
find_horizontal(Puzzle, load_words_to_find("words.txt"), ".", [])
Kind of silly, but you could insert string iterators to the front of a list, and then join and yield the next character from each iterator.
rows = [
"FUNCTIONRRIRAI",
"RAIOONFRCCPWON",
"PTCSNOBEUITOLO",
"BNCACIANTOSLIH",
"RBYOLILYNREFBT",
"HYYNOGESTIBRIY",
"AATTSIONCMCENP",
"UORTENRRCBFVAU",
"CEBEECVWIERORI",
"PROCESSORTOPYF",
"OHCOMPUTERHSOS",
"YCYPRESREOSMRW",
"OATHBRMVTHHCTR",
"PGORWOOUIPSCHP"
]
def get_next_diagonal(rows):
iters = []
for row in rows:
iters.insert(0, iter(row))
yield "".join(next(it, "") for it in iters)
while iters[0].__length_hint__():
yield "".join(next(it, "") for it in iters)
for diagonal in get_next_diagonal(rows):
print(diagonal)
Output:
F
RU
PAN
BTIC
RNCOT
HBCSOI
AYYANNO
UAYOCOFN
COTNLIBRR
PERTOIAECR
ORBTSGLNUCI
YHOEEIEYTIPR
OCCCENOSNOTWA
PAYOECRNTRSOOI
GTPMSVRCIELLN
OHRPSWCMBFIO
RBEUOIBCRBH
WRSTREFEIT
OMRETRVNY
OVEROOAP
UTOHPRU
IHSSYI
PHMOF
SCRS
CTW
HR
P
Apologies for the lack of efficiency, but here is my quick solution.
We view the grid as a set of coordinates. This solution is based off the fact that every item in the output you want will have X and Y coordinates than add up to a certain number. For example, the first item "F" has a location of (0,0), which sum to 0. The second two items "RU" are located ad (1,0) and (0,1), which both add up to 1. The third line "PAN" has letters located at (0,2), (1,1) and (2,0), and so on. Tracking this number with "i" in my solution, it needs to be big enough to scan down and across the lists, so this is twice the size of the length of the array. So we scan the list for items that are located at x and y coordinates where x+y==i.
Code:
Puzzle = ["FUNCTIONRRIRAI",
"RAIOONFRCCPWON",
"PTCSNOBEUITOLO",
"BNCACIANTOSLIH",
"RBYOLILYNREFBT",
"HYYNOGESTIBRIY",
"AATTSIONCMCENP",
"UORTENRRCBFVAU",
"CEBEECVWIERORI",
"PROCESSORTOPYF",
"OHCOMPUTERHSOS",
"YCYPRESREOSMRW",
"OATHBRMVTHHCTR",
"PGORWOOUIPSCHP"]
output = []
i = 0
while i < len(Puzzle)*2:
single_string = ""
for y in range(0,len(Puzzle)):
for x in range(0,len(Puzzle[0])):
if (x + y) == i:
single_string += Puzzle[x][y]
if single_string != "":
output.append(single_string)
i += 1
print(output)
Outputs
['F',
'RU',
'PAN',
'BTIC',
'RNCOT',
'HBCSOI',
'AYYANNO',
'UAYOCOFN',
'COTNLIBRR',
'PERTOIAECR',
'ORBTSGLNUCI',
'YHOEEIEYTIPR',
'OCCCENOSNOTWA',
'PAYOECRNTRSOOI',
'GTPMSVRCIELLN',
'OHRPSWCMBFIO',
'RBEUOIBCRBH',
'WRSTREFEIT',
'OMRETRVNY',
'OVEROOAP',
'UTOHPRU',
'IHSSYI',
'PHMOF',
'SCRS',
'CTW',
'HR',
'P']
Hope this helps. Happy to clarify anything if needed
I find it easier and clearer to just generate the indexes in two loops, down the rows starting at the first column and then along the columns starting at the last row:
puzzle = ['FUNCTIONRRIRAI',
'RAIOONFRCCPWON',
'PTCSNOBEUITOLO',
'BNCACIANTOSLIH',
'RBYOLILYNREFBT',
'HYYNOGESTIBRIY',
'AATTSIONCMCENP',
'UORTENRRCBFVAU',
'CEBEECVWIERORI',
'PROCESSORTOPYF',
'OHCOMPUTERHSOS',
'YCYPRESREOSMRW',
'OATHBRMVTHHCTR',
'PGORWOOUIPSCHP']
nrows = len(puzzle)
ncols = len(puzzle[0])
output = []
for ir in range(nrows):
row = []
ic = 0
jr = ir
while jr >= 0:
row.append(puzzle[jr][ic])
ic += 1
jr -= 1
output.append(''.join(row))
for ic in range(1, ncols):
row = []
ir = nrows - 1
jc = ic
while jc < ncols:
row.append(puzzle[ir][jc])
ir -= 1
jc += 1
output.append(''.join(row))
for row in output:
print(row)
Output:
F
RU
PAN
BTIC
RNCOT
HBCSOI
AYYANNO
UAYOCOFN
COTNLIBRR
PERTOIAECR
ORBTSGLNUCI
YHOEEIEYTIPR
OCCCENOSNOTWA
PAYOECRNTRSOOI
GTPMSVRCIELLN
OHRPSWCMBFIO
RBEUOIBCRBH
WRSTREFEIT
OMRETRVNY
OVEROOAP
UTOHPRU
IHSSYI
PHMOF
SCRS
CTW
HR
P
Variation on a theme - generate diagonal indices.
If you trace your finger down the left edge, those are the starting point for the top-half diagonals and tracing your finger across the bottom edge are starting points for the bottom-half diagonals.
Top Half:
From each diagonal's starting point the first dimension's indices range from the starting point to zero (negative steps) and the second dimension's indices range from zero to a maximum of the length of the second dimension (positive steps).
Bottom Half:
From each diagonal's starting point the first dimension's indices range from the length of the first dimension minus one to a minimum of zero (negative steps) and the second dimension's indices range from the starting point to a the length of the second dimension (positive steps).
For both sets of diagonals you can take advantage of the fact that zip will stop when the shortest iterable is exhausted.
def cw(dims,ragged=False):
'''Generate indices for diagonals based on dims.
dims --> tuple: (nrows,ncolumns)
Currently only implemented for all rows have same number of columns
Diagonals as if the rectangle was rotated CW 45 degrees
bottom-left to upper-right
'''
if ragged: raise NotImplementedError
nrows,ncolumns = dims
# top half
index1 = range(0,ncolumns)
for i in range(nrows):
yield zip(range(i,-1,-1),index1)
# bottom half
index0 = range(nrows-1,-1,-1)
for i in range(1,nrows):
yield zip(index0,range(i,ncolumns))
new = []
for diagonal in cw((len(Puzzle),len(Puzzle[0]))):
new.append(''.join(Puzzle[j][k] for (j,k) in diagonal))
And a CCW rotation solution
def ccw(dims,ragged=False):
'''Generate indices for diagonals based on dims.
dims --> tuple: (nrows,ncolumns)
Currently only implemented for all rows have same number of columns
Diagonals as if the rectangle was rotated CCW 45 degrees
top-left to bottom-right
'''
if ragged: raise NotImplementedError
nrows,ncolumns = dims
# top half
index0 = range(0,nrows)
for i in range(ncolumns,-1,-1):
yield zip(index0,range(i,ncolumns))
# bottom half
index1 = range(0,ncolumns)
for i in range(1,nrows):
yield zip(range(i,nrows),index1,)

Why does this code do closed[init[0]][init[1]] instead of closed[init[0]][init[0]]?

I'm reading this First Search Program - Artificial Intelligence for Robotics algorithm and I'm reading a python code of it. Here we have created a closed array to check cells once they expanded and don't expand them again. We defined an array called closed and its size as our grid. The author said it has two values 0 & 1. 0 means open and 1 means closed, but I saw it just zeros.
He marked the starting point 0,0 by 1 until not to check them, but he put the coordinate as 0 and 1 in this line closed[init[0]][init[1]] = 1. Why he put 0 and 1 instead of 0,0?
The python code is here:
#grid format
# 0 = navigable space
# 1 = occupied space
grid=[[0,0,1,0,0,0],
[0,0,1,0,0,0],
[0,0,0,0,1,0],
[0,0,1,1,1,0],
[0,0,0,0,1,0]]
init = [0,0]
goal = [len(grid)-1,len(grid[0])-1]
delta=[[-1, 0], #up
[ 0,-1], #left
[ 1, 0], #down
[ 0, 1]] #right
delta_name = ['^','<','V','>'] #The name of above actions
cost = 1
def search():
#open list elements are of the type [g,x,y]
closed = [[0 for row in range(len(grid[0]))] for col in range(len(grid))]
#We initialize the starting location as checked
closed[init[0]][init[1]] = 1
# we assigned the cordinates and g value
x = init[0]
y = init[1]
g = 0
#our open list will contain our initial value
open = [[g,x,y]]
found = False #flag that is set when search complete
resign= False #Flag set if we can't find expand
#print('initial open list:')
#for i in range(len(open)):
#print(' ', open[i])
#print('----')
while found is False and resign is False:
#Check if we still have elements in the open list
if len(open)==0: #If our open list is empty
resign=True
print('Fail')
print('############# Search terminated without success')
else:
#if there is still elements on our list
#remove node from list
open.sort()
open.reverse() #reverse the list
next = open.pop()
#print('list item')
#print('next')
#Then we assign the three values to x,y and g. Which is our expantion
x = next[1]
y = next[2]
g = next[0]
#Check if we are done
if x == goal[0] and y == goal[1]:
found = True
print(next) #The three elements above this if
print('############## Search is success')
else:
#expand winning element and add to new open list
for i in range(len(delta)):
x2 = x+delta[i][0]
y2 = y+delta[i][1]
#if x2 and y2 falls into the grid
if x2 >= 0 and x2 < len(grid) and y2 >=0 and y2 <= len(grid[0])-1:
#if x2 and y2 not checked yet and there is not obstacles
if closed[x2][y2] == 0 and grid[x2][y2] == 0:
g2 = g+cost #we increment the cose
open.append([g2,x2,y2])#we add them to our open list
#print('append list item')
#print([g2,x2,y2])
#Then we check them to never expand again
closed[x2][y2] = 1
search()
he put the coordinate as 0 and 1 in this line closed[init[0]][init[1]] = 1
closed[init[0]][init[1]] does not mean "set the value at coordinates (0,1) to 1". It means "using init[0] as the x coordinate and init[1] at the y coordinate, set the value to 1". init[0] is 0, and init[1] is 0, so closed[init[0]][init[1]] = 1 sets closed[0][0] to 1.
Suppose the starting coordinate was init = [2,5]. It would be incorrect to change the line to closed[init[2]][init[5]] = 1. This would crash with an IndexError, because init only has two elements, so you can only index it with 0 or 1.

How to add a stopping condition for Jacobian Matrix?

def jacobi(m,numiter=100):
#Number of rows determins the number of variables
numvars = m.shape[0]
#construct array for final iterations
history = np.zeros((numvars,numiter))
i = 1
while(i < numiter): #Loop for numiter
for v in range(numvars): # Loop over all variables
current = m[v,numvars] # Start with left hand side (augmented side of matrix)
for col in range(numvars): #Loop over columns
if v != col: # Don't count colume for current variable
current = current - (m[v,col]*history[col, i-1]) #subtract other guesses form previous timestep
current = current/m[v,v] #divide by current variable coefficent
history[v,i] = current #Add this answer to the rest
i = i + 1 #iterate
#plot each variable
for v in range(numvars):
plt.plot(history[v,: i]);
return history[:,i-1]
I have this code that calculates Jacobian method. How do I add a stopping condition for when the solutions converge? i.e. the values for the current iteration have changed less than some threshold e from the values for the previous iteration.
The threshold e will be an input to the function and the default value to 0.00001
You could add another condition to your while loop, so when it reaches your error threshold it stops.
def jacobi(m,numiter=100, error_threshold = 1e-4):
#Number of rows determins the number of variables
numvars = m.shape[0]
#construct array for final iterations
history = np.zeros((numvars,numiter))
i = 1
err = 10*error_threshold
while(i < numiter and err > error_threshold): #Loop for numiter and error threshold
for v in range(numvars): # Loop over all variables
current = m[v,numvars] # Start with left hand side (augmented side of matrix)
for col in range(numvars): #Loop over columns
if v != col: # Don't count colume for current variable
current = current - (m[v,col]*history[col, i-1]) #subtract other guesses form previous timestep
current = current/m[v,v] #divide by current variable coefficent
history[v,i] = current #Add this answer to the rest
#check error here. In this case the maximum error
if i > 1:
err = max((history[:,i] - history[:,i-1])/history[:,i-1])
i = i + 1 #iterate
#plot each variable
for v in range(numvars):
plt.plot(history[v,: i]);
return history[:,i-1]

How to deal with very big Bitboards

I'm working on a 2-player board game (e.g. connect 4), with parametric board size h, w. I want to check for winning condition using hw-sized bitboards.
In game like chess, where board size is fixed, bitboards are usually represented with some sort of 64-bit integer. When h and w are not constant and maybe very big (let's suppose 30*30) are bitboards a good idea? If so, are the any data types in C/C++ to deal with big bitboards keeping their performances?
Since I'm currently working on python a solution in this language is appreciated too! :)
Thanks in advance
I wrote this code while ago just to play around with the game concept. There is no intelligence behaviour involve. just random moves to demonstrate the game. I guess this is not important for you since you are only looking for a fast check of winning conditions. This implementation is fast since I did my best to avoid for loops and use only built-in python/numpy functions (with some tricks).
import numpy as np
row_size = 6
col_size = 7
symbols = {1:'A', -1:'B', 0:' '}
def was_winning_move(S, P, current_row_idx,current_col_idx):
#****** Column Win ******
current_col = S[:,current_col_idx]
P_idx= np.where(current_col== P)[0]
#if the difference between indexes are one, that means they are consecutive.
#we need at least 4 consecutive index. So 3 Ture value
is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
if is_idx_consecutive:
return True
#****** Column Win ******
current_row = S[current_row_idx,:]
P_idx= np.where(current_row== P)[0]
is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
if is_idx_consecutive:
return True
#****** Diag Win ******
offeset_from_diag = current_col_idx - current_row_idx
current_diag = S.diagonal(offeset_from_diag)
P_idx= np.where(current_diag== P)[0]
is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
if is_idx_consecutive:
return True
#****** off-Diag Win ******
#here 1) reverse rows, 2)find new index, 3)find offest and proceed as diag
reversed_rows = S[::-1,:] #1
new_row_idx = row_size - 1 - current_row_idx #2
offeset_from_diag = current_col_idx - new_row_idx #3
current_off_diag = reversed_rows.diagonal(offeset_from_diag)
P_idx= np.where(current_off_diag== P)[0]
is_idx_consecutive = sum(np.diff(P_idx)==1)>=3
if is_idx_consecutive:
return True
return False
def move_at_random(S,P):
selected_col_idx = np.random.permutation(range(col_size))[0]
#print selected_col_idx
#we should fill in matrix from bottom to top. So find the last filled row in col and fill the upper row
last_filled_row = np.where(S[:,selected_col_idx] != 0)[0]
#it is possible that there is no filled array. like the begining of the game
#in this case we start with last row e.g row : -1
if last_filled_row.size != 0:
current_row_idx = last_filled_row[0] - 1
else:
current_row_idx = -1
#print 'col[{0}], row[{1}]'.format(selected_col,current_row)
S[current_row_idx, selected_col_idx] = P
return (S,current_row_idx,selected_col_idx)
def move_still_possible(S):
return not (S[S==0].size == 0)
def print_game_state(S):
B = np.copy(S).astype(object)
for n in [-1, 0, 1]:
B[B==n] = symbols[n]
print B
def play_game():
#initiate game state
game_state = np.zeros((6,7),dtype=int)
player = 1
mvcntr = 1
no_winner_yet = True
while no_winner_yet and move_still_possible(game_state):
#get player symbol
name = symbols[player]
game_state, current_row, current_col = move_at_random(game_state, player)
#print '******',player,(current_row, current_col)
#print current game state
print_game_state(game_state)
#check if the move was a winning move
if was_winning_move(game_state,player,current_row, current_col):
print 'player %s wins after %d moves' % (name, mvcntr)
no_winner_yet = False
# switch player and increase move counter
player *= -1
mvcntr += 1
if no_winner_yet:
print 'game ended in a draw'
player = 0
return game_state,player,mvcntr
if __name__ == '__main__':
S, P, mvcntr = play_game()
let me know if you have any question
UPDATE: Explanation:
At each move, look at column, row, diagonal and secondary diagonal that goes through the current cell and find consecutive cells with the current symbol. avoid scanning the whole board.
extracting cells in each direction:
column:
current_col = S[:,current_col_idx]
row:
current_row = S[current_row_idx,:]
Diagonal:
Find the offset of the desired diagonal from the
main diagonal:
diag_offset = current_col_idx - current_row_idx
current_diag = S.diagonal(offset)
off-diagonal:
Reverse the rows of matrix:
S_reversed_rows = S[::-1,:]
Find the row index in the new matrix
new_row_idx = row_size - 1 - current_row_idx
current_offdiag = S.diagonal(offset)

Categories