Done c++ ant colony opt with 2.5opt = 7.5

This commit is contained in:
Claudio Maggioni 2020-11-29 22:17:17 +01:00
parent 9f61b503d1
commit 55fa9b5d64
15 changed files with 670 additions and 1868 deletions

141
.gitignore vendored
View file

@ -24,3 +24,144 @@
/Complete notebooks/ /Complete notebooks/
/Lectures/.ipynb_checkpoints/ /Lectures/.ipynb_checkpoints/
/.ipynb_checkpoints/Student_lecture 1-checkpoint.ipynb /.ipynb_checkpoints/Student_lecture 1-checkpoint.ipynb
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
c_prob/*
!c_prob/.gitkeep

BIN
AI_cup_2020_description.pdf Normal file

Binary file not shown.

BIN
AI_cup_2020_studentname.xls Normal file

Binary file not shown.

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 one or more lines are too long

View file

@ -1,37 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## Fourth Lecture"
]
}
],
"metadata": {
"kernelspec": {
"name": "pycharm-61970693",
"language": "python",
"display_name": "PyCharm (AI2020BsC)"
},
"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
}

427
aco.cc Normal file
View file

@ -0,0 +1,427 @@
// vim: set ts=2 sw=2 et tw=80:
// compile with
// g++ -lpthread --std=c++11 -o c_prob/aco aco.cc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <pthread.h>
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <unistd.h>
using namespace std;
typedef unsigned int uint;
ostream& operator<< (ostream& out, vector<uint> a) {
out << "[";
for (int i = 0; i < a.size() - 1; i++) {
out << a[i] << ",";
}
out << a[a.size() - 1] << "]";
return out;
}
const uint MAX_NODES = 1577;
// alpha >= 0
double alpha;
// beta >= 1
double beta;
double pheromone_evaporation_coeff;
double pheromone_constant;
uint n_iterations;
uint n_ants;
uint n_nodes;
double dist_matrix[MAX_NODES][MAX_NODES];
double pheromone_map[MAX_NODES][MAX_NODES];
double ant_updated_pheromone_map[MAX_NODES][MAX_NODES];
double sh_dist;
vector<uint> sh_route;
bool first_pass;
uint start;
uint select_random(const set<uint> &s) {
auto n = rand() % s.size(); // not _really_ random
auto it = begin(s);
advance(it, n); // 'advance' the iterator n times
return *it;
}
struct ant {
uint other;
uint idx;
pthread_t t_handle;
uint location;
double distance_travelled;
set<uint> possible_locations;
vector<uint> route;
bool tour_complete = false;
void init() {
this->other = 0;
this->distance_travelled = 0.0;
this->route.clear();
this->possible_locations.clear();
for (size_t i = 0; i < n_nodes; i++) {
this->possible_locations.insert(i);
}
this->location = start;
this->update_route(start);
this->tour_complete = false;
};
void update_route(uint new_loc) {
this->route.push_back(new_loc);
this->possible_locations.erase(new_loc);
};
uint pick_path() {
if (first_pass) {
return select_random(this->possible_locations);
} else {
double attractiveness[n_nodes];
double sum_total = 0.0;
vector<uint> idxs;
for (uint loc : this->possible_locations) {
idxs.push_back(loc);
double pheromone_amount = pheromone_map[this->location][loc];
double distance = dist_matrix[this->location][loc];
if (distance == 0) { distance = 0.000000001; };
attractiveness[loc] = pow(pheromone_amount, alpha) *
pow(1 / distance, beta);
//cerr << "ant " << idx << " attr[loc]=" << attractiveness[loc] << endl;
sum_total += attractiveness[loc];
if (isnan(sum_total)) { cerr << "nanalert " << attractiveness[loc] <<
" " << pheromone_amount << " " << distance << endl; }
}
// it is possible to have small values for pheromone amount / distance,
// such that with rounding errors this is equal to zero
if (sum_total == 0.0) {
// increment all zero's, such that they are the smallest non-zero
// values supported by the system
// source: http://stackoverflow.com/a/10426033/5343977
for (uint loc : idxs) {
attractiveness[loc] = nextafter(attractiveness[loc],
std::numeric_limits<double>::infinity());
}
sum_total = nextafter(sum_total, std::numeric_limits<double>::infinity());
}
double toss = (double) rand() / (double) RAND_MAX;
// cerr << "ant " << idx << " sum_total is " << sum_total << " toss is " << toss << endl;
double cumulative = 0.0;
for (uint loc : idxs) {
double weight = (attractiveness[loc] / sum_total);
//cerr << "ant " << idx << " w: " << weight + cumulative << endl;
if (toss <= (weight + cumulative)) {
return loc;
}
cumulative += weight;
}
cerr << "cum " << cumulative << " n " << idxs.size() << " toss " << toss << endl;
sleep(1);
other++;
// cerr << "ant " << idx << " change statement" << endl;
return idxs[idxs.size() - 1];
}
};
void traverse(uint next) {
this->update_route(next);
this->distance_travelled += dist_matrix[this->location][next];
this->location = next;
//cerr << "traversing " << next << " dist: " << this->distance_travelled << endl;
}
void run() {
// cerr << "started ant - # can pick: " << this->possible_locations.size() << endl;
while (!this->possible_locations.empty()) {
uint next = this->pick_path();
this->traverse(next);
}
this->distance_travelled += dist_matrix[this->route[this->route.size() - 1]]
[this->route[0]];
// cerr << "stopped ant" << endl;
this->tour_complete = true;
}
};
void *ant_thread (void *ant_ptr) {
ant& ant = *((struct ant *) ant_ptr);
ant.run();
return NULL;
}
ant* ants;
void init_ants() {
for (size_t i = 0; i < n_ants; i++) {
ants[i].init();
ants[i].idx = i;
}
}
pthread_mutex_t mut;
void init_aco() {
pthread_mutex_init(&mut, NULL);
start = 0;
first_pass = true;
memset(pheromone_map, 0, sizeof(pheromone_map));
memset(ant_updated_pheromone_map, 0, sizeof(ant_updated_pheromone_map));
init_ants();
sh_dist = -1.0;
}
void populate_ant_updated_pheromone_map(ant& ant) {
for (size_t i = 0; i < ant.route.size(); i++) {
size_t j = (i + 1) % n_nodes;
double current_ph = ant_updated_pheromone_map[ant.route[i]][ant.route[j]];
double new_ph = pheromone_constant / ant.distance_travelled;
ant_updated_pheromone_map[ant.route[i]][ant.route[j]] =
ant_updated_pheromone_map[ant.route[j]][ant.route[i]] =
current_ph + new_ph;
}
}
void update_pheromone_map() {
for (size_t i = 0; i < n_nodes; i++) {
for (size_t j = 0; j < n_nodes; j++) {
pheromone_map[i][j] = (1 - pheromone_evaporation_coeff) *
pheromone_map[i][j] + ant_updated_pheromone_map[i][j];
}
}
}
void mainloop() {
for (size_t i = 0; i < n_iterations; i++) {
srand(i);
//cerr << "starting ants" << endl;
for (uint j = 0; j < n_ants; j++) {
pthread_create(&(ants[j].t_handle), NULL, ant_thread, &(ants[j]));
}
// cerr << "joining ants" << endl;
for (uint j = 0; j < n_ants; j++) {
pthread_join(ants[j].t_handle, NULL);
}
//cerr << "summing ants" << endl;
uint os = 0;
for (uint j = 0; j < n_ants; j++) {
os += ants[j].other;
populate_ant_updated_pheromone_map(ants[j]);
if (sh_dist < 0 || ants[j].distance_travelled < sh_dist) {
sh_dist = ants[j].distance_travelled;
sh_route = ants[j].route;
cerr << "new short distance is " << sh_dist << " ant " << j << endl;
}
}
update_pheromone_map();
first_pass = false;
init_ants();
memset(ant_updated_pheromone_map, 0, sizeof(ant_updated_pheromone_map));
/*double real = 0;
for (uint k = 0; k < n_nodes; k++) {
real += dist_matrix[sh_route[k]][sh_route[(k + 1) % n_nodes]];
}*/
cerr << "iteration " << i << ": dist " << sh_dist << endl;// << " os " << os << " rdist " << real << endl;
/*
uint nnz = 0;
double sum = 0, min = 1.0/0.0, max = -1.0/0.0;
for (int i = 0; i < n_nodes; i++) {
for (int j = 0; j < n_nodes - 1; j++) {
if (pheromone_map[i][j] != 0.0) nnz++;
sum += pheromone_map[i][j];
if (min > pheromone_map[i][j]) min = pheromone_map[i][j];
if (max < pheromone_map[i][j]) max = pheromone_map[i][j];
}
}
cerr << "phmap: avg " << sum / (double) (n_nodes * n_nodes) << " min " << min << " max " << max << " nnz " << nnz << endl;*/
}
}
uint two_opt() {
uint swaps = 0;
for (int i = 0; i < n_nodes - 1; i++) {
for (int j = i+2; j < n_nodes; j++) {
size_t ip = i == 0 ? (n_nodes - 1) : (i - 1);
size_t ei = sh_route[i], ej = sh_route[j], eii = sh_route[ip],
ejj = sh_route[j];
double new_dist = sh_dist - dist_matrix[eii][ei] - dist_matrix[ejj][ej]
+ dist_matrix[ei][ej] + dist_matrix[ejj][eii];
if (new_dist < sh_dist) {
//cerr << "2opt " << i << " " << j << ": " << new_dist << endl;
sh_dist = new_dist;
reverse(sh_route.begin() + i, sh_route.begin() + j);
swaps++;
}
}
}
return swaps;
}
uint two_five_opt() {
uint swaps = 0;
for (int i = 0; i < n_nodes - 2; i++) {
for (int j = i+2; j < n_nodes; j++) {
size_t ip = i == 0 ? (n_nodes - 1) : (i - 1);
size_t x1 = sh_route[ip];
size_t x2 = sh_route[i];
size_t x3 = sh_route[i+1];
size_t y3 = sh_route[j-2];
size_t y1 = sh_route[j-1];
size_t y2 = sh_route[j];
double var_a = sh_dist - dist_matrix[x2][x1] - dist_matrix[y2][y1]
+ dist_matrix[x1][y1] + dist_matrix[y2][x2];
double var_b = sh_dist - dist_matrix[x2][x1] - dist_matrix[y2][y1]
- dist_matrix[x2][x3] + dist_matrix[x2][y2]
+ dist_matrix[y1][x2] + dist_matrix[x1][x3];
double var_c = sh_dist - dist_matrix[x2][x1] - dist_matrix[y2][y1]
- dist_matrix[y1][y3] + dist_matrix[x1][y1]
+ dist_matrix[y1][x2] + dist_matrix[y3][y2];
if (var_a < sh_dist && var_a < var_b && var_a < var_c) {
//cerr << "25opt(a) " << i << " " << j << ": " << var_a << endl;
sh_dist = var_a;
reverse(sh_route.begin() + i, sh_route.begin() + j);
swaps++;
} else if (var_b < sh_dist && var_b < var_a && var_b < var_c) {
//cerr << "25opt(b) " << i << " " << j << ": " << var_b << endl;
//cerr << vector<uint>(sh_route.begin() + i - 1, sh_route.begin() + j + 1) << endl;
for (int k = i; k < j - 1; k++) {
sh_route[k] = sh_route[k + 1];
}
sh_route[j - 1] = x2;
//cerr << vector<uint>(sh_route.begin() + i - 1, sh_route.begin() + j + 1) << endl;
sh_dist = var_b;
swaps++;
} else if (var_c < sh_dist && var_c < var_a && var_c < var_b) {
//cerr << "25opt(c) " << i << " " << j << ": " << var_c << endl;
//cerr << vector<uint>(sh_route.begin() + i - 1, sh_route.begin() + j + 1) << endl;
for (int k = j - 2; k >= i; k--) {
sh_route[k + 1] = sh_route[k];
}
sh_route[i] = y1;
//cerr << vector<uint>(sh_route.begin() + i - 1, sh_route.begin() + j + 1) << endl;
sh_dist = var_c;
swaps++;
}
}
}
return swaps;
}
#define buffersize 100000
int main(int argc, char** argv) {
if (argc < 8) {
cerr << argv[0] << " [n_nodes] [n_iter] [n_ants] [alpha] [beta] [evap] [weight]" << endl;
return 1;
}
n_nodes = atoi(argv[1]);
n_iterations = atoi(argv[2]);
n_ants = atoi(argv[3]);
sscanf(argv[4], "%lf", &alpha);
sscanf(argv[5], "%lf", &beta);
sscanf(argv[6], "%lf", &pheromone_evaporation_coeff);
sscanf(argv[7], "%lf", &pheromone_constant);
ant ants_arr[n_ants];
ants = ants_arr;
cerr << n_nodes << endl;
char * pch;
int row = 0, column = 0;
char buffer[buffersize];
for (size_t i = 0; i < n_nodes; i++) {
fgets(buffer, buffersize, stdin);
pch = strtok(buffer, " ");
column = 0;
while (pch != NULL) {
sscanf(pch, "%lf", &(dist_matrix[row][column]));
pch = strtok(NULL, " ");
column++;
}
row++;
}
cerr << "reading done" << endl;
/*uint nnz = 0;
for (int i = 0; i < n_nodes; i++) {
for (int j = 0; j < n_nodes - 1; j++) {
if (dist_matrix[i][j] != 0.0) nnz++;
}
}
cerr << "dist: nnz " << nnz << endl;*/
init_aco();
// scan and parse
mainloop();
//for (uint k = 0; k < n_nodes; k++) {
// cerr << "p: " << sh_route[k] << ": " << dist_matrix[sh_route[k]][sh_route[(k + 1) % n_nodes]] << endl;
//}
cerr << "pre-optimization length: " << sh_dist << endl;
uint i = 0;
uint j = 0;
do {
//for (i = 0; i < 50; i++) {
//cerr << "2opt round " << i << endl;
//if(two_opt() == 0) break;
//}
for (j = 0; j < 50; j++) {
//cerr << "25opt round " << j << endl;
if(two_five_opt() == 0) break;
}
cerr << "optimizing length: " << sh_dist << endl;
} while (i > 0 || j > 0);
cerr << "optimized length: " << sh_dist << endl;
cout << sh_route << endl;
}

