From 96e59ae0ffbe8c61baceddf733b5682a6726bf70 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 14 Feb 2025 20:51:19 +0000 Subject: [PATCH] [CT421]: Assignment 1 initialisation code --- .../assignments/assignment1/code/salesman.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 year4/semester2/CT421/assignments/assignment1/code/salesman.py diff --git a/year4/semester2/CT421/assignments/assignment1/code/salesman.py b/year4/semester2/CT421/assignments/assignment1/code/salesman.py new file mode 100755 index 00000000..253ba031 --- /dev/null +++ b/year4/semester2/CT421/assignments/assignment1/code/salesman.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 + +import argparse +import re +import math + +# function to read a TSP file in and construct a dictionary of its attributes +def graph_from_file(input_file): + graph = {} + + print("Reading cities data from: " + input_file) + + with open(input_file, "r") as file: + lines=file.readlines() + + # assuming that the data will be available on specific line numbers and that fields must be included, which works for the provided datasets. + # i would implement this in a better way if python didn't have such a terrible regex engine compared to perl (further evidence of why perl is the best and python sucks) + graph["name"] = lines[0].split()[1] + graph["type"] = lines[1].split()[1] + graph["comment"] = lines[2][lines[2].find(" ") + 1:] + graph["dimension"] = lines[3].split()[1] + graph["edge_weight_type"] = lines[4].split()[1] + + cities = [] + for line_number in range(6, len(lines)): + if lines[line_number] == "EOF\n": + break + + fields = lines[line_number].split() + cities.append({"name": int(fields[0]), "x": float(fields[1]), "y": float(fields[2]) }) + + graph["cities"] = cities + + return graph + +# function to generate an adjacency matrix from a graph +def adjacency_matrix_from_graph(graph): + matrix = [] + cities = sorted(graph["cities"], key=lambda city: city["name"]) # sorting list of cities in case not sorted, assuming each city's name is an int + + # iterating over sorted list of cities + for city in cities: + distances = [] + + for other_city in cities: + distances.append(dist(city, other_city)) + + matrix.append(distances) + + return matrix + +# function to calculate the euclidean distance between two cities +def dist(city1, city2): + return math.sqrt( (city2["x"] - city1["x"] )**2 + ( city2["y"] - city1["y"] )**2 ) + + +def main(): + parser = argparse.ArgumentParser(description="Program to solve the travelling salesman problem for a given TSP file using a genetic algorithm.") + parser.add_argument("-i", "--input-file", type=str, help="Path to input file in TSP format", required=True) + args=parser.parse_args() + + input_file=args.input_file + + graph = graph_from_file(input_file) + adjacency_matrix = adjacency_matrix_from_graph(graph) + + for row in adjacency_matrix: + print(row) + + +if __name__ == "__main__": + main()