In [13]:
from itertools import permutations
import pprint
from geopy.distance import vincenty
from random import randint
from copy import deepcopy
from datetime import date, timedelta
pp = pprint.PrettyPrinter(indent=4)
dataset = {
"cities": {
"ATL": {
"name": "Atlanta",
"location": (33.7550, 84.3900)
},
"BOS": {
"name": "Boston",
"location": (42.3601, 71.0589)
},
"CHI": {
"name": "Chicago",
"location": (41.8369, 87.6847)
},
"PIT": {
"name": "Pittsburgh",
"location": (40.4397, 79.9764)
}
},
"flights":[]
}
cities = dataset["cities"]
flights = dataset["flights"]
base_date = date.today()
def get_price(distance):
base_price = int(distance.miles / 5)
float_price = int(base_price / 3)
return base_price + randint(-float_price, float_price)
# Generte random flight data with price based on location and random
for begin, end in permutations(cities, 2):
for day in range(20):
cur = {"origin": begin, "destination": end}
cur["distance"] = vincenty(cities[begin]["location"], cities[end]["location"])
cur["date"] = base_date + timedelta(days=day)
cur["price"] = get_price(cur["distance"])
flights.append(cur)
def get_flight(origin, destination, days):
desired_date = base_date + timedelta(days=days)
for flight in flights:
if flight["origin"] == origin and flight["destination"] == destination and flight["date"] == desired_date:
return flight
In [14]:
min_price = 2 ** 30
final_sequence = []
min_day = 2
max_total_day = 18
# (current_city, current_day, current_price)
initial_state = ("ATL", 0, 0)
city_sequence = [("ATL", 0, 0)]
visited = {city: False for city in dataset["cities"]}
visited["ATL"] = True
def search(state):
global min_price, final_sequence
current_city, current_day, current_price = state
unvisited = [city for city in visited if visited[city] == False]
if not unvisited: # no city left
for days in range(current_day + min_day, max_total_day):
flight = get_flight(current_city, "ATL", days)
final_price = current_price + flight["price"]
city_sequence.append(("ATL", days, final_price))
if final_price < min_price:
min_price = final_price
final_sequence = deepcopy(city_sequence)
city_sequence.pop()
for city in unvisited:
for days in range(current_day + min_day, max_total_day):
flight = get_flight(current_city, city, days)
next_state = (city, days, current_price + flight["price"])
city_sequence.append(next_state)
visited[city] = True
search(next_state)
visited[city] = False
city_sequence.pop()
search(initial_state)
In [15]:
print("Generated Sequence:")
for index, step in enumerate(final_sequence):
print("Step %d: At %s, Day %02d, Total Price $%03d" % (index, step[0], step[1], step[2]))