[workshop] Add notebook
This commit is contained in:
1592
Workshop - 1 (Random, BFS, DFS, DP).ipynb
Normal file
1592
Workshop - 1 (Random, BFS, DFS, DP).ipynb
Normal file
File diff suppressed because one or more lines are too long
1420
Workshop - 2 (UCS, A, Hill-Climbing).ipynb
Normal file
1420
Workshop - 2 (UCS, A, Hill-Climbing).ipynb
Normal file
File diff suppressed because one or more lines are too long
122
Workshop - 3 (Game).ipynb
Normal file
122
Workshop - 3 (Game).ipynb
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Create a terminal here"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<img src=\"images/terminal.png\">"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Change working directory"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"```bash\n",
|
||||||
|
"$ cd Workshop\\ -\\ 3\\ \\(Game\\)/\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<img src=\"images/pwd.png\">"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Run the game"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"```bash\n",
|
||||||
|
"$ python3 minimax.py\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<img src=\"images/minimax.png\">"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"```bash\n",
|
||||||
|
"$ python3 ab-pruning.py\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<img src=\"images/ab-pruning.png\">"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Reading Materials"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"https://stackabuse.com/minimax-and-alpha-beta-pruning-in-python/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
191
Workshop - 3 (Game)/ab-pruning.py
Normal file
191
Workshop - 3 (Game)/ab-pruning.py
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
# We'll use the time module to measure the time of evaluating
|
||||||
|
# game tree in every move. It's a nice way to show the
|
||||||
|
# distinction between the basic Minimax and Minimax with
|
||||||
|
# alpha-beta pruning :)
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self):
|
||||||
|
self.initialize_game()
|
||||||
|
|
||||||
|
def initialize_game(self):
|
||||||
|
self.current_state = [['.','.','.'],
|
||||||
|
['.','.','.'],
|
||||||
|
['.','.','.']]
|
||||||
|
|
||||||
|
# Player X always plays first
|
||||||
|
self.player_turn = 'X'
|
||||||
|
|
||||||
|
def draw_board(self):
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
print('{}|'.format(self.current_state[i][j]), end=" ")
|
||||||
|
print()
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Determines if the made move is a legal move
|
||||||
|
def is_valid(self, px, py):
|
||||||
|
if px < 0 or px > 2 or py < 0 or py > 2:
|
||||||
|
return False
|
||||||
|
elif self.current_state[px][py] != '.':
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Checks if the game has ended and returns the winner in each case
|
||||||
|
def is_end(self):
|
||||||
|
# Vertical win
|
||||||
|
for i in range(0, 3):
|
||||||
|
if (self.current_state[0][i] != '.' and
|
||||||
|
self.current_state[0][i] == self.current_state[1][i] and
|
||||||
|
self.current_state[1][i] == self.current_state[2][i]):
|
||||||
|
return self.current_state[0][i]
|
||||||
|
|
||||||
|
# Horizontal win
|
||||||
|
for i in range(0, 3):
|
||||||
|
if (self.current_state[i] == ['X', 'X', 'X']):
|
||||||
|
return 'X'
|
||||||
|
elif (self.current_state[i] == ['O', 'O', 'O']):
|
||||||
|
return 'O'
|
||||||
|
|
||||||
|
# Main diagonal win
|
||||||
|
if (self.current_state[0][0] != '.' and
|
||||||
|
self.current_state[0][0] == self.current_state[1][1] and
|
||||||
|
self.current_state[0][0] == self.current_state[2][2]):
|
||||||
|
return self.current_state[0][0]
|
||||||
|
|
||||||
|
# Second diagonal win
|
||||||
|
if (self.current_state[0][2] != '.' and
|
||||||
|
self.current_state[0][2] == self.current_state[1][1] and
|
||||||
|
self.current_state[0][2] == self.current_state[2][0]):
|
||||||
|
return self.current_state[0][2]
|
||||||
|
|
||||||
|
# Is whole board full?
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
# There's an empty field, we continue the game
|
||||||
|
if (self.current_state[i][j] == '.'):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# It's a tie!
|
||||||
|
return '.'
|
||||||
|
|
||||||
|
def max_alpha_beta(self, alpha, beta):
|
||||||
|
maxv = -2
|
||||||
|
px = None
|
||||||
|
py = None
|
||||||
|
|
||||||
|
result = self.is_end()
|
||||||
|
|
||||||
|
if result == 'X':
|
||||||
|
return (-1, 0, 0)
|
||||||
|
elif result == 'O':
|
||||||
|
return (1, 0, 0)
|
||||||
|
elif result == '.':
|
||||||
|
return (0, 0, 0)
|
||||||
|
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
if self.current_state[i][j] == '.':
|
||||||
|
self.current_state[i][j] = 'O'
|
||||||
|
(m, min_i, in_j) = self.min_alpha_beta(alpha, beta)
|
||||||
|
if m > maxv:
|
||||||
|
maxv = m
|
||||||
|
px = i
|
||||||
|
py = j
|
||||||
|
self.current_state[i][j] = '.'
|
||||||
|
|
||||||
|
# Next two ifs in Max and Min are the only difference between regular algorithm and minimax
|
||||||
|
if maxv >= beta:
|
||||||
|
return (maxv, px, py)
|
||||||
|
|
||||||
|
if maxv > alpha:
|
||||||
|
alpha = maxv
|
||||||
|
|
||||||
|
return (maxv, px, py)
|
||||||
|
|
||||||
|
def min_alpha_beta(self, alpha, beta):
|
||||||
|
|
||||||
|
minv = 2
|
||||||
|
|
||||||
|
qx = None
|
||||||
|
qy = None
|
||||||
|
|
||||||
|
result = self.is_end()
|
||||||
|
|
||||||
|
if result == 'X':
|
||||||
|
return (-1, 0, 0)
|
||||||
|
elif result == 'O':
|
||||||
|
return (1, 0, 0)
|
||||||
|
elif result == '.':
|
||||||
|
return (0, 0, 0)
|
||||||
|
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
if self.current_state[i][j] == '.':
|
||||||
|
self.current_state[i][j] = 'X'
|
||||||
|
(m, max_i, max_j) = self.max_alpha_beta(alpha, beta)
|
||||||
|
if m < minv:
|
||||||
|
minv = m
|
||||||
|
qx = i
|
||||||
|
qy = j
|
||||||
|
self.current_state[i][j] = '.'
|
||||||
|
|
||||||
|
if minv <= alpha:
|
||||||
|
return (minv, qx, qy)
|
||||||
|
|
||||||
|
if minv < beta:
|
||||||
|
beta = minv
|
||||||
|
|
||||||
|
return (minv, qx, qy)
|
||||||
|
|
||||||
|
def play_alpha_beta(self):
|
||||||
|
while True:
|
||||||
|
self.draw_board()
|
||||||
|
self.result = self.is_end()
|
||||||
|
|
||||||
|
if self.result != None:
|
||||||
|
if self.result == 'X':
|
||||||
|
print('The winner is X!')
|
||||||
|
elif self.result == 'O':
|
||||||
|
print('The winner is O!')
|
||||||
|
elif self.result == '.':
|
||||||
|
print("It's a tie!")
|
||||||
|
|
||||||
|
|
||||||
|
self.initialize_game()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.player_turn == 'X':
|
||||||
|
|
||||||
|
while True:
|
||||||
|
start = time.time()
|
||||||
|
(m, qx, qy) = self.min_alpha_beta(-2, 2)
|
||||||
|
end = time.time()
|
||||||
|
print('Evaluation time: {}s'.format(round(end - start, 7)))
|
||||||
|
print('Recommended move: X = {}, Y = {}'.format(qx, qy))
|
||||||
|
|
||||||
|
px = int(input('Insert the X coordinate: '))
|
||||||
|
py = int(input('Insert the Y coordinate: '))
|
||||||
|
|
||||||
|
qx = px
|
||||||
|
qy = py
|
||||||
|
|
||||||
|
if self.is_valid(px, py):
|
||||||
|
self.current_state[px][py] = 'X'
|
||||||
|
self.player_turn = 'O'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print('The move is not valid! Try again.')
|
||||||
|
|
||||||
|
else:
|
||||||
|
(m, px, py) = self.max_alpha_beta(-2, 2)
|
||||||
|
self.current_state[px][py] = 'O'
|
||||||
|
self.player_turn = 'X'
|
||||||
|
|
||||||
|
def main():
|
||||||
|
g = Game()
|
||||||
|
g.play_alpha_beta()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
204
Workshop - 3 (Game)/minimax.py
Normal file
204
Workshop - 3 (Game)/minimax.py
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
# We'll use the time module to measure the time of evaluating
|
||||||
|
# game tree in every move. It's a nice way to show the
|
||||||
|
# distinction between the basic Minimax and Minimax with
|
||||||
|
# alpha-beta pruning :)
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self):
|
||||||
|
self.initialize_game()
|
||||||
|
|
||||||
|
def initialize_game(self):
|
||||||
|
self.current_state = [['.','.','.'],
|
||||||
|
['.','.','.'],
|
||||||
|
['.','.','.']]
|
||||||
|
|
||||||
|
# Player X always plays first
|
||||||
|
self.player_turn = 'X'
|
||||||
|
|
||||||
|
def draw_board(self):
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
print('{}|'.format(self.current_state[i][j]), end=" ")
|
||||||
|
print()
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Determines if the made move is a legal move
|
||||||
|
def is_valid(self, px, py):
|
||||||
|
if px < 0 or px > 2 or py < 0 or py > 2:
|
||||||
|
return False
|
||||||
|
elif self.current_state[px][py] != '.':
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Checks if the game has ended and returns the winner in each case
|
||||||
|
def is_end(self):
|
||||||
|
# Vertical win
|
||||||
|
for i in range(0, 3):
|
||||||
|
if (self.current_state[0][i] != '.' and
|
||||||
|
self.current_state[0][i] == self.current_state[1][i] and
|
||||||
|
self.current_state[1][i] == self.current_state[2][i]):
|
||||||
|
return self.current_state[0][i]
|
||||||
|
|
||||||
|
# Horizontal win
|
||||||
|
for i in range(0, 3):
|
||||||
|
if (self.current_state[i] == ['X', 'X', 'X']):
|
||||||
|
return 'X'
|
||||||
|
elif (self.current_state[i] == ['O', 'O', 'O']):
|
||||||
|
return 'O'
|
||||||
|
|
||||||
|
# Main diagonal win
|
||||||
|
if (self.current_state[0][0] != '.' and
|
||||||
|
self.current_state[0][0] == self.current_state[1][1] and
|
||||||
|
self.current_state[0][0] == self.current_state[2][2]):
|
||||||
|
return self.current_state[0][0]
|
||||||
|
|
||||||
|
# Second diagonal win
|
||||||
|
if (self.current_state[0][2] != '.' and
|
||||||
|
self.current_state[0][2] == self.current_state[1][1] and
|
||||||
|
self.current_state[0][2] == self.current_state[2][0]):
|
||||||
|
return self.current_state[0][2]
|
||||||
|
|
||||||
|
# Is whole board full?
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
# There's an empty field, we continue the game
|
||||||
|
if (self.current_state[i][j] == '.'):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# It's a tie!
|
||||||
|
return '.'
|
||||||
|
|
||||||
|
# Player 'O' is max, in this case AI
|
||||||
|
def max(self):
|
||||||
|
|
||||||
|
# Possible values for maxv are:
|
||||||
|
# -1 - loss
|
||||||
|
# 0 - a tie
|
||||||
|
# 1 - win
|
||||||
|
|
||||||
|
# We're initially setting it to -2 as worse than the worst case:
|
||||||
|
maxv = -2
|
||||||
|
|
||||||
|
px = None
|
||||||
|
py = None
|
||||||
|
|
||||||
|
result = self.is_end()
|
||||||
|
|
||||||
|
# If the game came to an end, the function needs to return
|
||||||
|
# the evaluation function of the end. That can be:
|
||||||
|
# -1 - loss
|
||||||
|
# 0 - a tie
|
||||||
|
# 1 - win
|
||||||
|
if result == 'X':
|
||||||
|
return (-1, 0, 0)
|
||||||
|
elif result == 'O':
|
||||||
|
return (1, 0, 0)
|
||||||
|
elif result == '.':
|
||||||
|
return (0, 0, 0)
|
||||||
|
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
if self.current_state[i][j] == '.':
|
||||||
|
# On the empty field player 'O' makes a move and calls Min
|
||||||
|
# That's one branch of the game tree.
|
||||||
|
self.current_state[i][j] = 'O'
|
||||||
|
(m, min_i, min_j) = self.min()
|
||||||
|
# Fixing the maxv value if needed
|
||||||
|
if m > maxv:
|
||||||
|
maxv = m
|
||||||
|
px = i
|
||||||
|
py = j
|
||||||
|
# Setting back the field to empty
|
||||||
|
self.current_state[i][j] = '.'
|
||||||
|
return (maxv, px, py)
|
||||||
|
|
||||||
|
# Player 'X' is min, in this case human
|
||||||
|
def min(self):
|
||||||
|
|
||||||
|
# Possible values for minv are:
|
||||||
|
# -1 - win
|
||||||
|
# 0 - a tie
|
||||||
|
# 1 - loss
|
||||||
|
|
||||||
|
# We're initially setting it to 2 as worse than the worst case:
|
||||||
|
minv = 2
|
||||||
|
|
||||||
|
qx = None
|
||||||
|
qy = None
|
||||||
|
|
||||||
|
result = self.is_end()
|
||||||
|
|
||||||
|
if result == 'X':
|
||||||
|
return (-1, 0, 0)
|
||||||
|
elif result == 'O':
|
||||||
|
return (1, 0, 0)
|
||||||
|
elif result == '.':
|
||||||
|
return (0, 0, 0)
|
||||||
|
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
if self.current_state[i][j] == '.':
|
||||||
|
self.current_state[i][j] = 'X'
|
||||||
|
(m, max_i, max_j) = self.max()
|
||||||
|
if m < minv:
|
||||||
|
minv = m
|
||||||
|
qx = i
|
||||||
|
qy = j
|
||||||
|
self.current_state[i][j] = '.'
|
||||||
|
|
||||||
|
return (minv, qx, qy)
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
while True:
|
||||||
|
self.draw_board()
|
||||||
|
self.result = self.is_end()
|
||||||
|
|
||||||
|
# Printing the appropriate message if the game has ended
|
||||||
|
if self.result != None:
|
||||||
|
if self.result == 'X':
|
||||||
|
print('The winner is X!')
|
||||||
|
elif self.result == 'O':
|
||||||
|
print('The winner is O!')
|
||||||
|
elif self.result == '.':
|
||||||
|
print("It's a tie!")
|
||||||
|
|
||||||
|
self.initialize_game()
|
||||||
|
return
|
||||||
|
|
||||||
|
# If it's player's turn
|
||||||
|
if self.player_turn == 'X':
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
start = time.time()
|
||||||
|
(m, qx, qy) = self.min()
|
||||||
|
end = time.time()
|
||||||
|
print('Evaluation time: {}s'.format(round(end - start, 7)))
|
||||||
|
print('Recommended move: X = {}, Y = {}'.format(qx, qy))
|
||||||
|
|
||||||
|
px = int(input('Insert the X coordinate: '))
|
||||||
|
py = int(input('Insert the Y coordinate: '))
|
||||||
|
|
||||||
|
(qx, qy) = (px, py)
|
||||||
|
|
||||||
|
if self.is_valid(px, py):
|
||||||
|
self.current_state[px][py] = 'X'
|
||||||
|
self.player_turn = 'O'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print('The move is not valid! Try again.')
|
||||||
|
|
||||||
|
# If it's AI's turn
|
||||||
|
else:
|
||||||
|
(m, px, py) = self.max()
|
||||||
|
self.current_state[px][py] = 'O'
|
||||||
|
self.player_turn = 'X'
|
||||||
|
|
||||||
|
def main():
|
||||||
|
g = Game()
|
||||||
|
g.play()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
252
Workshop - 3 (LP).ipynb
Normal file
252
Workshop - 3 (LP).ipynb
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Make sure you run this at the begining**"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import numpy as np\n",
|
||||||
|
"np.set_printoptions(suppress=True)\n",
|
||||||
|
"from scipy.optimize import linprog"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Feasible Example"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"\\begin{align}\n",
|
||||||
|
"\\max f=4x_1+x_2 \\\\\n",
|
||||||
|
"\\text{s.t.} -x_1 + 2x_2 &\\leq 4 \\\\\n",
|
||||||
|
"2x_1 + 3x_2 &\\leq 12 \\\\\n",
|
||||||
|
"x_1 - x_2 &\\leq 3 \\\\\n",
|
||||||
|
"\\text{and } x_1, x_2 \\geq 0\n",
|
||||||
|
"\\end{align}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"c = [-4, -1, 0, 0, 0]\n",
|
||||||
|
"A = [[-1, 2, 0, 0, 0], [2, 3, 0, 0, 0], [1, -1, 0, 0, 0]]\n",
|
||||||
|
"b = [4, 12, 3]\n",
|
||||||
|
"\n",
|
||||||
|
"x0_bounds = (0, None)\n",
|
||||||
|
"x1_bounds = (0, None)\n",
|
||||||
|
"x2_bounds = (None, None)\n",
|
||||||
|
"x3_bounds = (None, None)\n",
|
||||||
|
"x4_bounds = (None, None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {
|
||||||
|
"scrolled": true
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" con: array([], dtype=float64)\n",
|
||||||
|
" fun: -17.999999976555795\n",
|
||||||
|
" message: 'Optimization terminated successfully.'\n",
|
||||||
|
" nit: 4\n",
|
||||||
|
" slack: array([5.8 , 0.00000002, 0. ])\n",
|
||||||
|
" status: 0\n",
|
||||||
|
" success: True\n",
|
||||||
|
" x: array([4.19999999, 1.2 , 0. , 0. , 0. ])\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds, x2_bounds, x3_bounds, x4_bounds])\n",
|
||||||
|
"\n",
|
||||||
|
"print(res)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Infeasible Example"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"\\begin{align}\n",
|
||||||
|
"\\min f = x_1 - 2x_2 + 3x_3 \\\\\n",
|
||||||
|
"s.t. -2x_1 + x_2 + 3x_3 & = 2 \\\\\n",
|
||||||
|
"3x_1 + 3x_2 + 4x_3 & = 1 \\\\\n",
|
||||||
|
"\\end{align}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"c = [-1, 2, -3]\n",
|
||||||
|
"A = [[-2, 1, 3], [3, 3, 4]]\n",
|
||||||
|
"b = [2, 1]\n",
|
||||||
|
"\n",
|
||||||
|
"x0_bounds = (0, None)\n",
|
||||||
|
"x1_bounds = (0, None)\n",
|
||||||
|
"x2_bounds = (0, None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {
|
||||||
|
"scrolled": false
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" con: array([ 0. , -4.56053464])\n",
|
||||||
|
" fun: -0.6099904044751114\n",
|
||||||
|
" message: 'The algorithm terminated successfully and determined that the problem is infeasible.'\n",
|
||||||
|
" nit: 4\n",
|
||||||
|
" slack: array([], dtype=float64)\n",
|
||||||
|
" status: 2\n",
|
||||||
|
" success: False\n",
|
||||||
|
" x: array([0.2893146 , 0.75265113, 0.60865936])\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"res = linprog(c, A_eq=A, b_eq=b, bounds=[x0_bounds, x1_bounds, x2_bounds,])\n",
|
||||||
|
"\n",
|
||||||
|
"print(res)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<h1><font color='red'>Assignment</font></h1>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"\\begin{align}\n",
|
||||||
|
"\\min f = 3x_1 - x_2 \\\\\n",
|
||||||
|
"s.t. 2x_1 + x_2 & \\geq 2 \\\\\n",
|
||||||
|
"x_1 + 3x_2 & \\leq 3 \\\\\n",
|
||||||
|
"x_2 & \\leq 4 \\\\\n",
|
||||||
|
"\\text{and } x_1, x_2 \\geq 0\n",
|
||||||
|
"\\end{align}"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"c = [-3, 1]\n",
|
||||||
|
"A = [[-2, -1], [1, 3], [0, 1]]\n",
|
||||||
|
"b = [-2, 3, 4]\n",
|
||||||
|
"\n",
|
||||||
|
"x0_bounds = (0, None)\n",
|
||||||
|
"x1_bounds = (0, None)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {
|
||||||
|
"scrolled": true
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" con: array([], dtype=float64)\n",
|
||||||
|
" fun: -8.999999998556428\n",
|
||||||
|
" message: 'Optimization terminated successfully.'\n",
|
||||||
|
" nit: 4\n",
|
||||||
|
" slack: array([4., 0., 4.])\n",
|
||||||
|
" status: 0\n",
|
||||||
|
" success: True\n",
|
||||||
|
" x: array([3., 0.])\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds])\n",
|
||||||
|
"\n",
|
||||||
|
"print(res)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.8.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
1026
Workshop - 4 (TSP SA).ipynb
Normal file
1026
Workshop - 4 (TSP SA).ipynb
Normal file
File diff suppressed because one or more lines are too long
1022
Workshop - 5 (ACO, PSO).ipynb
Normal file
1022
Workshop - 5 (ACO, PSO).ipynb
Normal file
File diff suppressed because one or more lines are too long
2278
Workshop - 5 (PSO, ACO).ipynb
Normal file
2278
Workshop - 5 (PSO, ACO).ipynb
Normal file
File diff suppressed because it is too large
Load Diff
1317
Workshop - 6 (GA, SOM).ipynb
Normal file
1317
Workshop - 6 (GA, SOM).ipynb
Normal file
File diff suppressed because one or more lines are too long
BIN
images/ab-pruning.png
Normal file
BIN
images/ab-pruning.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
images/minimax.png
Normal file
BIN
images/minimax.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
BIN
images/pwd.png
Normal file
BIN
images/pwd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
images/solutions.png
Normal file
BIN
images/solutions.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
images/terminal.png
Normal file
BIN
images/terminal.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
BIN
images/tsp.jpg
Normal file
BIN
images/tsp.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
0
.gitignore → template/.gitignore
vendored
0
.gitignore → template/.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
## Build Image
|
||||||
|
|
||||||
|
docker build -t com2014-tsp .
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
@@ -35,13 +35,13 @@ def TSP(tsp_file, model):
|
|||||||
coords = load_data(tsp_file)
|
coords = load_data(tsp_file)
|
||||||
|
|
||||||
# Set timeout
|
# Set timeout
|
||||||
signal.signal(signal.SIGALRM, timeout_handler)
|
# signal.signal(signal.SIGALRM, timeout_handler)
|
||||||
signal.alarm(60)
|
# signal.alarm(60)
|
||||||
|
|
||||||
# Try your algorithm
|
# Try your algorithm
|
||||||
try:
|
try:
|
||||||
model.init(coords)
|
model.init(coords)
|
||||||
best_solution, fitness_list = model.fit(max_it=100000)
|
best_solution, fitness_list = model.fit(max_it=10000)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
if(str(exc) == "Timeout"):
|
if(str(exc) == "Timeout"):
|
||||||
log("Timeout -3")
|
log("Timeout -3")
|
||||||
@@ -72,7 +72,7 @@ class SimAnneal(Model):
|
|||||||
self.log("Starting annealing.")
|
self.log("Starting annealing.")
|
||||||
while self.T >= self.stopping_temperature and self.iteration < max_it:
|
while self.T >= self.stopping_temperature and self.iteration < max_it:
|
||||||
candidate = list(self.cur_solution)
|
candidate = list(self.cur_solution)
|
||||||
l = random.randint(2, self.N - 1)
|
l = random.randint(1, self.N - 1)
|
||||||
i = random.randint(0, self.N - l)
|
i = random.randint(0, self.N - l)
|
||||||
candidate[i : (i + l)] = reversed(candidate[i : (i + l)])
|
candidate[i : (i + l)] = reversed(candidate[i : (i + l)])
|
||||||
self.accept(candidate)
|
self.accept(candidate)
|
||||||
8
template/output/.gitignore
vendored
Normal file
8
template/output/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# .gitignore sample
|
||||||
|
###################
|
||||||
|
|
||||||
|
# Ignore all files in this dir...
|
||||||
|
*
|
||||||
|
|
||||||
|
# ... except for this one.
|
||||||
|
!.gitignore
|
||||||
21
template/utils/load_data.py
Normal file
21
template/utils/load_data.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
def log(msg):
|
||||||
|
print('[*] {msg}'.format(msg=msg))
|
||||||
|
|
||||||
|
def load_data(file):
|
||||||
|
coords = []
|
||||||
|
with open(file, "r") as infile:
|
||||||
|
line = infile.readline()
|
||||||
|
# Skip instance header
|
||||||
|
while "NODE_COORD_SECTION" not in line:
|
||||||
|
line = infile.readline()
|
||||||
|
|
||||||
|
for line in infile.readlines():
|
||||||
|
line = line.replace("\n", "")
|
||||||
|
if line and 'EOF' not in line:
|
||||||
|
line = [float(x) for x in line.lstrip().split(" ", 1)[1].split(" ") if x]
|
||||||
|
coords.append(line)
|
||||||
|
return coords
|
||||||
|
|
||||||
|
def timeout_handler(signum, frame):
|
||||||
|
print("Timeout")
|
||||||
|
raise Exception("Timeout")
|
||||||
139
template/utils/tsp.py
Normal file
139
template/utils/tsp.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import timeit
|
||||||
|
|
||||||
|
from utils.load_data import load_data
|
||||||
|
from utils.load_data import log
|
||||||
|
|
||||||
|
def timeout_handler(signum, frame):
|
||||||
|
raise Exception("Timeout")
|
||||||
|
|
||||||
|
def dist(node_0, node_1, coords):
|
||||||
|
"""
|
||||||
|
Euclidean distance between two nodes.
|
||||||
|
"""
|
||||||
|
coord_0, coord_1 = coords[node_0], coords[node_1]
|
||||||
|
return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)
|
||||||
|
|
||||||
|
def fitness(solution, coords):
|
||||||
|
N = len(coords)
|
||||||
|
cur_fit = 0
|
||||||
|
for i in range(len(solution)):
|
||||||
|
cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)
|
||||||
|
return cur_fit
|
||||||
|
|
||||||
|
def TSP_Bench(tsp_file, model, *args, max_it=1000, timeout=60):
|
||||||
|
|
||||||
|
start = timeit.default_timer()
|
||||||
|
|
||||||
|
# Model Running
|
||||||
|
best_solution, fitness_list = TSP(tsp_file, model, *args, max_it=max_it,timeout=timeout)
|
||||||
|
# Model End
|
||||||
|
|
||||||
|
stop = timeit.default_timer()
|
||||||
|
print('[*] Running for: {time:.2f} seconds'.format(time=(stop - start)))
|
||||||
|
|
||||||
|
print()
|
||||||
|
return best_solution, fitness_list, (stop - start)
|
||||||
|
|
||||||
|
def TSP_Bench_ALL(tsp_file_path, model, *args, max_it=1000, timeout=60):
|
||||||
|
best_solutions = []
|
||||||
|
fitness_lists = []
|
||||||
|
times = []
|
||||||
|
for root, _, files in os.walk(tsp_file_path):
|
||||||
|
if(files):
|
||||||
|
for f in files:
|
||||||
|
# Get input file name
|
||||||
|
tsp_file = str(root) + '/' + str(f)
|
||||||
|
log(tsp_file)
|
||||||
|
|
||||||
|
# Run TSP
|
||||||
|
best_solution, fitness_list, time = TSP_Bench(tsp_file, model, *args, max_it=max_it,timeout=timeout)
|
||||||
|
best_solutions.append(best_solution)
|
||||||
|
fitness_lists.append(fitness_lists)
|
||||||
|
times.append(time)
|
||||||
|
|
||||||
|
return best_solutions, fitness_lists, times
|
||||||
|
|
||||||
|
def TSP(tsp_file, model, *args, max_it=1000, timeout=60):
|
||||||
|
|
||||||
|
best_solution = []
|
||||||
|
fitness_list = []
|
||||||
|
|
||||||
|
nodes = load_data(tsp_file)
|
||||||
|
|
||||||
|
# Set timeout
|
||||||
|
signal.signal(signal.SIGALRM, timeout_handler)
|
||||||
|
signal.alarm(timeout)
|
||||||
|
|
||||||
|
if not os.path.exists('output'):
|
||||||
|
os.makedirs('output')
|
||||||
|
|
||||||
|
# Try your algorithm
|
||||||
|
try:
|
||||||
|
model.init(nodes, *args)
|
||||||
|
best_solution, fitness_list = model.fit(max_it)
|
||||||
|
except Exception as exc:
|
||||||
|
if(str(exc) == "Timeout"):
|
||||||
|
log("Timeout -3")
|
||||||
|
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile:
|
||||||
|
outfile.write("-3")
|
||||||
|
best_solution = [-1] * len(nodes)
|
||||||
|
else:
|
||||||
|
print(exc)
|
||||||
|
log("Unkown -4")
|
||||||
|
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile:
|
||||||
|
outfile.write("-4")
|
||||||
|
|
||||||
|
signal.alarm(0)
|
||||||
|
|
||||||
|
# Collect results
|
||||||
|
if(len(fitness_list) > 0):
|
||||||
|
log("[Node] " + str(len(best_solution)) + ", [Best] " + str(fitness_list[fitness_list.index(min(fitness_list))]))
|
||||||
|
|
||||||
|
if (len(best_solution) == 0):
|
||||||
|
log("No Answer -1")
|
||||||
|
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile:
|
||||||
|
outfile.write("-1")
|
||||||
|
elif (len(best_solution) != len(nodes)):
|
||||||
|
log("Invalid -2")
|
||||||
|
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile:
|
||||||
|
outfile.write("-2")
|
||||||
|
else:
|
||||||
|
# log("Writing the best solution to file" )
|
||||||
|
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile:
|
||||||
|
outfile.write(str(model.fitness(best_solution)))
|
||||||
|
outfile.write("\n")
|
||||||
|
outfile.write(", ".join(str(item) for item in best_solution))
|
||||||
|
|
||||||
|
# Write to JSON
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
data['nodes'] = []
|
||||||
|
for i in range(len(nodes)):
|
||||||
|
data['nodes'].append({
|
||||||
|
'title': str(i),
|
||||||
|
'id': i,
|
||||||
|
'x': int(nodes[i][0]),
|
||||||
|
'y': int(nodes[i][1])
|
||||||
|
})
|
||||||
|
|
||||||
|
data['edges'] = []
|
||||||
|
for i in range(len(best_solution)):
|
||||||
|
if i == len(best_solution)-1:
|
||||||
|
data['edges'].append({
|
||||||
|
'source': best_solution[i],
|
||||||
|
'target': best_solution[0]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
data['edges'].append({
|
||||||
|
'source': best_solution[i],
|
||||||
|
'target': best_solution[i+1]
|
||||||
|
})
|
||||||
|
|
||||||
|
with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.json', 'w') as outfile:
|
||||||
|
json.dump(data, outfile)
|
||||||
|
|
||||||
|
return best_solution, fitness_list
|
||||||
Reference in New Issue
Block a user