[workshop] Add notebook
This commit is contained in:
parent
38dce8dc73
commit
4d2d53da56
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
|
|
@ -1,3 +1,6 @@
|
|||
## Build Image
|
||||
|
||||
docker build -t com2014-tsp .
|
||||
|
||||
## Windows
|
||||
|
||||
|
|
@ -35,13 +35,13 @@ def TSP(tsp_file, model):
|
|||
coords = load_data(tsp_file)
|
||||
|
||||
# Set timeout
|
||||
signal.signal(signal.SIGALRM, timeout_handler)
|
||||
signal.alarm(60)
|
||||
# signal.signal(signal.SIGALRM, timeout_handler)
|
||||
# signal.alarm(60)
|
||||
|
||||
# Try your algorithm
|
||||
try:
|
||||
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:
|
||||
if(str(exc) == "Timeout"):
|
||||
log("Timeout -3")
|
||||
|
|
@ -72,7 +72,7 @@ class SimAnneal(Model):
|
|||
self.log("Starting annealing.")
|
||||
while self.T >= self.stopping_temperature and self.iteration < max_it:
|
||||
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)
|
||||
candidate[i : (i + l)] = reversed(candidate[i : (i + l)])
|
||||
self.accept(candidate)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# .gitignore sample
|
||||
###################
|
||||
|
||||
# Ignore all files in this dir...
|
||||
*
|
||||
|
||||
# ... except for this one.
|
||||
!.gitignore
|
||||
|
|
@ -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")
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue