{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom joblib import Parallel, delayed","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#mapping from site_floor to grids\nsite_floor_grids_map = pd.read_pickle('/kaggle/input/discrete-optimization-of-2nd-place-solution/exp346_site_floor_map_test.pkl')\n\n#submission after iterative snap to corridor and akio cost minimization\nsub = pd.read_csv('/kaggle/input/discrete-optimization-of-2nd-place-solution/exp328_check.csv')\nsub_split = pd.DataFrame()\nsub_split['timestamp'] = [int(el.split('_')[-1]) for el in sub['site_path_timestamp']]\nsub_split['site'] = [el.split('_')[0] for el in sub['site_path_timestamp']]\nsub_split['path'] = [el.split('_')[1] for el in sub['site_path_timestamp']]\nsub_split['site_floor'] = (sub_split['site'] + '_').str.cat(sub['floor'].astype('str'))\nsplit_idx = (np.where(sub_split['path'].values != np.append(sub_split['path'].values[1:], 0))[0] + 1)[:-1]\nsubtes_site_floors = np.split(sub_split['site_floor'].values, split_idx)\nsubtes_site_floors = [el[0] for el in subtes_site_floors]\n\nlen_subs = sub_split.groupby('path', sort = False).size().values\n\n#ensembled delta prediction \ndelta = pd.read_pickle('/kaggle/input/discrete-optimization-of-2nd-place-solution/test_exp338_ensemble_delta_df.pkl')\nsplit_pred = np.split(sub[['x', 'y']].values, split_idx)\nsplit_delta = np.split(delta[['pred_delta_x', 'pred_delta_y']].values, np.cumsum(len_subs - 1)[:-1])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_optim_grids(pred_, delta_, site_floor, site_floor_grids_map, alpha = 1, \\\n                    beta_1 = 9, beta_2 = 56, gamma = 27, zeta = 0, kappa = 0, tau = 4, n_window = 7, n_closest = 8):\n    if np.isnan(pred_).sum() != 0:\n        return pred_\n    pred = np.flipud(pred_)\n    delta = -np.flipud(delta_)\n    diff = pred[:, None, :] - site_floor_grids_map[site_floor][0][None, :, :2]\n    dist = np.sqrt(diff[:, :, 0] ** 2 + diff[:, :, 1] ** 2)\n    closest_idx = np.argsort(dist, axis = 1)[:, :n_closest]\n    closest_dist = np.sort(dist, axis = 1)[:, :n_closest]\n    closest_grids = site_floor_grids_map[site_floor][0][closest_idx]\n    closest_freq = closest_grids[:, :, 2].copy()\n    closest_grids = closest_grids[:, :, :2]\n    closest_grids = np.concatenate((closest_grids, pred[:, None, :]), axis = 1)\n    closest_freq = np.concatenate((closest_freq, np.full((closest_freq.shape[0], 1), 0)), axis = 1)\n    closest_dist = np.concatenate((closest_dist, np.full((closest_dist.shape[0], 1), gamma)), axis = 1)\n    closest_idx = np.concatenate((closest_idx, np.full_like(closest_idx[:, :1], -1)), axis = 1)\n    traj_mat = site_floor_grids_map[site_floor][1]\n\n    answer_indices = np.full(pred.shape[0], 9999)\n    for i in range(0, pred.shape[0], n_window):\n        if i == 0:\n            spc_pred = pred[i: i + n_window]\n            spc_delta = delta[i: i + n_window - 1]\n            spc_closest_idx = closest_idx[i : i + n_window]\n            spc_closest_dist = closest_dist[i : i + n_window]\n            spc_closest_freq = closest_freq[i : i + n_window]\n            spc_closest_grids = closest_grids[i : i + n_window].transpose(2, 0, 1)\n        elif i > 0:\n            spc_pred = pred[i - 1: i + n_window]\n            spc_delta = delta[i - 1: i + n_window - 1]\n            spc_closest_idx = closest_idx[i - 1 : i + n_window]\n            spc_closest_dist = closest_dist[i - 1 : i + n_window]\n            spc_closest_freq = closest_freq[i - 1 : i + n_window]\n            spc_closest_grids = closest_grids[i - 1 : i + n_window].transpose(2, 0, 1)\n        expand_dist = [np.expand_dims(spc_closest_dist[j], axis = [i for i in range(spc_pred.shape[0]) if i != j]) for j in range(spc_pred.shape[0])]\n        sum_abs_loss = np.sum(expand_dist)\n        expand_freq = [np.expand_dims(spc_closest_freq[j], axis = [i for i in range(spc_pred.shape[0]) if i != j]) \\\n                           for j in range(spc_pred.shape[0])]\n        sum_freq_loss = np.sum(expand_freq)\n\n        expand_grid = [np.expand_dims(spc_closest_grids[:, j], axis = [i + 1 for i in range(spc_pred.shape[0]) if i != j]) \\\n                       for j in range(spc_pred.shape[0])]\n        expand_losses_dist = []\n        expand_losses_angle = []\n        expand_traj_losses = []\n        expand_zerodelta_losses = []\n        for j in range(spc_pred.shape[0] - 1):\n            expand_delta = np.expand_dims(spc_delta[j], axis = [i + 1 for i in range(spc_pred.shape[0])])\n            d1 = ((expand_grid[j + 1] - expand_grid[j])**2).sum(axis = 0)**0.5\n            expand_zerodelta_losses.append((d1 == 0).astype('float'))\n            d2 = (expand_delta**2).sum(axis = 0)**0.5\n            expand_loss_dist = np.abs(d1 - d2)\n            expand_loss_angle = np.arctan2(expand_grid[j + 1][1] - expand_grid[j][1],\n                                           expand_grid[j + 1][0] - expand_grid[j][0]) - \\\n                                np.arctan2(expand_delta[1], expand_delta[0])\n            expand_loss_angle = ((expand_loss_angle + 3*np.pi) % (2*np.pi) - np.pi)**2\n            expand_loss_angle *= np.tanh((d1 + d2) / 2)\n            expand_losses_dist.append(expand_loss_dist)\n            expand_losses_angle.append(expand_loss_angle)\n            stacked = np.stack([np.repeat(spc_closest_idx[j][:, None], (spc_closest_idx.shape[1]), 1), \n                              np.repeat(spc_closest_idx[j + 1][:, None], (spc_closest_idx.shape[1]), 1).T]).reshape(2, -1)\n            expand_traj_loss = np.expand_dims(traj_mat[stacked[0], stacked[1]].reshape(spc_closest_idx.shape[1], spc_closest_idx.shape[1]), \n               axis = list(np.delete([i for i in range(spc_pred.shape[0])], np.array([j, j + 1]))))\n            expand_traj_losses.append(expand_traj_loss)\n        if len(expand_losses_dist) > 1:\n            sum_delta_dist_loss = np.sum(expand_losses_dist)\n            sum_delta_angle_loss = np.sum(expand_losses_angle)**0.5\n            sum_traj_loss = np.sum(expand_traj_losses)\n            sum_zerodelta_loss = np.sum(expand_zerodelta_losses)\n        elif len(expand_losses_dist) == 1:\n            sum_delta_dist_loss = expand_losses_dist[0]\n            sum_delta_angle_loss = expand_losses_angle[0]**0.5\n            sum_traj_loss = expand_traj_losses[0]\n            sum_zerodelta_loss = expand_zerodelta_losses[0]\n        else:\n            assert(False)\n        sum_loss = alpha * sum_abs_loss + beta_1 * sum_delta_dist_loss \\\n        + beta_2 * sum_delta_angle_loss + kappa * sum_traj_loss + tau * sum_zerodelta_loss\n        if i > 0:\n            sum_loss = sum_loss + np.expand_dims(last_answer_loss, axis = [i for i in range(1, sum_loss.ndim)])\n        answer_index = np.array(np.unravel_index(np.argmin(sum_loss), sum_loss.shape))\n        if i == 0:\n            answer_indices[i: i + n_window] = answer_index\n        elif i > 0:\n            answer_indices[i - 1: i + n_window] = answer_index\n        last_answer_loss = sum_loss[answer_index[0]]\n        for idx in answer_index[1:-1]:\n            last_answer_loss = last_answer_loss[idx]\n    optim_grids = closest_grids[np.arange(closest_grids.shape[0]), answer_indices]\n    return np.flipud(optim_grids)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"r_optim_grids = Parallel(n_jobs=-1, verbose = 1, backend = 'multiprocessing')\\\n( [delayed(get_optim_grids)(pred, delta, site_floor, site_floor_grids_map) \\\n   for (pred, delta, site_floor) in zip(split_pred, split_delta, subtes_site_floors)] ) \noptim_grids = np.concatenate(r_optim_grids)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub['x'] = optim_grids[:, 0]\nsub['y'] = optim_grids[:, 1]\nsub_fn = 'exp346_submission.csv'\nsub.to_csv(sub_fn, index = False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}