Kaggle competition: Traveling Santa 2018 - Prime Paths
<SOS> metric: TravelingSanta2 Kaggle data source: traveling-santa-2018-prime-paths<train_model>
pd.options.display.float_format = '{:.6f}'.format
learn.fit_one_cycle(6, max_lr=slice(1e-6,1e-3))<set_options>
def read_cities(filename='.. /input/traveling-santa-2018-prime-paths/cities.csv'):
return pd.read_csv(filename, index_col=['CityId'])
 class Tour:
cities = read_cities()
coords =(cities.X + 1j * cities.Y ).values
penalized = ~cities.index.isin(sympy.primerange(0, len(cities)))
 def __init__(self, data):

 if type(data)is str:
data = self._read(data)
 elif type(data)is not np.ndarray or data.dtype != np.int32:
data = np.array(data, dtype=np.int32)
 self.data = data
if len(data)!= len(self.cities)+ 1:
raise Exception('Bad length')
 if data[0] != 0 or data[-1] != 0:
raise Exception('Must start/end with 0');
try:
x = np.zeros(len(data)- 1, dtype=np.bool)
 x[data[1:]] = 1
if np.min(x)== 0:
raise Exception('Repeated/missing cities')
 except IndexError:
raise Exception('Indexes out of bounds')
 @classmethod
def _read(cls, filename):
data = open(filename, 'r' ).read()
if data.startswith('Path'):
return pd.read_csv(io.StringIO(data)).Path.values
offs = data.find('TOUR_SECTION
')
 if offs != -1:
data = np.fromstring(data[offs+13:], sep='
', dtype=np.int32)
 data[-1] = 1
return data - 1
else:
data = data.replace('
', ' ')
 data = np.fromstring(data, sep=' ', dtype=np.int32)
 if len(data)!= data[0] + 1:
raise Exception('Unrecognized format in %s' % filename)
 return np.concatenate(( data[1:], [0]))
def info(self):
dist = np.abs(np.diff(self.coords[self.data]))
penalty = 0.1 * np.sum(dist[9::10] * self.penalized[self.data[9:-1:10]])
 dist = np.sum(dist)
 return { 'score': dist + penalty, 'dist': dist, 'penalty': penalty }
def dist(self):
return self.info() ['dist']
def score(self):
return self.info() ['score']
def __repr__(self):
return 'Tour: %s' % str(self.info())
 def to_csv(self, filename):
pd.DataFrame({'Path': self.data} ).to_csv(filename, index=False)
 def reversed(self):
return Tour(self.data[::-1])
 def roll(self, k):
return Tour(np.concatenate(( [0], np.roll(self.data[1:-1], k), [0])))
 def plot(self, cmap=mpl.cm.gist_rainbow, figsize=(25, 20)) :
fig, ax = plt.subplots(figsize=figsize)
 n = len(self.data)
 for i in range(201):
ind = self.data[n//200*i:min(n, n//200*(i+1)+1)]
ax.plot(self.cities.X[ind], self.cities.Y[ind], color=cmap(i/200.0), linewidth=1)
 ax.plot(self.cities.X[0], self.cities.Y[0], marker='*', markersize=15, markerfacecolor='k')
 ax.autoscale(tight=True)
 mpl.colorbar.ColorbarBase(ax=fig.add_axes([0.125, 0.075, 0.775, 0.01]),
norm=mpl.colors.Normalize(vmin=0, vmax=n),
cmap=cmap, orientation='horizontal' )
learn.export()
learn.save('stage-2' )<find_best_params>
filename = '.. /input/lkh-solver/submission.csv'
Tour(filename )
interp = ClassificationInterpretation.from_learner(learn)
 losses,idxs = interp.top_losses()
len(data.valid_ds)==len(losses)==len(idxs )<predict_on_test>
tour = Tour(filename)
 print('Original: %.2f' % tour.score())
 print('reversed: %.2f' % tour.reversed().score())
 print('roll(6): %.2f' % tour.roll(6 ).score())
 print('------------')
 print('Improvement: %.2f' %(tour.score() - tour.roll(6 ).score()))
tour = tour.roll(6 )
<import_modules><EOS> 
tour.to_csv('submission.csv')
 tour.plot()