This repository has been archived on 2021-10-31. You can view files and clone it, but cannot push or open issues or pull requests.
AICup/Lectures/Student_lecture 1.ipynb

646 lines
217 KiB
Plaintext
Raw Normal View History

2020-10-01 16:03:04 +00:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
2020-10-19 15:25:30 +00:00
"## First Lab\n",
2020-10-12 09:45:37 +00:00
"\n",
"What we are going to do today:\n",
"- read TSP data\n",
"- define euclidean distance function\n",
"- define a ProblemInstance python class \n",
"- store nodes in an instance of the class defined before\n",
"- plot raw data\n",
"- generate naive solution \n",
"- check if the solution is valid\n",
"- evaluate solution!#\n",
"\n",
"NOTE: I've marked all the code that you will have to fill with a `# TODO` comment\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2020-11-01 18:24:26 +00:00
"This cell below is simply importing some useful stuff for later"
2020-10-12 09:45:37 +00:00
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import glob\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Read TSP data\n",
"In this Cup you will have to deal with predefined set of problems. These problems are located in the `problems` folder.\n",
"\n",
"First lets get list them out"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ch130.tsp\n",
"d198.tsp\n",
"eil76.tsp\n",
"fl1577.tsp\n",
"kroA100.tsp\n",
"lin318.tsp\n",
"pcb442.tsp\n",
"pr439.tsp\n",
"rat783.tsp\n",
"u1060.tsp\n"
]
}
],
"source": [
"problems = glob.glob('../problems/*.tsp')\n",
2020-11-01 18:24:26 +00:00
"# example_problem = [\"../problems/eil76.tsp\"]\n",
2020-10-12 09:45:37 +00:00
"for prob in problems:\n",
" print(prob[12:])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Checking by hand if all of the 10 problems are in the folder would be a waste of time so we can write a line of code just to check if they are all there"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n"
]
}
],
"source": [
"print(np.all([n[12:] in ['fl1577.tsp','pr439.tsp','ch130.tsp','rat783.tsp','d198.tsp', 'kroA100.tsp','u1060.tsp','lin318.tsp','eil76.tsp','pcb442.tsp'] for n in problems]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### File format\n",
"All the problems are stored in a `.tsp` (this file is actually a renamed `.txt` file, so you could open them with your favorite text editor)\n",
"\n",
"As we will see in a bit all the problems files are composed of different sections:\n",
"* `NAME`: the shortned name of the problem\n",
"* `COMMENT`: a comment area that can contain the full name of the problem\n",
"* `TYPE`: this defines the type of problem at hand, in our case is always TSP\n",
"* `DIMENSION`: this states the problem dimension\n",
"* `EDGE_WEIGHT_TYPE`: this section states the types of weights applied to edges, in our case it is always EUC_2D or the weights are giveng using the euclidean distance in 2 dimension\n",
"* `BEST_KNOWN`: this states the best known result obtained, note that as the Prof said, it is unlikely to get a better performance than this\n",
"* `NODE_COORD_SECTION`: finally we have the section that states the triplets that defines the problems points. These triplets are (point_number, x,y).\n",
"\n",
"Now that we know all of that, lets print the content of a single problem"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['NAME : eil76', 'COMMENT : 76-city problem (Christofides/Eilon)', 'TYPE : TSP', 'DIMENSION : 76', 'EDGE_WEIGHT_TYPE : EUC_2D', 'BEST_KNOWN : 538', 'NODE_COORD_SECTION', '1 22 22', '2 36 26', '3 21 45', '4 45 35', '5 55 20', '6 33 34', '7 50 50', '8 55 45', '9 26 59', '10 40 66', '11 55 65', '12 35 51', '13 62 35', '14 62 57', '15 62 24', '16 21 36', '17 33 44', '18 9 56', '19 62 48', '20 66 14', '21 44 13', '22 26 13', '23 11 28', '24 7 43', '25 17 64', '26 41 46', '27 55 34', '28 35 16', '29 52 26', '30 43 26', '31 31 76', '32 22 53', '33 26 29', '34 50 40', '35 55 50', '36 54 10', '37 60 15', '38 47 66', '39 30 60', '40 30 50', '41 12 17', '42 15 14', '43 16 19', '44 21 48', '45 50 30', '46 51 42', '47 50 15', '48 48 21', '49 12 38', '50 15 56', '51 29 39', '52 54 38', '53 55 57', '54 67 41', '55 10 70', '56 6 25', '57 65 27', '58 40 60', '59 70 64', '60 64 4', '61 36 6', '62 30 20', '63 20 30', '64 15 5', '65 50 70', '66 57 72', '67 45 42', '68 38 33', '69 50 4', '70 66 8', '71 59 5', '72 35 60', '73 27 24', '74 40 20', '75 40 37', '76 40 40', 'EOF']\n"
]
}
],
"source": [
"example_problem = \"../problems/eil76.tsp\"\n",
"with open(example_problem,\"r\") as exprob:\n",
" print(exprob.read().splitlines())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Euclidean Distance\n",
"Since all of our problems are using the euclidean distance between points for the edges weights.\n",
"We will now define a function that computes the euclidean distance. This distance will also be used to build the distance matrix"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def distance_euc(point_i, point_j):\n",
2020-10-12 09:45:37 +00:00
" rounding = 0\n",
" x_i, y_i = point_i[0], point_i[1]\n",
2020-11-01 18:24:26 +00:00
" x_j, y_j = point_j[0], point_j[1]\n",
" distance = np.sqrt((x_i - x_j) ** 2 + (y_i - y_j) ** 2)\n",
2020-10-12 09:45:37 +00:00
" return round(distance, rounding)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's test it"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4.0"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"point_1 = (2, 2)\n",
"point_2 = (5, 5)\n",
"distance_euc(point_1, point_2)\n",
"# Expected output is 4.0 with rounding to 0 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Reading and storing the data\n",
"We will now define a Class called `ProblemInstance`\n",
"\n",
"in the Constructor of the class (`__init__()`method of a class in Python) you will have to implement the code for:\n",
"* reading the raw data\n",
"* store the metadata\n",
"* read all the point and store them\n",
"* code the method that creates the distance matrix between points\n",
"* \\[optional\\] check if the problem loaded has an optimal and in that case store the optimal solution\n",
"* \\[optional\\] code the plotting method\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [],
"source": [
"from src.utils import distance_euc\n",
"\n",
"class ProblemInstance:\n",
"\n",
" def __init__(self, name_tsp):\n",
" self.exist_opt = False\n",
" self.optimal_tour = None\n",
" self.dist_matrix = None\n",
" \n",
" # read raw data \n",
" # TODO\n",
2020-11-01 18:24:26 +00:00
" with open(name_tsp) as f_o:\n",
" data= f_o.read()\n",
" self.lines = data.splitlines()\n",
" \n",
"# file_object = open(name_tsp)\n",
"# data = file_object.read()\n",
"# file_object.close()\n",
"# self.lines = data.splitlines()\n",
2020-10-12 09:45:37 +00:00
"\n",
" # store metadata set information \n",
" # TODO\n",
2020-11-01 18:24:26 +00:00
" self.name = self.lines[0].split(' ')[2]\n",
" # here we expect the name of the problem\n",
" self.nPoints = np.int(self.lines[3].split(' ')[2])\n",
" self.best_sol = np.float(self.lines[5].split(' ')[2])\n",
" # here the lenght of the best solution\n",
2020-10-12 09:45:37 +00:00
" \n",
" # read all data points and store them \n",
" # TODO\n",
" self.points = np.zeros((self.nPoints, 3)) # this is the structure where we will store the pts data \n",
2020-11-01 18:24:26 +00:00
" for i in range(self.nPoints):\n",
" line_i = self.lines[7 + i].split(' ')\n",
2020-11-01 18:24:26 +00:00
" self.points[i, 0] = int(line_i[0])\n",
" self.points[i, 1] = line_i[1]\n",
" self.points[i, 2] = line_i[2]\n",
2020-10-12 09:45:37 +00:00
" \n",
" self.create_dist_matrix()\n",
" \n",
" # TODO [optional]\n",
" # if the problem is one with a optimal solution, that solution is loaded\n",
" if name_tsp in [\"../problems/eil76.tsp\", \"../problems/kroA100.tsp\"]:\n",
" self.exist_opt = True\n",
2020-11-01 18:24:26 +00:00
" file_object = open(name_tsp.replace(\".tsp\", \".opt.tour\"))\n",
" data = file_object.read()\n",
" file_object.close()\n",
" lines = data.splitlines()\n",
2020-10-12 09:45:37 +00:00
"\n",
" # read all data points and store them\n",
" self.optimal_tour = np.zeros(self.nPoints, dtype=np.int)\n",
2020-11-01 18:24:26 +00:00
" for i in range(self.nPoints):\n",
" line_i = lines[5 + i].split(' ')\n",
" self.optimal_tour[i] = int(line_i[0]) - 1\n",
2020-10-12 09:45:37 +00:00
"\n",
" def print_info(self):\n",
" print(\"\\n#############################\\n\")\n",
" print('name: ' + self.name)\n",
" print('nPoints: ' + str(self.nPoints))\n",
" print('best_sol: ' + str(self.best_sol))\n",
" print('exist optimal: ' + str(self.exist_opt))\n",
"\n",
" def plot_data(self,show_numbers=False): # todo [optional]\n",
" plt.figure(figsize=(8, 8))\n",
" plt.title(self.name)\n",
" plt.scatter(self.points[:, 1], self.points[:, 2])\n",
" if show_numbers:\n",
" for i, txt in enumerate(np.arange(self.nPoints)): # tour_found[:-1]\n",
" plt.annotate(txt, (self.points[i, 1], self.points[i, 2]))\n",
" plt.show()\n",
"\n",
" def create_dist_matrix(self): # TODO\n",
2020-11-01 18:24:26 +00:00
" self.dist_matrix = np.zeros((self.nPoints, self.nPoints))\n",
"\n",
2020-11-01 18:24:26 +00:00
" for i in range(self.nPoints):\n",
" for j in range(i, self.nPoints):\n",
" self.dist_matrix[i, j] = distance_euc(self.points[i][1:3], self.points[j][1:3])\n",
" self.dist_matrix += self.dist_matrix.T\n"
2020-10-12 09:45:37 +00:00
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"------------------------\n",
"Now we can test our Class with an example problem"
]
},
{
"cell_type": "code",
"execution_count": 8,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [],
"source": [
"example_problem = \"../problems/eil76.tsp\"\n",
"p_inst=ProblemInstance(example_problem)"
]
},
{
"cell_type": "code",
"execution_count": 9,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"#############################\n",
"\n",
"name: eil76\n",
"nPoints: 76\n",
"best_sol: 538.0\n",
"exist optimal: True\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 576x576 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"'\\n#############################\\n\\nname: eil76\\nnPoints: 76\\nbest_sol: 538.0\\nexist optimal: True\\n\\n'"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
2020-10-12 09:45:37 +00:00
"source": [
"p_inst.print_info()\n",
"p_inst.plot_data()\n",
"#Expected output\n",
"\"\"\"\n",
"#############################\n",
"\n",
"name: eil76\n",
"nPoints: 76\n",
"best_sol: 538.0\n",
"exist optimal: True\n",
"\n",
"\"\"\""
]
},
{
"cell_type": "code",
"execution_count": 10,
2020-10-12 09:45:37 +00:00
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 576x576 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
2020-10-12 09:45:37 +00:00
"source": [
"p_inst.plot_data(show_numbers=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"-------------\n",
"### Random solver \n",
"Now we will code the random solver and test it with a class called `SolverTSP` that takes the solvers and the problem instance and act as a framework to compute the solution and gives us some additional information.\n",
"We will also need to code the `evaluate_solution` method of the the `SolverTSP` class"
]
},
{
"cell_type": "code",
"execution_count": 11,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [],
"source": [
"import random\n",
2020-10-12 09:45:37 +00:00
"def random_method(instance_): # TODO\n",
" n = int(instance_.nPoints)\n",
" solution = np.random.choice(np.arange(n), size=n, replace=False)\n",
2020-10-12 09:45:37 +00:00
" return solution\n",
"\n",
"def marco_random_method(instance_):\n",
" solution = list(range(instance_.npoints))\n",
" for i in range(len(solution)):\n",
" rand = random.randint(i, len(solution))\n",
" solution[i], solution[rand] = solution[rand], solution[i]\n",
" return solution\n",
"\n",
"def numpy_random_method(insta_):\n",
" return np.random.permutation(np.arange(insta_.nPoints)) \n",
"available_methods = {\"random\": random_method,\n",
" \"marco\":marco_random_method,\n",
" \"numpy\":numpy_random_method}"
2020-10-12 09:45:37 +00:00
]
},
{
"cell_type": "code",
"execution_count": 12,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [],
"source": [
"from time import time as t\n",
"\n",
"class SolverTSP:\n",
" def __init__(self, algorithm_name, problem_instance):\n",
" self.duration = np.inf\n",
" self.found_length = np.inf\n",
" self.algorithm_name = algorithm_name\n",
" self.name_method = \"initialized with \" + algorithm_name\n",
" self.solved = False\n",
" self.problem_instance = problem_instance\n",
" self.solution = None\n",
"\n",
" def compute_solution(self, verbose=True, return_value=True):\n",
" self.solved = False\n",
" if verbose:\n",
" print(f\"### solving with {self.algorithm_name} ####\")\n",
" start_time = t()\n",
" self.solution = available_methods[self.algorithm_name](self.problem_instance)\n",
" assert self.check_if_solution_is_valid(self.solution), \"Error the solution is not valid\"\n",
" end_time = t()\n",
" self.duration = np.around(end_time - start_time, 3)\n",
" if verbose:\n",
" print(f\"### solved ####\")\n",
" self.solved = True\n",
" self.evaluate_solution()\n",
" self._gap()\n",
" if return_value:\n",
" return self.solution\n",
"\n",
" def plot_solution(self):\n",
" assert self.solved, \"You can't plot the solution, you need to compute it first!\"\n",
" plt.figure(figsize=(8, 8))\n",
" self._gap()\n",
" plt.title(f\"{self.problem_instance.name} solved with {self.name_method} solver, gap {self.gap}\")\n",
" ordered_points = self.problem_instance.points[self.solution]\n",
" plt.plot(ordered_points[:, 1], ordered_points[:, 2], 'b-')\n",
" plt.show()\n",
"\n",
" def check_if_solution_is_valid(self, solution):\n",
" rights_values = np.sum([self.check_validation(i, solution) for i in np.arange(self.problem_instance.nPoints)])\n",
" if rights_values == self.problem_instance.nPoints:\n",
" return True\n",
" else:\n",
" return False \n",
" \n",
2020-10-12 09:45:37 +00:00
" def check_validation(self, node , solution):\n",
" if np.sum(solution == node) == 1:\n",
" return 1\n",
" else:\n",
" return 0\n",
"\n",
" def evaluate_solution(self, return_value=False):\n",
" total_length = 0\n",
" from_node_id = self.solution[0] # starting_node\n",
2020-10-12 09:45:37 +00:00
" # TODO\n",
" for node_id in self.solution[1:]:\n",
" edge_distance = self.problem_instance.dist_matrix[from_node_id, node_id]\n",
" total_length += edge_distance\n",
" from_node_id = node_id\n",
2020-10-12 09:45:37 +00:00
" self.found_length = total_length\n",
" if return_value:\n",
" return total_length\n",
"\n",
" def _gap(self):\n",
" self.evaluate_solution(return_value=False)\n",
" self.gap = np.round(\n",
" ((self.found_length - self.problem_instance.best_sol) / self.problem_instance.best_sol) * 100, 2)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"----------------------------\n",
"Now we will test our code"
]
},
{
"cell_type": "code",
"execution_count": 13,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"### solving with random ####\n",
"### solved ####\n",
"the total length for the solution found is 2522.0\n",
"while the optimal length is 538.0\n",
"the gap is 368.77%\n",
"the solution is found in 0.0 seconds\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAeAAAAHiCAYAAAAwHB+eAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOyddbhUxRvHv0N3hzSC0kh4JZROqSuCEiqCkoKCCgiiSAki/FRAKQsJKUEQJZQu6RKQ7oZLXuLmzu+P7zmes3u3+8J8nmef3T0xZ07NO2/MO0JKCYVCoVAoFMElRagroFAoFArFo4gSwAqFQqFQhAAlgBUKhUKhCAFKACsUCoVCEQKUAFYoFAqFIgQoAaxQKBQKRQhQAthLhBCDhBDfa7+LCiGkECJVqOulo9XniQCUe1oI0cDHMpYLITo6Wf+TEOJTN8sqLIS4K4RI6Y9ttfXF3CjL6p67OidvEEIMFULM8rGMV4UQfzlZX0cIcd6XY/gTIUQnIcSmUNfDEf64JwqFjhLAXiKlHCWl7GJvnRDioNaQ658EIcTvpvUphRCfCiEuCiGihRB7hBDZglf70CKlbCKlnA743uBKKc9KKTNJKRM93VYIsU4I0cVmm0xSypNe1OO/cwonpJQ/Sykb6f8D1TFTPDwIIeoKIfYLIW4JIa4LIRYJIQrYbNNACLFbCHFPCHFOCNHGtK6etu6OEOKkEKKbk2M5bCuFEDVt1t3Vnt/WgTv74KIEcACQUpbVGvJMADIDOAvgF9MmwwA8C6A6gCwAOgCICXpFFQofEES1IX7AHQtOEPkXQGMpZTYA+QEcAzBZXymEKANgNoCPAGQFUBHALm1dagCLAEzV1rUF8KUQooK9AzlrK6WUG/V12vrmAO4CWOH/Uw4N6uVxghAivxBioRDimhDilBCit2mdu6aoWgDyAFio7ZcdwLsAukopz0hyQEppVwALIZoKIf7VNOULQoh+pnVdhRDHhRA3hBBLhBD57exfTQhx2fyCCyFeFEL8o/1OIYQYKIQ4ofV25wshcpi27SCEOKOt+8jJtXpc6zGn0P5/L4S4alo/SwjxrvZ7nRCiixCiNIApAKprvdtbpiKzCyGWaue9TQhR3MFxbU3B64QQI4QQm7V9/xJC5LLdVggxEkBNAN9ox/5G2+Y/DVEI0UyzTtzRevlDnZz/f9q0EGKfnV57HdP9+Fu7Vvv05aZruF6r90oAuZwcb72uCQghamjHaKr9byCE2Kv9/s/CIITYoO2u16+tqby+QoirQohLQog3XJznSCHEZgD3ARQTQrwhhDik1fukEKK7afs6QojzjsoXQuTUnt07QojtAIrbHO9ZIcQOIcRt7ftZm7p8ql3Pu0KI37XyftbK2yGEKOrgPNJpz+R17V7sEELk1dbl1+p0Q/D96uqgjBVCiLdtlu0TQrTSfpcSQqzUyjkirLXEn4QQk4UQy4QQ9wDUdXTNTfs00sq5LYSYpD0D+jNXXAixRjufKO0aZDPte1oI8aFgW3JTCDFNCJHO3nGklFeklBdNixIBmK0mHwOYKqVcLqVMkFJel1Ke0NblAJWKmVrbtgPAIQBlXJ0fbNpKO3QEsEBKec+NspIHUkr1sfMBOye7AHwCIA2AYgBOgj1DABgKYJb2uygACSCVnXJ+BPCT6X8tALcADABwGcBRAL2c1OMSgJra7+wAKmu/6wGIAlAZQFoAXwPYYNpPAnhC+30CQEPTul8ADNR+vwtgK4CCWjlTAczR1pUBe5y1tHVfAkgA0MBBXc8CeFr7fUS7XqVN6yppv9cB6KL97gRgk005PwG4AaAKgFQAfgYw18Exra69VvYJACUApNf+j3aybReb8szXrQ6A8tqz8BSAKwBauluWtrwbgMNgo1QAwHUATbUyG2r/c2vbbtGucVrtmkdDe8bslDscwNfa70HaOX9uWjfe3vU1n5/pHBO0fVJrdbsPILuD467T7mVZ7d6kBtAMFJwCQG1t/8rulA9gLoD5ADICKAfggl5fsDG/CVqIUgFor/3PaarLce3YWUHN7SiABtr2MwBMc3Ae3QH8DiADgJQAngaQRVu3HsAkAOlA7e4agPp23vvXAWw2lVkGfLfTaudzDsAbWl0qg+9rWdMzfhvAc9qzkM5Fe5QLwB0ArbTy+gCIh/EePQE+T2kB5AawAcA40/6nARwAUEi7rpsBfOrkeIW1c7Fox+lkWncSwAgA+8H2aRaAHKb1swH00q5rdQBXARRyo821aitt1mUA34c6rspJTp+QVyBcPwCqAjhrs+xD/YWGGwJYe2jumB8aAK9o2/4ACointBe8oYN6nNUaiyw2y38AMMb0P5P2ohTV/psFyacAftR+ZwZwD0AR7f8hvXHR/ufTykkFdj7mmtZlBBAHxwJ4JoD3ATwGCuAxAHoAeFx7mVNo262DawH8vel/UwCHHRzT6tprZX9sWt8TwAon2zoUwHaONQ7AVx6UVQNsfEpo/weAmoF5mz/Bnn1hUFBlNK2bDccCuD6Af7TfKwB0AbBV+78eQCt719f2/EAB+QCmZ1erczUHx10HYLiLd2cxgD6uygcb6HgApUzrRsEQwB0AbLcpews0YaDV5SPTui8ALDf9bwFgr4M6vgngbwBP2SwvBGp8mU3LPoMmGGD93tu+SyNhvGdtAWy0KXsqgCGmZ3yGs+tos+/rALaY/gtQwCfp9GnrWwLYY/p/GkAPm3fqhBvHzaE9t9VMy+K08kqA7c5CAD/bXPcr4POcAFr7XB0nSVtps74DgFMAhLvXLDl8lAnaMUUA5NfMU7cEzaODAOT1oIxWoCa33rTsgfY9XEr5QEr5D6gFNHVQRmtt3RnN5FRdW54fwBl9IynlXVCbKpC0CMwG0EoIkVar024ppb5vEQCLTOd4CGyA8mrHOGc6xj3tGI5YDza4tcAe+DpQI6oNNkYWJ/vactn0+z74ogdj3/8QQlQVQqwVdEHcBjsTDs3CNvsWAjW7jlLKo9riIgBetnmmaoCdnvwAbkpr89oZOGYLgBKa2bQiqO0VEjS3VwGvv7tcl1ImmP67umbnzH+EEE2EEFs1U+st8Hk1XydH5ecGO3rm8sznnB9Jr8EZWD/jV0y/H9j57+g8ZoKdn7mCwZBjBP2X+QHckFJGOzkmAEDbZimAdtqidqC1BuC9rmpzr18FO6c6VtfRBbbvogTwX/S6ECKPEGKuoJvqDqiV2j6rttc5icvKFinlDQDTAfwmjFEeD0BF5KjW7oyC1n4JIUoBmAd2GNKAlpIPhBDNXBzKXltppiPYYZGu6pycUALYMecAnJJSZjN9MkspHQlKe9h7aP7Rvt16kKSUO6SUL4C+kcVgow4AF8GXHAAghMgIICdowrMt41/whWsCauCzTavPAWhic57ppJQXQPNSIdMxMmjHcMR60K9aR/u9CTSx1YbjFyuUL5SrY88GsAQ0n2UF/dXCVaFCiPTgvRonpVxuWnUO1IDN1zqjlHI0eK2za/dRp7DDikt5H3SR9AFwQEoZB2p074OaTZSrevrAf9dN69QtBPA/AHklA3eWwY3rBFp+EmB6xmB9zlbPuGl9kmfcU6SU8VLKYVLKMmBAZHNQaFwEkEMIkdnNY84B0F7rGKcHsFZbfg7Aept7nUlK+Za5Gh5U+RLoJgLAADjzf1BLl6BGnwXAa0h6D2yv80W4Ryqw/cmi/f8HjuteDsARKeWfUkqLlPII2Elp4uIYDgWs1pmtA3YyHyqUAHbMdgB3hBADhBDpBYcOlRNCPOPOzkKIgmBghdXQFMlghY0APhJCpBUMRGoL4A87ZaQRHMeZVUoZD5po9OE2swG8IYSoqDWCowBsk1KedlCl2QB6g9qpOSJ7CoCRQogi2jFzCyFe0NYtANBcMMgnDejHc/jMSCmPgb3j10B/9B1QI2kNxwL4CoCCWvnB5gro23dEZlAbihFCVAE7L+7wI2gyH2OzfBaAFkKIxtrzlE4wSKmgZpHYCWCYdt9rgKY8Z6wH8DaMa7vO5r89XJ2zp6QB/Y7XACQIIZoAaOR8FyI5HOxXAEOFEBkEo2s7mjZ
"text/plain": [
"<Figure size 576x576 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"'\\n### solving with random ####\\n### solved ####\\nthe total length for the solution found is 2424.0\\nwhile the optimal length is 538.0\\nthe gap is 350.56%\\nthe solution is found in 0.0 seconds\\n'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
2020-10-12 09:45:37 +00:00
"source": [
"\n",
2020-10-12 09:45:37 +00:00
"# here I'm repeating this two lines just to remind you which problem we are using\n",
"example_problem = \"../problems/eil76.tsp\"\n",
"p_inst = ProblemInstance(example_problem)\n",
"available_methods = {\"random\": random_method,\n",
" \"marco\":marco_random_method,\n",
" \"numpy\":numpy_random_method}\n",
"solver_name=\"random\"\n",
2020-10-12 09:45:37 +00:00
"# TODO\n",
"# 1. create an instance of SolverTSP\n",
"solver = SolverTSP(solver_name, p_inst)\n",
"# 2. compute a solution\n",
"solver.compute_solution()\n",
"# 3. print the information as for the output\n",
"# print(\"the total length for the solution found is\" + solver.solution)\n",
"print(f\"the total length for the solution found is {solver.found_length}\",\n",
" f\"while the optimal length is {solver.problem_instance.best_sol}\",\n",
" f\"the gap is {solver.gap}%\",\n",
" f\"the solution is found in {solver.duration} seconds\", sep=\"\\n\")\n",
"# 4. plot the solution\n",
"solver.plot_solution()\n",
2020-10-12 09:45:37 +00:00
"# this is the output expected and after that the solution's plot\n",
"\"\"\"\n",
"### solving with random ####\n",
"### solved ####\n",
"the total length for the solution found is 2424.0\n",
"while the optimal length is 538.0\n",
"the gap is 350.56%\n",
"the solution is found in 0.0 seconds\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"--------------------\n",
"Finally since our example problem has an optimal solution we can plot it"
]
},
{
"cell_type": "code",
"execution_count": 14,
2020-10-12 09:45:37 +00:00
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 576x576 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
2020-10-12 09:45:37 +00:00
"source": [
"solver = SolverTSP(\"optimal\", p_inst)\n",
"solver.solved = True\n",
"solver.solution = np.concatenate([p_inst.optimal_tour, [p_inst.optimal_tour[0]]])\n",
"solver.plot_solution()"
2020-10-01 16:03:04 +00:00
]
}
],
"metadata": {
"kernelspec": {
2020-10-12 09:45:37 +00:00
"display_name": "PyCharm (AI2020BsC)",
2020-10-01 16:03:04 +00:00
"language": "python",
2020-10-12 09:45:37 +00:00
"name": "pycharm-61970693"
2020-10-01 16:03:04 +00:00
},
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}