def testPathLoad(tmp_path): file_path = tmp_path / "test_dataset.tsv" file_path.write_text("1.0 0.0\n1.1 0.1\n3.0 3.1") p = Path() with file_path.open() as f: p.load(f) assert p.get_vertices() == [(1.0, 0.0), (1.1, 0.1), (3.0, 3.1)]
def testPathGetCycleLength_with_permutation(): assert Path([(1, 1)]).get_cycle_length([0]) == 0 assert Path([(1, 1), (2, 1)]).get_cycle_length([1, 0]) == 2 assert Path([(2, 1), (1, 1), (2, 2)]).get_cycle_length([1, 0, 2])\ == approx(3.41, 0.01) assert Path([(2, 2), (1, 2), (1, 1), (2, 1)], ).get_cycle_length([2, 3, 0, 1]) == 4 assert Path([(1, 1), (2, 2), (2, 3), (1, 3)], ).get_cycle_length([0, 1, 2, 3]) == approx(5.41, 0.01)
def plot(self, path: Path): """Plots path""" vertices = path.get_vertices() if len(vertices) > 1: vertices.append(vertices[0]) x, y = zip(*vertices) plt.plot(x, y)
def testSolve(): original_vertices = [(1, 1), (1, 2), (0, 0), (0, 3)] path = Path(original_vertices) solver = EvolutionarySolver(path, population_size=10, ngen=10) solution = solver.solve() solution_vertices = solution.get_vertices() assert len(solution_vertices) == len(original_vertices) assert set(solution_vertices) == set(original_vertices)
def solve(self) -> Path: """Solves TSP with random approach Generates solution by choosing best path from population of random paths. The population size is given by population attribute. Returns: Result path. """ vertices = self.path.get_vertices() vertices_len = len(vertices) return min([Path(sample(vertices, vertices_len)) for _ in range(self.population)], key=lambda x: x.get_cycle_length())
def testPathGetCycleLength_without_permutation(): assert Path([]).get_cycle_length() == 0 assert Path([(1, 1)]).get_cycle_length() == 0 assert Path([(1, 1), (2, 1)]).get_cycle_length() == 2 assert Path([(1, 1), (2, 1), (2, 2)]).get_cycle_length()\ == approx(3.41, 0.01) assert Path([(1, 1), (2, 1), (2, 2), (1, 2)]).get_cycle_length() == 4 assert Path([(1, 1), (2, 2), (2, 3), (1, 3)]).get_cycle_length()\ == approx(5.41, 0.01)
def main(): parser = argparse.ArgumentParser( description='Travelling Salesman Problem solver using (Mu+Lambda)\ Evolutionary Algorithm') parser.add_argument('--file', '-f', help='input file path', type=argparse.FileType('r')) parser.add_argument('--vertices', '-vert', help='number of vertices to be genarated \ if no input file is used', type=int, default=78) parser.add_argument('--fast', help='use smaller population to shorten computation', action='store_true') parser.add_argument('--generations', '-gen', help='number of generations', type=int, default=500) parser.add_argument('--verbose', '-v', help='increase output verbosity', action='store_true') args = parser.parse_args() if args.file is not None: path = Path() print("Loading vertices from file:", args.file.name, '...') path.load(args.file) else: print("Generating random vertices...") path = RandomPath(args.vertices) print('Number of vertices:', path.get_number_of_vertices()) print('Length of input path:', path.get_cycle_length()) if args.fast: print('Using smaller population for faster computation.') solver = EvolutionarySolver(path, population_size=100, mu=100, lambda_=300, ngen=args.generations, verbose=args.verbose) else: solver = EvolutionarySolver(path, ngen=args.generations, verbose=args.verbose) print('Solving TSP...', end='\n' if args.verbose else ' ') sys.stdout.flush() path = solver.solve() print('done.') print('Evolutionary solved length:', path.get_cycle_length()) print('Plotting solution...') plotter = PathPlotter() plotter.plot(path) plotter.show() print('Bye.') return 0
def testPathGetVertices(): V = [(1, 2), (2, 3)] p = Path(V) assert p.get_vertices() == V
def testPathPermute(): p = Path([(0, 0), (1, 1), (2, 2), (3, 3)]) p.permute([1, 3, 2, 0]) assert p.get_vertices() == [(1, 1), (3, 3), (2, 2), (0, 0)] p.permute([3, 0, 2, 1]) assert p.get_vertices() == [(0, 0), (1, 1), (2, 2), (3, 3)]
def testPathDistance(): assert Path._distance((1, 1), (1, 2)) == 1 assert Path._distance((1, 2), (1, 1)) == 1 assert Path._distance((1, 1), (2, 1)) == 1 assert Path._distance((2, 1), (1, 1)) == 1 assert Path._distance((1, 1), (2, 2)) == approx(1.41, 0.01)
def testPathGetNumberOfVertices_not_empty(): V = [(i, i) for i in range(13)] p = Path(V) assert p.get_number_of_vertices() == 13
def testPathGetNumberOfVertices_empty(): p = Path([]) assert p.get_number_of_vertices() == 0