#!/usr/bin/env python
# coding: utf-8
# # The Traveling Baseball Fan Problem
# Model formulation
#
# $$
# \begin{array}{rrcll}
# \text{minimize:} & \text{Total Time} \\
# \text{subject to:} & \text{Balance} \\
# & \text{Visit all stadiums once}
# \end{array}
# $$
#
# $$
# \begin{array}{rlcll}
# \textrm{minimize:} & \sum_{(g_1, g_2) \in \text{ARCS}} c[g_1,g_2] \cdot u[g_1,g_2] \\
# \textrm{subject to:} & \sum_{(g,g_2) \in \text{ARCS}} u[g,g_2] - \sum_{(g_1,g) \in \text{ARCS}} u[g_1,g] &= & \begin{cases} 1 & \text{if } g = \text{source,} \\ -1 & \text{if } g = \text{sink,} \\ 0 & \text{otherwise}\end{cases} & & \forall g \in \text{NODES} \\
# & \sum_{(g1,g2) \in \text{ARCS}: g_2 \not = \text{sink and } l[g_2] = s} u[g_1, g_2] & = & 1 & & \forall s \in \text{STADIUMS}
# \end{array}
# $$
# # Solutions
# In[1]:
# Import packages
import os
import pandas as pd
import folium
from bokeh.models.callbacks import CustomJS
from bokeh.io import output_notebook
from bokeh.layouts import column, row
from bokeh.models import HoverTool, ColumnDataSource, TapTool, Div
from bokeh.plotting import figure, show
from dateutil.parser import parse
from IPython.core.display import display, HTML
# In[2]:
# Parse all solutions
solutions = []
for filename in sorted(os.listdir(os.getcwd() + '/results'), reverse=True):
f = open('results/'+filename, 'r')
rowx = {'ref': filename}
for line in f:
if 'schd' in line:
rowx['schd'] = []
for visit in f:
if ']' not in visit:
items = visit.split(',')
items = [i.replace('\n','') for i in items]
rowx['schd'].append(items)
elif ': ' in line:
pl = line.split(': ')
rowx[pl[0]] = pl[1].replace('\n','')
rowx['df'] = pd.DataFrame(rowx['schd'], columns=['ID', 'Venue', 'Away', 'Home', 'City', 'Date', 'Lat', 'Long']).set_index(['ID'])
rowx['df'] = rowx['df'].to_html(columns=['Away', 'Home', 'Venue', 'City', 'Date'])
solutions.append(rowx)
f.close()
# In[3]:
# Generate source for plots and maps
solutions = sorted(solutions, key=lambda x: (round(float(x['mont'])), x['sdat'], x['objt']))
linef = '{:>2} {:>2} {:>11} {:>5} {:>4} {:>13} {:>12} {:>16} {:>12}'
df_source = []
for i, v in enumerate(solutions):
period = v['sdat'][5:] + '/' + v['edat'][5:]
df_source.append([
i+1, v['ref'].split('.')[0], float(v['objt']), period, float(v['mont']), float(v['vars']), float(v['cons']),
float(v['solv'].split()[0]), float(v['time'].split()[0]),
float(v['dist'].split()[0]), float(v['cost'].split()[0]), v['df']
])
# Draw all maps
allhtml = []
for no, i in enumerate(solutions):
mapname = 'maps/{}.html'.format(no+1)
if not os.path.isfile(mapname):
route = i['schd']
tbfmap = folium.Map(location=[39.82, -98.58], zoom_start=4, tiles="OpenStreetMap")
for node in route:
popup_text = '''
Game {}: {} @ {}
{}, {}
{}
'''.format(node[0], node[2], node[3], node[1], node[4],
parse(node[5]).strftime("%A, %B %d, %Y - %I:%M %p"))
folium.Marker(location=[float(node[6]), float(node[7])],popup=popup_text,
#icon=folium.Icon(icon='adjust', prefix='fa')
icon=folium.DivIcon(html='{}'.format(node[0]))
).add_to(tbfmap)
lines = folium.PolyLine(locations=[(float(i[6]), float(i[7])) for i in route])
lines.add_to(tbfmap)
tbfmap.save(mapname)
allhtml.append(''.format(mapname))
maps=ColumnDataSource(data=dict(map=allhtml))
# ## Solution Table
# In[4]:
# Prepare and print plot data
df = pd.DataFrame(
df_source,
columns=[
'id', 'ref', 'objt', 'period', 'mont', 'vars', 'cons', 'solv',
'time', 'dist', 'cost', 'html'
]).set_index(['id'])
axis_map = {
"Tour Length": 'tour', "Tour Distance": 'dist', "Tour Cost": 'cost', "Period Length": 'mont'
}
df2=df.rename(columns = {'ref': 'Reference', 'objt':'Obj. Type', 'period': 'Period', 'mont': 'P.Length', 'vars': '# Variables', 'cons': '# Constraints',
'solv': 'Solve Time (secs)', 'time': 'Tour Time (days)', 'dist': 'Tour Distance (miles)', 'cost': 'Tour Cost ($)'})
display(HTML(df2.to_html(columns=['Period', '# Variables', '# Constraints', 'Solve Time (secs)', 'Tour Time (days)', 'Tour Distance (miles)', 'Tour Cost ($)'],index_names=False)))
# In[5]:
# Generate plots and set callbacks
callback = CustomJS(code="""
console.log('Tap event occured at x-position: ' + cb_obj.x + ',' + cb_obj.y)
""")
output_notebook()
def add_plots(dfv=11):
source=ColumnDataSource(df)
divtext = '