-
Notifications
You must be signed in to change notification settings - Fork 0
/
tsp.c
147 lines (139 loc) · 5.44 KB
/
tsp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
Created by: Carbonell-Kiamtia, Maxim
mjcarbon
May 2nd, 2021
Assignment 4: Navigations of Denver Long
CSE 13S, Computer Systems and C Programming
UC Santa Cruz, Spring 2021
Description: This directory is for the purposes of finding the shortest hamiltonian path given a set of vertices and edges connecting them. It will handle an error if not given the proper format of veritces, edges, and names.
*/
#include "tsp.h"
#include "graph.h"
#include "path.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define OPTIONS "hvui:o:"
#define BLOCK 4096
bool vPrint = false;
uint32_t temp = 0;
uint32_t rounds = 0;
uint32_t calls = 0;
uint32_t lastLength = 0;
void DFS(Graph *G, uint32_t v, Path *curr, Path *shortest, char *cities[],
FILE *outfile) { // DFS is a recursive function that finds all possible hamiltonian paths.
graph_mark_visited(G, v); // Begin by marking the vertex as visited
uint32_t amountVertices = graph_vertices(G);
for (uint32_t i = 0; i < (amountVertices); ++i) { // Iterate through all possible paths
if ((graph_visited(G, i)
== false)) { // If we have not visited it and it has an edge connecting the two vertices then we must push it to the path and call DFS to find all possible options from our new vertex.
if (graph_has_edge(G, v, i)) {
path_push_vertex(curr, i, G);
calls += 1;
DFS(G, i, curr, shortest, cities, outfile);
}
}
if ((path_vertices(curr))
== (amountVertices
- 1)) { // If our path's length is one short of all the vertices that exist then that means we have found a hamiltonian path since we did not pass the origin onto the path
path_push_vertex(curr, 0, G);
if (rounds == 0) {
path_copy(shortest, curr);
lastLength = path_length(curr);
}
if (vPrint == true) { // If verbose printing is on print all paths
if (rounds == 0) {
fprintf(stdout, "Path length: %d\n", path_length(curr));
path_print(curr, stdout, cities);
} else {
if (path_length(curr) < lastLength) {
fprintf(stdout, "Path length: %d\n", path_length(curr));
path_print(curr, stdout, cities);
lastLength = path_length(curr);
}
}
}
if (path_length(curr)
< path_length(shortest)) { // Logic to copy the track the shortest Path we take
path_copy(shortest, curr);
}
path_pop_vertex(curr, &temp, G);
rounds += 1;
}
}
graph_mark_unvisited(G,
v); // We perform this when we have already tried all of our options and none succeeded. Eventually all vertices will come to this point anyway.
path_pop_vertex(curr, &v, G);
}
int main(int argc, char **argv) {
int i, j, k, c;
char buffer[BLOCK];
char *names[53];
int numVertices = 1;
bool unDir = false;
char *newFile = malloc(256);
char *newFileOut = malloc(256);
for (int i = 0; i < argc; i++) { // Handles arguments
if (strcmp(argv[i], "-h") == 0) {
fprintf(stdout, "SYNOPSIS\n");
fprintf(stdout, " Travelling Salesman Problem using DFS.\n\n");
fprintf(stdout, "USAGE\n");
fprintf(stdout, " ./tsp [-u] [-v] [-h] [-i infile] [-o outfile]\n");
fprintf(stdout, "OPTIONS\n");
fprintf(stdout, " -u Use undirected graph.\n");
fprintf(stdout, " -v Enable verbose printing.\n");
fprintf(stdout, " -h program usage and help.\n");
fprintf(stdout, " -i infile Input containing graph (default: stdin)\n");
fprintf(stdout, " -o outfile Output of computed path (default: stdout)\n");
}
if (strcmp(argv[i], "-u") == 0) {
unDir = true;
}
if (strcmp(argv[i], "-i") == 0) {
strcpy(newFile, argv[i + 1]);
freopen(newFile, "r", stdin);
}
if (strcmp(argv[i], "-o") == 0) {
strcpy(newFileOut, argv[i + 1]);
freopen(newFileOut, "w", stdout);
}
if (strcmp(argv[i], "-v") == 0) {
vPrint = true;
}
}
for (int i = 0; i < (numVertices + 1); ++i) { // Reading input
fgets(buffer, BLOCK, stdin);
if (i == 0) {
numVertices = atoi(buffer);
if (numVertices > 26) {
exit(1);
}
} else {
names[i - 1] = strdup(buffer);
strtok(names[i - 1], "\n");
}
}
Graph *graph = graph_create(numVertices, unDir); // Creating graph
Path *currentPath = path_create();
Path *shortestPath = path_create();
while ((c = fscanf(stdin, "%d %d %d\n", &i, &j, &k)) != EOF) {
if (c != 3) {
printf("Error: malformed edge.\n");
exit(1);
break;
}
graph_add_edge(graph, i, j, k);
}
// CREATING GRAPH
//graph_print(graph);
DFS(graph, 0, currentPath, shortestPath, names, stdout); // Calling DFS
if (vPrint == false) {
fprintf(stdout, "Path length: %d\n", path_length(shortestPath));
path_print(shortestPath, stdout, names);
}
fprintf(stdout, "Total recursive calls: %d\n", (calls + 1));
return 0;
}