48
run.py
View file

@ -1,13 +1,17 @@
import glob import glob
import pandas as pd #import pandas as pd
from src.io_tsp import ProblemInstance from src.io_tsp import ProblemInstance
from src.TSP_solver import TSPSolver, available_improvers, available_solvers from src.TSP_solver import TSPSolver, available_improvers, available_solvers
import numpy as np import numpy as np
def use_solver_to_compute_solution(solver, improve, index, results, name, verbose, show_plots): def use_solver_to_compute_solution(solver, improve, index, results, name, verbose, show_plots):
solver.bind(improve) #solver.bind(improve)
# solver.bind("2-opt")
# solver.bind("2.5-opt")
solver.compute_solution(return_value=False, verbose=verbose) solver.compute_solution(return_value=False, verbose=verbose)
# solver.pop()
# solver.pop()
if verbose: if verbose:
print(f"the total length for the solution found is {solver.found_length}", print(f"the total length for the solution found is {solver.found_length}",
@ -23,8 +27,10 @@ def use_solver_to_compute_solution(solver, improve, index, results, name, verbos
def run(show_plots=False, verbose=False): def run(show_plots=False, verbose=False):
# problems = glob.glob('./problems/*.tsp') problems = glob.glob('./problems/*.tsp')
problems = ["./problems/eil76.tsp"]
problems = ["./problems/fl1577.tsp"]
solvers_names = available_solvers.keys() solvers_names = available_solvers.keys()
improvers_names = available_improvers.keys() improvers_names = available_improvers.keys()
results = [] results = []
@ -36,19 +42,22 @@ def run(show_plots=False, verbose=False):
if show_plots: if show_plots:
prob_instance.plot_data() prob_instance.plot_data()
for solver_name in solvers_names: for solver_name in solvers_names:
for improve in improvers_names: solver = TSPSolver(solver_name, prob_instance)
solver = TSPSolver(solver_name, prob_instance) use_solver_to_compute_solution(solver, None, index, results, problem_path, verbose, show_plots)
use_solver_to_compute_solution(solver, improve, index, results, problem_path, verbose, show_plots) # for improve in improvers_names:
for improve2 in [j for j in improvers_names if j not in [improve]]: # solver = TSPSolver(solver_name, prob_instance)
use_solver_to_compute_solution(solver, improve2, index, results, problem_path, verbose, show_plots) # use_solver_to_compute_solution(solver, improve, index, results, problem_path, verbose, show_plots)
# for improve2 in [j for j in improvers_names if j not in [improve]]:
for improve3 in [j for j in improvers_names if j not in [improve, improve2]]: # use_solver_to_compute_solution(solver, improve2, index, results, problem_path, verbose, show_plots)
use_solver_to_compute_solution(solver, improve3, index, results, problem_path, verbose, #
show_plots) # for improve3 in [j for j in improvers_names if j not in [improve, improve2]]:
solver.pop() # use_solver_to_compute_solution(solver, improve3, index, results, problem_path, verbose,
# show_plots)
solver.pop() # solver.pop()
#
# solver.pop()
if prob_instance.exist_opt and show_plots: if prob_instance.exist_opt and show_plots:
solver = TSPSolver("optimal", prob_instance) solver = TSPSolver("optimal", prob_instance)
@ -56,11 +65,12 @@ def run(show_plots=False, verbose=False):
solver.solution = np.concatenate([prob_instance.optimal_tour, [prob_instance.optimal_tour[0]]]) solver.solution = np.concatenate([prob_instance.optimal_tour, [prob_instance.optimal_tour[0]]])
solver.plot_solution() solver.plot_solution()
index = pd.MultiIndex.from_tuples(index, names=['problem', 'method']) #index = pd.MultiIndex.from_tuples(index, names=['problem', 'method'])
return pd.DataFrame(results, index=index, columns=["tour length", "optimal solution", "gap", "time to solve"]) return None
#return pd.DataFrame(results, index=index, columns=["tour length", "optimal solution", "gap", "time to solve"])
if __name__ == '__main__': if __name__ == '__main__':
df = run(show_plots=False, verbose=True) df = run(show_plots=True, verbose=True)
df.to_csv("./results.csv") df.to_csv("./results.csv")

View file

@ -6,17 +6,23 @@ from src.two_opt import loop2opt
from src.two_dot_five_opt import loop2dot5opt from src.two_dot_five_opt import loop2dot5opt
from src.simulated_annealing import sa from src.simulated_annealing import sa
from src.constructive_algorithms import random_method, nearest_neighbor, best_nearest_neighbor, multi_fragment_mf from src.constructive_algorithms import random_method, nearest_neighbor, best_nearest_neighbor, multi_fragment_mf
from src.ant_colony import ant_colony_opt
available_solvers = {"random": random_method, # available_solvers = {"random": random_method,
"nearest_neighbors": nearest_neighbor, # "nearest_neighbors": nearest_neighbor,
"best_nn": best_nearest_neighbor, # "best_nn": best_nearest_neighbor,
"multi_fragment": multi_fragment_mf # "multi_fragment": multi_fragment_mf
} # }
available_improvers = {"2-opt": loop2opt, available_improvers = {"2-opt": loop2opt,
"2.5-opt": loop2dot5opt, "2.5-opt": loop2dot5opt,
"simulated_annealing": sa} "simulated_annealing": sa}
# available_solvers = {}
# for i in range(1, 10):
# for j in range(1, 10):
# available_solvers["aco_" + str(i) + "_" + str(j)] = ant_colony_opt(i/10, j)
available_solvers = {"aco": ant_colony_opt}
class TSPSolver: class TSPSolver:
def __init__(self, algorithm_name, problem_instance, passed_avail_solvers=None, passed_avail_improvers=None): def __init__(self, algorithm_name, problem_instance, passed_avail_solvers=None, passed_avail_improvers=None):
@ -52,14 +58,14 @@ class TSPSolver:
print(f"### solving with {self.algorithms} ####") print(f"### solving with {self.algorithms} ####")
start_time = t() start_time = t()
self.solution = self.available_solvers[self.algorithms[0]](self.problem_instance) self.solution = self.available_solvers[self.algorithms[0]](self.problem_instance)
if self.check_if_solution_is_valid(): if not self.check_if_solution_is_valid():
print(f"Error the solution of {self.algorithm_name} for problem {self.problem_instance.name} is not valid") print(f"Error the solution of {self.algorithm_name} for problem {self.problem_instance.name} is not valid")
if return_value: if return_value:
return False return False
for i in range(1, len(self.algorithms)): for i in range(1, len(self.algorithms)):
improver = self.algorithms[i] improver = self.algorithms[i]
self.solution = self.available_improvers[improver](self.solution, self.problem_instance) self.solution = self.available_improvers[improver](self.solution, self.problem_instance)
if self.check_if_solution_is_valid(): if not self.check_if_solution_is_valid():
print( print(
f"Error the solution of {self.algorithm_name} with {improver} for problem {self.problem_instance.name} is not valid") f"Error the solution of {self.algorithm_name} with {improver} for problem {self.problem_instance.name} is not valid")
if return_value: if return_value:

55
src/ant_colony.py Normal file
View file

@ -0,0 +1,55 @@
from src.io_tsp import ProblemInstance
import os
# OOT = out-of-time
# Run #0 unknown
# Run #1
# alpha = 0.5, beta = 7, evap = 0.5, weight = instance.best_sol
# if instance.nPoints > 1000: ants = 550 loops = 15
# elif instance.nPoints > 195: ants = 1000 loops = 55
# else: ants = 2500 loops = 150
# pr439=112263 pcb442=53699 d198=16199 fl1577=<OOT> ch130=6332 u1060=247703
# kroA100=21737 eil76=554 rat783=<OOT> lin318=45580
# Run #2
# alpha, beta, evap, weight = (0.9, 8, 0.4, 100_000)
# ants, loops = (900, 6) if instance.nPoints > 1100 \
# else (600, 15) if instance.nPoints > 1000 \
# else (750, 30) if instance.nPoints > 700 \
# else (975, 40) if instance.nPoints > 500 \
# else (1000, 50) if instance.nPoints > 300 \
# else (1100, 70) if instance.nPoints > 195 else (2700, 140)
# pr439=111322 pcb442=52176 d198=16177 ch130=6269 u1060=246085
# kroA100=21665 eil76=550 lin318=43675
# Separate run: fl1577=24238 (132s) rat783=9389 (174s)
dir = "/Users/maggicl/Git/AI2020BsC/c_prob/"
def ant_colony_opt(instance):
fname = dir + instance.name + ".txt"
# write .mat file for C++
if not os.path.exists(fname):
with open(fname, "w") as f:
for i in range(instance.nPoints):
print(" ".join(map(str, instance.dist_matrix[i])), file=f)
alpha, beta, evap, weight = (0.9, 8, 0.4, 100_000)
ants, loops = (1000,7) if instance.nPoints > 1100 \
else (600,15) if instance.nPoints > 1000 \
else (750,30) if instance.nPoints > 700 \
else (975,40) if instance.nPoints > 500 \
else (1000,50) if instance.nPoints > 300 \
else (1100,70) if instance.nPoints > 195 else (2700, 140)
# Call C++ program
cmd = dir + "aco " + str(instance.nPoints) + " " + str(loops) + " " + str(ants) + \
" " + str(alpha) + " " + str(beta) + " " + str(evap) + " " + str(weight) +" < " + fname + " &2>/dev/null"
print(cmd)
solution = eval(os.popen(cmd).read())
solution.append(solution[0])
return solution
if __name__ == "__main__":
ant_colony_opt(ProblemInstance("../problems/eil76.tsp"))

View file

@ -2,13 +2,11 @@ import numpy as np
from src.utils import compute_length from src.utils import compute_length
def random_method(instance_): def random_method(instance_):
n = int(instance_.nPoints) n = int(instance_.nPoints)
solution = np.random.choice(np.arange(n), size=n, replace=False) solution = np.random.choice(np.arange(n), size=n, replace=False)
return np.concatenate([solution, [solution[0]]]) return np.concatenate([solution, [solution[0]]])
def nearest_neighbor(instance_, starting_node=0): def nearest_neighbor(instance_, starting_node=0):
dist_matrix = np.copy(instance_.dist_matrix) dist_matrix = np.copy(instance_.dist_matrix)
n = int(instance_.nPoints) n = int(instance_.nPoints)

View file

@ -27,7 +27,8 @@ def step2dot5opt(solution, matrix_dist, distance):
uncrosses += 1 uncrosses += 1
tsp_sequence = sequences[best_method] tsp_sequence = sequences[best_method]
distance = best_len distance = best_len
# print(distance, best_method, [twoOpt_len, first_shift_len, second_shift_len]) print(i, j, best_len)
#print(distance, best_method, [twoOpt_len, first_shift_len, second_shift_len])
return tsp_sequence, distance, uncrosses return tsp_sequence, distance, uncrosses
@ -62,7 +63,7 @@ def shift_gain2(i, j, tsp_sequence, matrix_dist):
return - old_link_len + changed_links_len return - old_link_len + changed_links_len
def loop2dot5opt(solution, instance, max_num_of_changes=10000): def loop2dot5opt(solution, instance, max_num_of_changes=2500):
matrix_dist = instance.dist_matrix matrix_dist = instance.dist_matrix
actual_len = compute_length(solution, matrix_dist) actual_len = compute_length(solution, matrix_dist)
new_tsp_sequence = np.copy(np.array(solution)) new_tsp_sequence = np.copy(np.array(solution))

View file

@ -2,7 +2,6 @@ import numpy as np
from src.utils import compute_length from src.utils import compute_length
def step2opt(solution, matrix_dist, distance): def step2opt(solution, matrix_dist, distance):
seq_length = len(solution) - 1 seq_length = len(solution) - 1
tsp_sequence = np.array(solution) tsp_sequence = np.array(solution)
@ -26,7 +25,7 @@ def swap2opt(tsp_sequence, i, j):
def gain(i, j, tsp_sequence, matrix_dist): def gain(i, j, tsp_sequence, matrix_dist):
old_link_len = (matrix_dist[tsp_sequence[i], tsp_sequence[i - 1]] + matrix_dist[ old_link_len = (matrix_dist[tsp_sequence[i], tsp_sequence[i - 1]] + matrix_dist[
tsp_sequence[j], tsp_sequence[j + 1]]) tsp_sequence[j], tsp_sequence[j + 1]])x
changed_links_len = (matrix_dist[tsp_sequence[j], tsp_sequence[i - 1]] + matrix_dist[ changed_links_len = (matrix_dist[tsp_sequence[j], tsp_sequence[i - 1]] + matrix_dist[
tsp_sequence[i], tsp_sequence[j + 1]]) tsp_sequence[i], tsp_sequence[j + 1]])
return - old_link_len + changed_links_len return - old_link_len + changed_links_len