Travelling Salesman implementation - python

# def shortest_path(grid: List[List[int]]) -> List[Tuple[int, int]]:
# ROW, COL = len(grid), len(grid[0])
# extra = []
# start, dest = None, None
Expand
message.txt
4 KB
Help me please

```# from typing import List, Tuple
# def shortest_path(grid: List[List[int]]) -> List[Tuple[int, int]]:
# ROW, COL = len(grid), len(grid[0])
# extra = []
# start, dest = None, None
# # find the starting and ending points and the extra
# for row in range(ROW):
# for col in range(COL):
# if grid[row][col] == 3:
# start = (row, col)
# elif grid[row][col] == 4:
# dest = (row, col)
# elif grid[row][col] == 5:
# extra.append((row, col))
# print(extra)
# # add the destination to the end of the list of extra
# extra.append(dest)
# def bfs(curr, dest, extra, path, visited):
# if not extra and curr == dest:
# return path
# for row, col in [(0,1), (0,-1), (1,0), (-1,0)]:
# r, c = curr[0] + row, curr[1] + col
# if (0 <= r < ROW) and (0 <= c < COL) and (grid[r][c] != 0) and ((r,c) not in visited):
# if (r,c) in extra:
# index = extra.index((r,c))
# for i in range(index, len(extra)):
# res = bfs((r,c), extra[i], extra[i+1:], path + [(r,c)], visited + [(r,c)])
# if res:
# # print(res)
# return res
# else:
# res = bfs((r,c), dest, extra, path + [(r,c)], visited + [(r,c)])
# if res:
# # print(res)
# return res
# return []
# return bfs(start, dest, extra, [start], [start])
from typing import List, Tuple
def shortest_path(maze: List[List[int]]) -> List[Tuple[int, int]]:
ROW, COL = len(maze), len(maze[0])
extra = []
start, dest = None, None
for row in range(ROW):
for col in range(COL):
if maze[row][col] == 3:
start = (row, col)
elif maze[row][col] == 4:
dest = (row, col)
elif maze[row][col] == 5:
extra.append((row, col))
print(extra)
def bfs(curr, dest, extra, path, visited):
if not extra and curr == dest:
return path
for row, col in [(0,1), (0,-1), (1,0), (-1,0)]:
r, c = curr[0] + row, curr[1] + col
if (0 <= r < ROW) and (0 <= c < COL) and (maze[r][c] != 0) and ((r,c) not in visited):
if (r,c) in extra:
index = extra.index((r,c))
for i in range(index, len(extra)):
res = bfs((r,c), dest, extra[i+1:], path + [(r,c)], visited + [(r,c)])
if res:
return res
else:
res = bfs((r,c), dest, extra, path + [(r,c)], visited + [(r,c)])
if res:
return res
return None
result = bfs(start, dest, extra, [start], [start])
if result:
return result
else:
return []
GRID = [[0, 0, 0, 5, 0, 0, 1,1 , 1, 1, 1, 0],
[0, 1, 1, 1, 5,5, 1, 1, 1, 0, 4, 0],
[0, 1, 0, 1, 5, 1, 1, 0, 1, 0, 0, 0],
[0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 5, 0],
[0, 1, 1, 1, 1, 1, 5, 1, 1, 0, 1, 0],
[0, 3, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
path = shortest_path(GRID)
print(path)
Hey all, I have a question, given a grid above, with 1 as open path, 0 as closed path, 3 as start, 4 as end, 5 as extra points; how can i code a BFS (or any algorithms better) such that it is able to return me the individual coordinates to take to go from start point to end point, while passing through extra points(5). The code above does not really work, (does not pass through all extra points)

Related

What does the error "TypeError: '>' not supported between instances of 'vectorize' and 'vectorize'" mean?

I am getting this error:
Traceback (most recent call last):
File "main.py", line 95, in <module>
if mPLocX > mPLocY:
TypeError: '>' not supported between instances of 'vectorize' and 'vectorize'
From this program:
import numpy as np
#For the array
import random as ran
#For random starting positions
import math
#To find the difference in position
field = np.array([
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
])
my = ran.randint(0, 5)
#Monster Y
mx = ran.randint(0, 5)
#Monster X
py = ran.randint(0, 5)
#Player Y
px = ran.randint(0, 5)
#Player X
if my != py and mx != my:
field[my, mx] = 1
field[py, px] = 2
else:
my = ran.randint(0, 5)
#Monster Y
mx = ran.randint(0, 5)
#Monster X
py = ran.randint(0, 5)
#Player Y
px = ran.randint(0, 5)
#Player X
field[my, mx] = 1
field[py, px] = 2
mPLocY = 0
#Monster Player Location Y
mPLocX = 0
#Monster Player Location X
turn = 0
for i in range(20):
turn += 1
trueTurn = turn % 2
if trueTurn == 1:
print ("Player's Turn")
else:
print ("Monster's turn")
print("Monster is at:" + str(mx) + ", " + str(my))
print("Player is at " + str(px) + ", " + str(py))
pLoc = np.where(field == 2)
#pLoc = Player Location (declared in loop)
mLoc = np.where(field == 1)
#mLoc = Monster Location (declared in loop)
(my, mx) = mLoc
if turn == 0:
mPLocX = math.fabs(mx - px)
#Monster Player Location X (declared out of loop)
mPLocY = math.fabs(my - py)
#Monster Player Location Y (declared out of loop)
else:
mPLocX = np.vectorize(math.fabs(mx - px))
#Monster Player Location X (declared out of loop)
mPLocY = np.vectorize(math.fabs(my - py))
#Monster Player Location Y (declared out of loop)
if trueTurn == 1:
drctn = input("Input a direction (wasd): ")
#drctn means Direction
if drctn == "w":
field[py, px] = 0
py = py + 1
field[py, px] = 2
elif drctn == "s":
field[py, px] = 0
py = py - 1
field[py, px] = 2
elif drctn == "a":
field[py, px] = 0
px = px - 1
field[py, px] = 2
elif drctn == "d":
field[py, px] = 0
px = px + 1
field[py, px] = 2
else:
print("Error!")
else:
if mPLocX > mPLocY:
if mx > px:
field[my, mx] = 0
mx = mx - 1
field[my, mx] = 2
else:
field[my, mx] = 0
mx = mx + 1
field[my, mx] = 2
else:
if my > py:
field[my, mx] = 0
py = py - 1
field[my, mx] = 2
else:
field[my, mx] = 0
py = py - 1
field[my, mx] = 2
The first time the loop code goes, there are no errors. Come second iteration, mx and my become shapes. The error originates at lines 62–71.
I tried just getting rid of the vectorize, but that doesn't work. I tried using astype on all of the separate variables, but that did not work. It only works with the if/else thing, because on the first loop, they are not shapes.
In your code you wrote
mPLocX = np.vectorize(math.fabs(mx - px))
mPLocY = np.vectorize(math.fabs(my - py))
which makes mPLocX and mPLocY instances of np.vectorize (whether they make sense or not is another topic).
Then you wrote
if mPLocX > mPLocY:
which raises the exception you are seeing, because the > operator is not supported between instances of np.vectorize.
It seems you intended to take the element-wise absolute value of an array that is the element-wise difference between two other arrays (whether mx and px etc. are actually arrays or just single numbers is yet another topic).
NumPy can already do the element-wise calculations out-of-the box. You don't need to use np.vectorize:
>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 4, 1])
>>> a - b
array([-1, -2, 2])
>>> np.abs(a - b)
array([1, 2, 2])

identity test game of life

I'm writing the conway's game code in python. My code is like this:
def update_board(board: list[list[int]]) -> list[list[int]]:
rows = len(board)
cols = len(board[0])
count = 0
copy_board = deepcopy(board)
indx = [-1, -1, -1, 0, 0, 1, 1, 1]
indy = [-1, 0, 1, -1, 1, -1, 0, 1]
for i in range(rows):
for j in range(cols):
for k, value in enumerate(indx):
if check(i + value, j + indy[k], rows,
cols) and copy_board[i + indx[k]][j + indy[k]]:
count += 1
# Apply the rule to each cell
if count < 2 or count > 3:
board[i][j] = 0
elif count == 3:
board[i][j] = 1
# Reset the count for the next cell
count = 0
return board
It need to pass through the identity test:
def test_is_not_identity() -> None:
"""Test board update is not done in place."""
board = [[0 for _ in range(4)] for _ in range(4)]
assert board is not update_board(board)
and the stills test (I don't know what it does):
def test_stills(name: str, proto: str) -> None:
"""Test still lifes."""
board = parse_board(proto)
assert board == update_board(deepcopy(board)), name
but it doesn't pass although I updated the board in place so I don't understand.
You should return the copy_board instead of board. Also moodify copy_booard instead of board itself
def update_board(board: list[list[int]]) -> list[list[int]]:
rows = len(board)
cols = len(board[0])
count = 0
copy_board = deepcopy(board)
indx = [-1, -1, -1, 0, 0, 1, 1, 1]
indy = [-1, 0, 1, -1, 1, -1, 0, 1]
for i in range(rows):
for j in range(cols):
for k, value in enumerate(indx):
if check(i + value, j + indy[k], rows,
cols) and board[i + indx[k]][j + indy[k]]:
count += 1
# Apply the rule to each cell
if count < 2 or count > 3:
copy_board[i][j] = 0
elif count == 3:
copy_board[i][j] = 1
# Reset the count for the next cell
count = 0
return copy_board

N-puzzle problem using A-star search algorithm

I am making a n-puzzle solver for my Artificial Intelligence class using A* in Python. The problem I have with my solution is , that the solve_puzzle() is not working as it should. While searching through the nodes it gets just deeper and deeper, but it never ends, the depth goes into really high numbers (depth of some child node is 5k for example).
I think it gets stuck in some loop and it keeps just looping through the same nodes (That is just what I think, I am not sure about that). I don't really know, I tried 3 different A* solutions, but the result is the same - the search loop never ends and never reaches the Goal.
I can solve very primitive puzzle like
start -> 0, 1, 2, 3, 4, 5, 6, 7, 8 goal -> 1, 2, 0, 3, 4, 5, 6, 7, 8 (just two moves to left are made)
but for just a little more complex puzzle like
start = 0, 1, 2, 3, 4, 5, 6, 7, 8
goal = 1, 2, 5, 0, 3, 4, 6, 7, 8 it is a never ending search.
I move the tile with number, not the blank tile.
Below is the whole code:
'''
class Node():
def __init__(self, n_size, m_size, current_state, goal_state, choosen_heuristic, parent):
self.n_size = n_size
self.m_size = m_size
self.dimension = self.n_size * self.m_size
self.current_state = current_state
self.goal_state = goal_state
self.choosen_heuristic = choosen_heuristic
self.parent = parent
self.child = [None, None, None, None]
self.last_operator = None
self.heuristic_cost = 0
self.depth = 0
self.priority = self.depth + self.heuristic_cost
def check_if_goal_is_reached(self):
if (self.heuristic_cost == 0):
print("GOAL IS REACHED!")
exit(1) #for now
#return
def get_blank_tile_position(self):
blank_position = 0
for i in range(self.dimension):
if (self.current_state[i] == 0):
blank_position = i
return blank_position
def misplaced_tiles_heuristic(self):
misplaced_sum = 0
for i in range(self.dimension):
if self.current_state[i] != self.goal_state[i]:
misplaced_sum += 1
#print("Count of misplaced tiless in this node is : ", misplaced_sum)
self.heuristic_cost = "misplaced"
self.heuristic_cost = misplaced_sum
self.check_if_goal_is_reached()
return misplaced_sum
def manhattan_distance(self):
distance_sum = 0
for i in range(self.dimension):
current_x = self.current_state[i] % self.n_size
goal_x = self.goal_state[i] % self.n_size
current_y = self.current_state[i] // self.m_size
goal_y = self.goal_state[i] // self.m_size
distance_sum += abs(current_x - goal_x) + abs(current_y - goal_y)
#print("Sum of Manhattan distance for this node is : ", distance_sum)
self.heuristic_cost = "manhattan"
#print("Hĺbka tohto uzla : ", self.depth)
self.check_if_goal_is_reached()
return distance_sum
def generate_children(self, choosen_heuristic):
possible_directions = []
current_node_blank_position = self.get_blank_tile_position()
# UP - I move a tile with number on it, not the blank tile
if current_node_blank_position < (self.dimension - self.n_size):
self.child[0] = Node(self.n_size, self.m_size, self.current_state, self.goal_state, self.choosen_heuristic, self.current_state)
self.child[0] = copy.deepcopy(self)
self.child[0].parent = self.current_state
self.child[0].last_operator = "UP"
self.child[0].depth = self.depth + 1
new_blank_position = current_node_blank_position + self.m_size
temp = self.child[0].current_state[current_node_blank_position]
self.child[0].current_state[current_node_blank_position] = self.child[0].current_state[new_blank_position]
self.child[0].current_state[new_blank_position] = temp
if choosen_heuristic == "misplaced":
self.child[0].misplaced_tiles_heuristic()
if choosen_heuristic == "manhattan":
self.child[0].manhattan_distance()
possible_directions.append("UP")
print("Depth of this node is : : ", self.child[0].depth)
else:
self.child[0] = None
# DOWN - I move a tile with number on it, not the blank tile
if current_node_blank_position > (self.n_size - 1):
self.child[1] = Node(self.n_size, self.m_size, self.current_state, self.goal_state, self.choosen_heuristic, self.current_state)
self.child[1] = copy.deepcopy(self)
self.child[1].parent = self.current_state
self.child[1].last_operator = "DOWN"
self.child[1].depth = self.depth + 1
new_blank_position = current_node_blank_position - self.m_size
temp = self.child[1].current_state[current_node_blank_position]
self.child[1].current_state[current_node_blank_position] = self.child[1].current_state[new_blank_position]
self.child[1].current_state[new_blank_position] = temp
if choosen_heuristic == "misplaced":
self.child[1].misplaced_tiles_heuristic()
if choosen_heuristic == "manhattan":
self.child[1].manhattan_distance()
possible_directions.append("DOWN")
#print("Depth of this node is : : ", self.child[1].depth)
else:
self.child[1] = None
# RIGHT - I move a tile with number on it, not the blank tile
if (current_node_blank_position + self.n_size) % self.m_size:
self.child[2] = Node(self.n_size, self.m_size, self.current_state, self.goal_state, self.choosen_heuristic, self.current_state)
self.child[2] = copy.deepcopy(self)
self.child[2].parent = self.current_state
self.child[2].last_operator = "RIGHT"
self.child[2].depth = self.depth + 1
new_blank_position = current_node_blank_position - 1
temp = self.child[2].current_state[current_node_blank_position]
self.child[2].current_state[current_node_blank_position] = self.child[2].current_state[new_blank_position]
self.child[2].current_state[new_blank_position] = temp
if choosen_heuristic == "misplaced":
self.child[2].misplaced_tiles_heuristic()
if choosen_heuristic == "manhattan":
self.child[2].manhattan_distance()
possible_directions.append("RIGHT")
#print("Depth of this node is : : ", self.child[2].depth)
else:
self.child[2] = None
# LEFT - I move a tile with number on it, not the blank tile
if (current_node_blank_position + 1) % self.m_size:
self.child[3] = Node(self.n_size, self.m_size, self.current_state, self.goal_state, self.choosen_heuristic, self.current_state)
self.child[3] = copy.deepcopy(self)
self.child[3].parent = self.current_state
self.child[3].last_operator = "LEFT"
self.child[3].depth = self.depth + 1
new_blank_position = current_node_blank_position + 1
temp = self.child[3].current_state[current_node_blank_position]
self.child[3].current_state[current_node_blank_position] = self.child[3].current_state[new_blank_position]
self.child[3].current_state[new_blank_position] = temp
if choosen_heuristic == "misplaced":
self.child[3].misplaced_tiles_heuristic()
if choosen_heuristic == "manhattan":
self.child[3].manhattan_distance()
possible_directions.append("LEFT")
#print("Depth of this node is : ", self.child[3].depth)
else:
self.child[3] = None
#print("From this node (the parent node) I can move to -> ", possible_directions)
def get_node_priority(node):
return node.priority
def solve_puzzle(n_size, m_size, current_state, goal_state, choosen_heuristic):
open_list = []
closed_list = []
init_node_parent = None
init_node = Node(n_size, m_size, current_state, goal_state, choosen_heuristic, init_node_parent)
open_list.append(init_node)
while len(open_list) != 0:
if (len(open_list) == 0):
print("Fail - solution not found !")
else:
node = open_list.pop(0)
if (node.parent != None):
node.check_if_goal_is_reached()
node.generate_children(choosen_heuristic)
closed_list.append(node)
temp_list = []
for i in range(4):
if node.child[i] != None:
temp_list.insert(0, node.child[i])
sorted_temp_list = sorted(temp_list, key=get_node_priority, reverse=True)
for x in range(len(sorted_temp_list)):
if sorted_temp_list[x] != None:
open_list.insert(0, sorted_temp_list[x])
def print_current_node(current_node):
puzzle = ""
if current_node is None:
puzzle = ""
print(puzzle)
else:
puzzle = ""
count_lines = 0
for i in range(current_node.dimension):
puzzle += (str(current_node.current_state[i]) + " ")
count_lines += 1
if (count_lines % current_node.m_size == 0):
puzzle += "\n"
print(puzzle)
def main():
###################
# Static Data #
###################
# static for now, later I will let user to choose
n_size = 3
m_size = 3
current_state = [0, 1, 2, 3, 4, 5, 6, 7, 8]
goal_state = [8, 0, 6, 5, 4, 7, 2, 3, 1]
choosen_heuristic = "manhattan"
start_time = time.process_time()
solve_puzzle(n_size, m_size, current_state, goal_state, choosen_heuristic)
end_time = time.process_time()
search_time = end_time - start_time
print("Solved in : ", search_time, "seconds.")
main()
'''
Make sure you test with a solvable puzzle.
Here are some solvable tests:
goal: {1,2,3,4,5,6,7,8,0}
6 steps: {1,3,5,4,0,2,7,8,6}
18 steps: {1,4,0,5,2,8,7,6,3}
26 steps: {2,1,7,5,0,8,3,4,6}
27 steps: {8,5,3,4,7,0,6,1,2}
28 steps: {0,6,7,3,8,5,4,2,1}
30 steps: {5,7,0,4,6,8,1,2,3}
31 steps: {8,6,7,2,5,4,3,0,1} (highest number of steps possible for 3x3 )

graph theory DFS get the path from start to end node

i need only a one path from source to destination node,to return from this function, but this function doesn't stop after the path is discovered.
i only used return when the end node is found.
how can i end this when the path is found.
my situation only have one path , and no loops
one node have maximum 4 child nodes
def dfs(gpdic,start,end,visited,path):
visited[start] = 1
path.append(start)
print(f"start node {start}")
if start == end:
print(f"this is the path {path}")
return path
else:
print(f"stack {path}")
for node in gpdic[start]:
print(f" in node - {node}")
if visited[node]== -1 and node != -1 and node != 0 :
print(f" calling for next recursive funtion {node} ")
dfs(gpdic,node,end,visited,path)
#return path
po = path.pop()
print(f" poped last {po}")
visited[start] = -1
if __name__ == '__main__':
gp = {1: [2, -1, -1, -1], 2: [3, 4, 1, 5], 3: [6, -1, 2, 7],
4:[-1, -1, -1, 2], 5: [-1, 2, -1, -1], 6: [-1, -1, 3, -1],
7[-1, 3, -1, -1]}
visited = [-1] * 12
path = []
pathret = dfs(gp,7,4,visited,path)
print(f"finale path - > {pathret}")
problem solved just need to get the return variable from function and compare it
def dfs(gpdic,start,end,visited,path):
visited[start] = 1
path.append(start)
print(f"start node {start}")
if start == end:
print(f"this is the path {path}")
return path
else:
print(f"stack {path}")
for node in gpdic[start]:
print(f" in node - {node}")
if visited[node]== -1 and node != -1 and node != 0 :
print(f" calling for next recursive funtion {node} ")
l = dfs(gpdic,node,end,visited,path)
if l is not None:
return path
po = path.pop()
print(f" poped last {po}")
visited[start] = -1
if __name__ == '__main__':
gp = {1: [2, -1, -1, -1], 2: [3, 4, 1, 5], 3: [6, -1, 2, 7],
4:[-1, -1, -1, 2], 5: [-1, 2, -1, -1], 6: [-1, -1, 3, -1],
7[-1, 3, -1, -1]}
visited = [-1] * 12
path = []
pathret = dfs(gp,7,4,visited,path)
print(f"finale path - > {pathret}")

Python TicTacToe minimax choses wrong option

I'm currently trying to implement an AI for my Python TicTacToe game.
Everything performs greatly, apart from one single situation.
My current code:
def testLine(line):
'''
' :param line: Liste containing 3 ints
' :return: 1, if all elements of the list == 1
' -1, if all elements of the list == -1
' 0, otherwise
'''
if line[0] == 1 and line[1] == 1 and line[2] == 1:
return 1
elif line[0] == -1 and line[1] == -1 and line[2] == -1:
return -1
return 0
def getWinner(board):
# test columns
for idx in range(3):
line = [board[0][idx], board[1][idx], board[2][idx]]
if not testLine(line) == 0:
return line[0]
# test rows
for idx in range(3):
line = board[idx]
if not testLine(line) == 0:
return line[0]
# test diagonals
line = [board[0][0], board[1][1], board[2][2]]
if not testLine(line) == 0:
return line[0]
line = [board[0][2], board[1][1], board[2][0]]
if not testLine(line) == 0:
return line[0]
# no winner
return 0
def count(board, obj):
c = 0
for r in range(len(board)):
for col in range(len(board[r])): # FIXED IT
if board[r][col] == obj:
c += 1
return c
def nextMove(board, player):
if len(board[0]) + len(board[1]) + len(board[2]) == 1: return 0, 4
nextPlayer = player * (-1)
if not getWinner(board) == 0:
if player is 1: return -1, (-1, -1)
else: return 1, (-1, -1)
listOfResults = [] # empty array
if count(board, 0) == 0: # there is no empty field
return 0, (-1, -1)
_list = []
for i in range(len(board)):
for j in range(len(board[i])):
if board[i][j] == 0:
_list.append((i, j))
for (i, j) in _list:
board[i][j] = player
ret, move = nextMove(board, nextPlayer)
listOfResults.append(ret)
board[i][j] = 0
if player is 1:
maxPossibleValue = max(listOfResults)
return maxPossibleValue, _list[listOfResults.index(maxPossibleValue)]
else:
minPossibleValue = min(listOfResults)
return minPossibleValue, _list[listOfResults.index(minPossibleValue)]
if __name__ == '__main__':
print(str(nextMove([[ 1, -1, 0],
[ -1, -1, 1],
[ 1, 1, 0]],
-1)))
Output: (0, (0, 2))
I can say for sure that count, getWinner and testLine work perfectly.
But the output of the scenario at the very bottom of the code is simply wrong, as it should be (0, 2, 2) because the computer has to "block" my chance to win in the bottom line.
Do you have suggestions on how to fix my minimax algorithm?
EDIT: I've fixed it. The error was in the count method. You shouldn't say
for col in board[r]
but
for col in range(len(board[r]))
Because otherwise it won't keep the elements in the right order and the whole method returned a false value.
I've fixed it. The error was in the count method. You shouldn't say
for col in board[r]
but
for col in range( len(board[r]) )
Because otherwise it won't keep the elements in the right order and the whole method returned a false value.
The first thing you need to know is that return a, b is similar to return (a,b), because defining a tuple does not need parenthesis (exept for an empty tuple).
So you can easily return (0, 0, 2) instead of (0, (0, 2)) :
return (maxPossibleValue,) + _list[listOfResults.index(maxPossibleValue)]
# use (a,) for a tuple of len 1
But I'm aware this solves only the half of your problem.

Categories