├── README.md └── demo.py /README.md: -------------------------------------------------------------------------------- 1 | # p_vs_np_challenge 2 | P vs NP Challenge by @Sirajology on [Youtube](https://youtu.be/9MvbNPQiEE8) 3 | 4 | 5 | 6 | Overview 7 | ============ 8 | This is the code for 'Why is P vs NP Important?' by @Sirajology on [Youtube](https://youtu.be/9MvbNPQiEE8). In this demo code, I go over a brute force approach to the Traveling Salesman Problem. The [TSP](https://developers.google.com/optimization/routing/tsp) problem states that given a list of cities, what's the shortest possible route a traveling salesman could take to visit all of them and return back to his home city? The way the demo code solves this is to try every possible path. Since the number of cities is low, this works. But if we added more cities, this would quickly get really computationally expensive. 9 | 10 | Dependencies 11 | ============ 12 | 13 | None! Just good old Python 3. 14 | 15 | Usage 16 | =========== 17 | 18 | To run the demo code just run the following in terminal 19 | 20 | ``python demo.py`` 21 | 22 | 23 | Challenge 24 | =========== 25 | 26 | The challenge for this video is to add a function to the demo code that gives a best estimate for the shortest route. Instead of trying every possible path, use another strategy to estimate the shortest route. Some examples of possible strategies you could use are Random path, Greedy, 2-Opt, or Simulated Annealing. 27 | 28 | Credits 29 | =========== 30 | Credit for the vast majority of code here goes to [westphal](https://github.com/westphal). I've merely created a wrapper around all of the important functions to get people started. 31 | 32 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | routes = [] 2 | 3 | def find_paths(node, cities, path, distance): 4 | # Add way point 5 | path.append(node) 6 | 7 | # Calculate path length from current to last node 8 | if len(path) > 1: 9 | distance += cities[path[-2]][node] 10 | 11 | # If path contains all cities and is not a dead end, 12 | # add path from last to first city and return. 13 | if (len(cities) == len(path)) and (path[0] in cities[path[-1]]): 14 | global routes 15 | path.append(path[0]) 16 | distance += cities[path[-2]][path[0]] 17 | print(path, distance) 18 | routes.append([distance, path]) 19 | return 20 | 21 | # Fork paths for all possible cities not yet used 22 | for city in cities: 23 | if (city not in path) and (node in cities[city]): 24 | find_paths(city, dict(cities), list(path), distance) 25 | 26 | #CHALLENGE -- write your own strategy to estimate the shortest route 27 | #def find_paths_estimate(node, cities, path, distance): 28 | 29 | 30 | if __name__ == '__main__': 31 | cities = { 32 | 'RV': {'S': 195, 'UL': 86, 'M': 178, 'BA': 180, 'Z': 91}, 33 | 'UL': {'RV': 86, 'S': 107, 'N': 171, 'M': 123}, 34 | 'M': {'RV': 178, 'UL': 123, 'N': 170}, 35 | 'S': {'RV': 195, 'UL': 107, 'N': 210, 'F': 210, 'MA': 135, 'KA': 64}, 36 | 'N': {'S': 210, 'UL': 171, 'M': 170, 'MA': 230, 'F': 230}, 37 | 'F': {'N': 230, 'S': 210, 'MA': 85}, 38 | 'MA': {'F': 85, 'N': 230, 'S': 135, 'KA': 67}, 39 | 'KA': {'MA': 67, 'S': 64, 'BA': 191}, 40 | 'BA': {'KA': 191, 'RV': 180, 'Z': 85, 'BE': 91}, 41 | 'BE': {'BA': 91, 'Z': 120}, 42 | 'Z': {'BA': 120, 'BE': 85, 'RV': 91} 43 | } 44 | 45 | print("Start: River City") 46 | find_paths('RV', cities, [], 0) 47 | routes.sort() 48 | if len(routes) != 0: 49 | print("Shortest route: %s" % routes[0]) 50 | --------------------------------------------------------------------------------