신호생성 repo (24. 1. 5 ~).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

917 lines
51 KiB

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import os\n",
"import sumolib\n",
"import copy\n",
"import json\n",
"from tqdm import tqdm\n",
"from datetime import datetime"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"m = 105\n",
"midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
"next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
"fmins = range(midnight, next_day, 300)\n",
"\n",
"# 현재시각\n",
"present_time = fmins[m]\n",
"sigtable_start = fmins[m] - 600\n",
"sim_start = fmins[m] - 300\n",
"sim_end = fmins[m]\n",
"\n",
"# network and dataframes\n",
"net = sumolib.net.readNet('../Data/networks/sn.net.xml')\n",
"inter_node = pd.read_csv('../Data/tables/inter_node.csv', index_col=0)\n",
"plan = pd.read_csv('../Data/tables/plan.csv', index_col=0)\n",
"match6 = pd.read_csv('../Intermediates/match6.csv', index_col=0)\n",
"match6 = match6[['node_id', 'phase_no', 'ring_type', 'inc_edge', 'out_edge']].reset_index(drop=True)\n",
"histid = pd.read_csv(f'../Intermediates/histid/histid_{present_time}.csv', index_col=0)\n",
"histid = histid.reset_index(drop=True).drop(columns=['inter_no'])\n",
"\n",
"# helper dictionaries and lists\n",
"inter_node_p = inter_node[inter_node.inter_type=='parent']\n",
"inter2node = dict(zip(inter_node_p['inter_no'], inter_node_p['node_id']))\n",
"node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
"pa2ch = {'i0':['u00'], 'i1':[], 'i2':['u20'], 'i3':['c30', 'u30', 'u31', 'u32'], 'i6':['u60'], 'i7':[], 'i8':[], 'i9':[]}\n",
"node_ids = sorted(inter_node.node_id.unique())\n",
"parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
"nodes = [net.getNode(node_id) for node_id in node_ids]"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def attach_children(histid, match6, parent_ids, pa2ch):\n",
" '''\n",
" 자식교차로에 대한 진입·진출 엣지 정보를 붙여주는 함수\n",
"\n",
" input :\n",
" (1) histid\n",
" - 각 교차로에 대한 (시작유닉스, A현시, B현시)별 현시시간, 진입·진출엣지\n",
" - 부모교차로(주교차로)에 대해서만 값이 지정되어 있음\n",
" (2) match6\n",
" - (현시, 링)별 진입·진출엣지\n",
" - 자식교차로(유턴 및 연동교차로)에 대해서도 값이 지정되어 있음\n",
" (3) parent_ids : 부모교차로 목록\n",
" (4) pa2ch : 각 부모교차로id를 부모교차로가 포함하고 있는 자식교차로들의 id들의 리스트로 대응시키는 딕셔너리\n",
"\n",
" output : histids\n",
" - 모든(부모 및 자식) 교차로에 대한 시작유닉스 (시작유닉스, A현시, B현시)별 현시시간, 진입·진출엣지\n",
" '''\n",
" new_histids = []\n",
" for parent_id in parent_ids:\n",
" for child_id in pa2ch[parent_id]:\n",
" new_histid = histid.copy()[histid.node_id==parent_id]\n",
" new_histid[['inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']] = np.nan\n",
" for i, row in new_histid.iterrows():\n",
" phas_A = row.phas_A\n",
" phas_B = row.phas_B\n",
" new_match = match6[match6.node_id==child_id]\n",
" Arow = new_match[(new_match.phase_no==phas_A) & (new_match.ring_type=='A')]\n",
" if ~ Arow[['inc_edge', 'out_edge']].isna().all().all():\n",
" inc_edge = Arow.iloc[0].inc_edge\n",
" out_edge = Arow.iloc[0].out_edge\n",
" new_histid.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge, out_edge]\n",
" Brow = new_match[(new_match.phase_no==phas_B) & (new_match.ring_type=='B')]\n",
" if ~ Brow[['inc_edge', 'out_edge']].isna().all().all():\n",
" inc_edge = Brow.iloc[0].inc_edge\n",
" out_edge = Brow.iloc[0].out_edge\n",
" new_histid.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge, out_edge]\n",
" new_histid.loc[i, 'node_id'] = child_id\n",
" new_histids.append(new_histid)\n",
" new_histids = pd.concat(new_histids)\n",
" histids = pd.concat([histid.copy(), new_histids])\n",
" histids = histids.sort_values(by=['start_unix', 'node_id', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
" return histids\n",
"histids = attach_children(histid, match6, parent_ids, pa2ch)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def initialize_states(net, nodes, histids):\n",
" '''\n",
" 신호 초기화\n",
"\n",
" input :\n",
" (1) net : 네트워크\n",
" (2) nodes : 노드 목록\n",
" (3) histids : 모든 교차로에 대한 시작유닉스 (시작유닉스, A현시, B현시)별 현시시간, 진입·진출엣지\n",
"\n",
" output : node2init\n",
" - 각 노드를 초기화된 신호로 맵핑하는 딕셔너리\n",
" - 초기화된 신호란, 우회전을 g로 나머지는 r로 지정한 신호를 말함.\n",
" '''\n",
" node2init = {}\n",
" for node in nodes:\n",
" node_id = node.getID()\n",
" conns = [(c.getJunctionIndex(), c) for c in node.getConnections()]\n",
" conns = [c for c in conns if c[0] >= 0]\n",
" conns = sorted(conns, key=lambda x: x[0])\n",
" state = []\n",
" for i, ci in conns:\n",
" if ci.getTLLinkIndex() < 0:\n",
" continue\n",
" are_foes = False\n",
" for j, cj in conns:\n",
" if ci.getTo() == cj.getTo():\n",
" continue\n",
" if node.areFoes(i, j):\n",
" are_foes = True\n",
" break\n",
" state.append('r' if are_foes else 'g')\n",
" node2init[node_id] = state\n",
"\n",
" # 어떤 연결과도 상충이 일어나지는 않지만, 신호가 부여되어 있는 경우에는 r을 부여\n",
" for _, row in histids.iterrows():\n",
" node_id = row['node_id']\n",
" inc_edge_A = row.inc_edge_A\n",
" inc_edge_B = row.inc_edge_B\n",
" out_edge_A = row.out_edge_A\n",
" out_edge_B = row.out_edge_B\n",
"\n",
" if pd.isna(inc_edge_A) or pd.isna(out_edge_A):\n",
" pass\n",
" else:\n",
" inc_edge_A = net.getEdge(inc_edge_A)\n",
" out_edge_A = net.getEdge(out_edge_A)\n",
" for conn in inc_edge_A.getConnections(out_edge_A):\n",
" index = conn.getTLLinkIndex()\n",
" if index >= 0:\n",
" node2init[node_id][index] = 'r'\n",
"\n",
" if pd.isna(inc_edge_B) or pd.isna(out_edge_B):\n",
" pass\n",
" else:\n",
" inc_edge_B = net.getEdge(inc_edge_B)\n",
" out_edge_B = net.getEdge(out_edge_B)\n",
" for conn in inc_edge_B.getConnections(out_edge_B):\n",
" index = conn.getTLLinkIndex()\n",
" if index >= 0:\n",
" node2init[node_id][index] = 'r'\n",
" return node2init\n",
"node2init = initialize_states(net, nodes, histids)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def assign_signals(histids, node2init, net):\n",
" '''\n",
" 진입·진출엣지를 신호문자열로 배정\n",
"\n",
" input :\n",
" (1) histids : 모든 교차로에 대한 (시작유닉스, A현시, B현시)별 현시시간, 진입·진출엣지\n",
" (2) node2init : 각 노드를 초기화된 신호로 맵핑하는 딕셔너리\n",
" (3) net : 네트워크\n",
"\n",
" output : sigtable\n",
" - 모든 교차로에 대한 (시작유닉스, A현시, B현시)별 현시시간, 신호문자열\n",
" - 황색 및 적색신호는 아직 반영되지 않았음.\n",
" '''\n",
" sigtable = histids.copy()\n",
" sigtable['init_state'] = sigtable['node_id'].map(node2init)\n",
" sigtable['state'] = sigtable['init_state'].map(lambda x:''.join(x))\n",
" for i, row in sigtable.iterrows():\n",
" node_id = row.node_id\n",
" inc_edge_A = row.inc_edge_A\n",
" inc_edge_B = row.inc_edge_B\n",
" out_edge_A = row.out_edge_A\n",
" out_edge_B = row.out_edge_B\n",
" state = copy.deepcopy(node2init)[node_id]\n",
" if pd.isna(inc_edge_A) or pd.isna(out_edge_A):\n",
" pass\n",
" else:\n",
" inc_edge_A = net.getEdge(inc_edge_A)\n",
" out_edge_A = net.getEdge(out_edge_A)\n",
" for conn in inc_edge_A.getConnections(out_edge_A):\n",
" index = conn.getTLLinkIndex()\n",
" if index >= 0:\n",
" state[index] = 'G'\n",
" sigtable.at[i, 'state'] = ''.join(state)\n",
"\n",
" if pd.isna(inc_edge_B) or pd.isna(out_edge_B):\n",
" pass\n",
" else:\n",
" inc_edge_B = net.getEdge(inc_edge_B)\n",
" out_edge_B = net.getEdge(out_edge_B)\n",
" for conn in inc_edge_B.getConnections(out_edge_B):\n",
" index = conn.getTLLinkIndex()\n",
" if index >= 0:\n",
" state[index] = 'G'\n",
" sigtable.at[i, 'state'] = ''.join(state)\n",
" sigtable = sigtable.dropna(subset='state')\n",
" sigtable = sigtable.reset_index(drop=True)\n",
" sigtable['phase_sumo'] = sigtable.groupby(['node_id', 'start_unix']).cumcount()\n",
" # sigtable = sigtable[sigtable.start_unix >= sigtable_start]\n",
" sigtable = sigtable[['node_id', 'start_unix', 'phase_sumo', 'duration', 'state']]\n",
" sigtable = sigtable.sort_values(by=['start_unix', 'node_id'])\n",
" sigtable['start_dt'] = sigtable['start_unix'].apply(lambda x:datetime.fromtimestamp(x))\n",
" return sigtable\n",
"sigtable = assign_signals(histids, node2init, net)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def assign_red_yellow(sigtable):\n",
" '''\n",
" 적색, 황색신호를 반영한 신호문자열 배정\n",
"\n",
" input : sigtable\n",
" - 모든 교차로에 대한 (시작유닉스, A현시, B현시)별 현시시간, 신호문자열\n",
" (1) sigtable : 모든 교차로에 대한 (시작유닉스, A현시, B현시)별 현시시간, 진입·진출엣지\n",
" (2) node2init : 각 노드를 초기화된 신호로 맵핑하는 딕셔너리\n",
" (3) net : 네트워크\n",
"\n",
" output : Sigtable\n",
" - 모든 교차로에 대한 (시작유닉스, A현시, B현시)별 현시시간, (황·적색신호가 포함된) 신호문자열\n",
" '''\n",
" Sigtable = []\n",
" for node_id, group in sigtable.groupby('node_id'):\n",
" new_rows_list = []\n",
" for i in range(1, len(group)):\n",
" prev_row = group.iloc[i-1:i].copy()\n",
" next_row = group.iloc[i:i+1].copy()\n",
" new_rows = pd.concat([prev_row, prev_row, next_row]).reset_index(drop=True)\n",
" new_rows.loc[0, 'phase_sumo'] = str(prev_row.phase_sumo.iloc[0]) + '_g'\n",
" new_rows.loc[0, 'duration'] = new_rows.loc[0, 'duration'] - 5\n",
" new_rows.loc[1, 'phase_sumo'] = str(prev_row.phase_sumo.iloc[0]) + '_y'\n",
" new_rows.loc[1, 'duration'] = 4\n",
" yellow_state = ''\n",
" red_state = ''\n",
" for a, b in zip(prev_row.state.iloc[0], next_row.state.iloc[0]):\n",
" if a == 'G' and b == 'r':\n",
" yellow_state += 'y'\n",
" red_state += 'r'\n",
" else:\n",
" yellow_state += a\n",
" red_state += a\n",
" new_rows.loc[2, 'phase_sumo'] = str(next_row.phase_sumo.iloc[0]) + '__r'\n",
" new_rows.loc[2, 'duration'] = 1\n",
" new_rows.loc[1, 'state'] = yellow_state\n",
" new_rows.loc[2, 'state'] = red_state\n",
" new_rows_list.append(new_rows)\n",
" next_row['phase_sumo'] = str(next_row.phase_sumo.iloc[0]) + '_g'\n",
" next_row['duration'] -= 5\n",
" # next_row.loc['duration'] -= 5\n",
" new_rows_list.append(next_row)\n",
" new_rows = pd.concat(new_rows_list)\n",
" Sigtable.append(new_rows)\n",
" Sigtable = pd.concat(Sigtable).sort_values(by=['node_id', 'start_unix', 'phase_sumo']).reset_index(drop=True)\n",
" return Sigtable\n",
"Sigtable = assign_red_yellow(sigtable)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAiIAAAGvCAYAAABmcr6xAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/OQEPoAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA1jUlEQVR4nO3de3RU5aH+8WeSkEmAZCK3hEBABOQSLOWiFLxX5FKKeDlFaeoJytKfCscLFTFaL9ijgaqoy4MIWoGzarXaA4pUqRdQYIlykSgRRVAEKwRUTCYRDJB5f39gpkzIZSaZmXfv8P2slbWcmXf2ft43Iftxz+yJxxhjBAAAYEGC7QAAAODERREBAADWUEQAAIA1FBEAAGANRQQAAFhDEQEAANZQRAAAgDUUEQAAYE1SvHcYCAS0e/dupaWlyePxxHv3AACgEYwxKi8vV3Z2thISonceI+5FZPfu3crJyYn3bgEAQBR89dVX6ty5c9S2F/cikpaWJunoRNLT0+O9ewBu4/NJZWW2UzQPrCWawO/3KycnJ3gcj5a4F5Hql2PS09MpIgDCw++K6GEt0UTRflsFb1YFAADWUEQAAIA1FBEAAGANRQQAAFhDEQEAANZQRAAAgDUUEQAAYA1FBAAAWBP3DzRrDgKBgHbu3KmKigq1bt1aXbt2jern7kcbeWPPbZnJG1tuyyu5LzN57ewjFiIqIlVVVbr33nv1l7/8RSUlJcrOztbEiRP1hz/84YT5A3ZbtmzR8uXL5ff7g/elp6dr1KhR6tu3r8VktSNv7Lkts9vylrduracefdQ1ed22vpL7MpPXzj5ixWOMMeEOfuCBBzR79mwtWrRIubm52rBhg6666irdf//9uvHGG8Paht/vl8/nU1lZmes+4n3Lli164YUX6nx8/PjxjvqGkzf23JbZjXkTL7lEz02YUOvjTszr6PX1eKQav/Idn7kG8trZhxS743dEZ0TeffddjRs3TmPGjJEknXzyyXruuee0bt26qAVyqkAgoOXLl9c7Zvny5TrllFMccSosEAjotddeq3cMeZvGbZndmvfX9YxxYt762M6b5PHoyKFDwdtuyHws8jZ+H71793bEmtQm4jMi8+fP1+uvv65TTz1VH374oUaMGKHZs2crLy+v1udUVlaqsrIyeLv6r/e57YzIjh07tGjRItsxgBPOhOeeq/OMCCLDWp648vPz1a1btyZtwxFnRG6//Xb5/X717t1biYmJqqqq0v33319nCZGkwsJCzZgxo8lBbauoqLAdAQCARnHyMSyiIvLCCy/o2Wef1V//+lfl5uaqqKhIN998s7Kzs5Wfn1/rcwoKCjR16tTg7eozIm7TunXrsMbl5eWpa9euMU7TsJ07d+rZZ59tcBx5G89tmckbW27Im3TffbrjjjuCt92Q+Vjkbfw+wj2G2RBREZk2bZpuv/12XXHFFZKk0047TTt37lRhYWGdRcTr9crr9TY9qWVdu3ZVenp6yDuSa0pPT1f37t0d8Tpc9+7dyRtjbsvs1rz1cWJeR6+vMUpOTg7edEXmY5C38ftwQjGrS0QzP3DgwHGLlZiYqEAgENVQTpSQkKBRo0bVO2bUqFGO+OGXyBsPbstM3thyW17JfZnJa2cfsRbRm1UnTpyoN998U/PmzVNubq42bdqka6+9VldffbVmzZoV1jbcfPmu5L5rtckbe27L7La85WlpemrGDNfkdfT61nL5ruTwzLUgr519xOr4HVERKS8v11133aUlS5Zo3759ys7O1oQJE3T33XeHnO6rj9uLiOS+T68jb+y5LbOr8no8ClRVuSevHLy+dRQRycGZ60De+O/DEUUkGppDEQEQR/UcPBEh1hJNEKvjt3PrIwAAaPYoIgAAwBqKCAAAsIYiAgAArKGIAAAAaygiAADAGooIAACwhiICAACsoYgAAABrKCIAAMAaiggAALCGIgIAAKyhiAAAAGsoIgAAwBqKCAAAsIYiAgAArKGIAAAAaygiAADAGooIAACwhiICAACsoYgAAABrKCIAAMAaiggAALCGIgIAAKyhiAAAAGsoIgAAwBqKCAAAsIYiAgAArKGIAAAAaygiAADAGooIAACwhiICAACsoYgAAABrKCIAAMAaiggAALCGIgIAAKxJsh0glkzAqHJHmQLlh5SQlixvN588CR7bsepE3thyW17JfZnJG3tuy0ze2HJb3tpEVEROPvlk7dy587j7b7jhBs2ZMydqoaLhYPG3Kn3lc1WVHQrel+hLVsbY7krt185istqRN7bclldyX2byxp7bMpM3ttyWty4eY4wJd/A333yjqqqq4O3i4mJdeOGFWrlypc4777ywtuH3++Xz+VRWVqb09PSIA4fjYPG3+u4vn9T5eNvf9XHUN4m8seW2vJL7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0UUXmc6dO5uioiKzZ8+e4NexVxU4dX4Nfe9qqnnVjDHundvixYtNixYtzPz58822bduClwCuXr06uI3rrrvOdOnSxaxYscJs2LDBDB061AwdOjT4ePWlhiNGjDBFRUVm+fLlpn379nG5fLeh+Z177rkmNzfXrFy50nzxxRdmwYIFJiUlxTzxxBOOnt/1119vfD6fefvtt0P+PR04cCCquasvAZ02bZr55JNPzJw5c+Jy+W5D8ysrKzNDhgwxp512mtm+fXvImCNHjjh6fuF872pSHZfvxmNuJ3wR8fv95qabbjJdunQxKSkp5pRTTjF33nlnyMErEAiYu+66y2RmZhqv12suuOACs3Xr1pDtfPfdd2bChAmmdevWJj093Vx11VWmvLw8rnNZuXKlkXTcV35+flTn8eGHH5qzzjrLeL1e06lTJzNz5kzr89uxY0etj0kyK1eudPz8Gvre1VRbEXHz3P785z+bHj16mJSUFNO/f3/z0ksvhWzj4MGD5oYbbjAnnXSSadmypbnkkkvMnj17QsZ8+eWXZvTo0SY1NdW0a9fO/P73vw9eZmlzfnv27DETJ0402dnZJiUlxfTq1cs8/PDDJhAIOHp+df17WrBgQdRzr1y50vz85z83ycnJ5pRTTgnZh6351fV9lWR27Njh6PmF872r7Tk1Lz2P19w8PwUAAACIuxP+PSIAAMAeiggAALCGIgIAAKyhiAAAAGsoIgAAwBqKCAAAsIYiAgAArKGIAABOePfff7+GDRumli1bHvcXhevi8Xhq/XrwwQeDY/bv36+8vDylp6crIyNDkyZNUkVFRa3b2759u9LS0urd//PPPy+Px6OLL7445P7FixdrxIgRatu2rTweT/Bj2yM1Z84c9enTR6mpqerVq5f+93//t1HbiQRFBABwQjjvvPO0cOHCWh87dOiQfvOb3+j6668Pe3t79uwJ+XrmmWfk8Xh02WWXBcfk5eXp448/1htvvKFly5Zp1apVuvbaa4/b1uHDhzVhwgSdffbZde7vyy+/1K233lrrmB9++EFnnXWWZs2aFXb+mubOnauCggLde++9+vjjjzVjxgxNnjxZr7zySqO3GZaIP4sVAAAXOvfccxv8CPIFCxYYn8/XqO2PGzfO/PKXvwze3rJli5Fk1q9fH7zvtddeMx6Px3z99dchz73tttvM7373uzr3f+TIETNs2DDz9NNPm/z8fDNu3LhaM1T/uYtNmzYd99j3339vJk2aZNq1a2fS0tLM+eefb4qKioKPDx061Nx6660hz5k6dao588wzw5h943FGBACAJtq7d6/+8Y9/aNKkScH71q5dq4yMDA0ePDh43/Dhw5WQkKD3338/eN+KFSv04osvas6cOXVu/7777lOHDh1Cth+p3/zmN9q3b59ee+01bdy4UQMHDtQFF1yg/fv3S5IqKyuP+wvDqampWrduXchf7Y42iggAAE20aNEipaWl6dJLLw3eV1JSog4dOoSMS0pKUps2bVRSUiJJ+u677zRx4kQtXLhQ6enptW57zZo1+vOf/6ynnnqq0fnWrFmjdevW6cUXX9TgwYPVs2dPPfTQQ8rIyNDf//53SdLIkSP19NNPa+PGjTLGaMOGDXr66ad1+PBhffvtt43ed0MoIgCAZumBBx5Q69atg1+rV6/WddddF3Lfrl27orKvZ555Rnl5ecedUWjINddco9/+9rc655xzan28vLxcV155pZ566im1a9eu0fk+/PBDVVRUqG3btiHz37Fjhz7//HNJ0l133aXRo0frF7/4hVq0aKFx48YpPz9fkpSQELu6kBSzLQMAYNF1112n8ePHB2/n5eXpsssuCzlrkZ2d3eT9rF69Wlu3btXf/va3kPuzsrK0b9++kPuOHDmi/fv3KysrS9LRl2WWLl2qhx56SJJkjFEgEFBSUpLmz5+vgQMH6ssvv9TYsWOD2wgEApKOnl3ZunWrunfv3mDGiooKdezYUW+//fZxj1VfpZOamqpnnnlG8+bN0969e9WxY0fNnz9faWlpat++fdjrESmKCACgWWrTpo3atGkTvJ2amqoOHTqoR48eUd3Pn//8Zw0aNEj9+/cPuX/o0KEqLS3Vxo0bNWjQIElHi0cgENCQIUMkHX0fSVVVVfA5L7/8smbNmqV3331XnTp1UmpqqjZv3hyy3T/84Q8qLy/XY489ppycnLAyDhw4UCUlJUpKStLJJ59c79gWLVqoc+fOko5eLvzrX/+aMyIAAMTSrl27tH//fu3atUtVVVXBz+Ho0aOHWrduLUnq3bu3CgsLdckllwSf5/f79eKLL+rhhx8+bpt9+vTRqFGjdM011+jJJ5/U4cOHNWXKFF1xxRXBMzF9+vQJec6GDRuUkJCgfv36Be879r+lf5/BOPb+6uy7d++WJG3dulXS0bMyWVlZGj58uIYOHaqLL75Yf/rTn3Tqqadq9+7d+sc//qFLLrlEgwcP1meffaZ169ZpyJAh+v777zV79mwVFxdr0aJFjVnSsPEeEQDACe/uu+/WgAEDdM8996iiokIDBgzQgAEDtGHDhuCYrVu3qqysLOR5zz//vIwxmjBhQq3bffbZZ9W7d29dcMEF+tWvfqWzzjpL8+fPj3r+pUuXasCAARozZowk6YorrtCAAQP05JNPSjr64WuvvvqqzjnnHF111VU69dRTdcUVV2jnzp3KzMyUJFVVVenhhx9W//79deGFF+rHH3/Uu+++2+AZlKbyGGNMTPcAAABQB86IAAAAaygiAADAGooIAACwhiICAACsoYgAAABrKCIAAMAaiggAALCGIgIAAKyhiAAAAGsoIgAAwBqKCAAAsIYiAgAArPn/MxFBmIdBMcMAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"k = 0\n",
"for node_id, group in histid.groupby('node_id'):\n",
" k += 1\n",
" plt.plot(group.start_unix.unique(), [k] * len(group.start_unix.unique()), marker='o')\n",
" plt.axvline(present_time - 300, c='r', linewidth=.5)\n",
" plt.axvline(present_time, c='r', linewidth=.5)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{175: 'i0',\n",
" 176: 'i1',\n",
" 177: 'i2',\n",
" 178: 'i3',\n",
" 201: 'i8',\n",
" 202: 'i9',\n",
" 206: 'i7',\n",
" 210: 'i6'}"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"inter2node"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'i0': 175,\n",
" 'u00': 175,\n",
" 'i1': 176,\n",
" 'i2': 177,\n",
" 'u20': 177,\n",
" 'i3': 178,\n",
" 'u30': 178,\n",
" 'u31': 178,\n",
" 'u32': 178,\n",
" 'i8': 201,\n",
" 'i9': 202,\n",
" 'i7': 206,\n",
" 'i6': 210,\n",
" 'u60': 210,\n",
" 'c30': 178}"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"node2inter"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'c30': 4,\n",
" 'i0': 3,\n",
" 'i1': 4,\n",
" 'i2': 4,\n",
" 'i3': 4,\n",
" 'i6': 4,\n",
" 'i7': 4,\n",
" 'i8': 4,\n",
" 'i9': 4,\n",
" 'u00': 3,\n",
" 'u20': 4,\n",
" 'u30': 4,\n",
" 'u31': 4,\n",
" 'u32': 4,\n",
" 'u60': 4}"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# node2num_cycles : A dictionary that maps a node_id to the number of cycles\n",
"def get_node2num_cycles(plan, node_ids):\n",
" Aplan = plan.copy()[['inter_no'] + [f'dura_A{j}' for j in range(1,9)] + ['cycle']]\n",
" grouped = Aplan.groupby('inter_no')\n",
" df = grouped.agg({'cycle': 'min'}).reset_index()\n",
" df = df.rename(columns={'cycle': 'min_cycle'})\n",
" df['num_cycle'] = 300 // df['min_cycle'] + 2\n",
" inter2num_cycles = dict(zip(df['inter_no'], df['num_cycle']))\n",
" node2numcycles = {node_id : inter2num_cycles[node2inter[node_id]] for node_id in node_ids}\n",
" return node2numcycles\n",
"node2num_cycles = get_node2num_cycles(plan, node_ids)\n",
"node2num_cycles"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>node_id</th>\n",
" <th>start_unix</th>\n",
" <th>phase_sumo</th>\n",
" <th>duration</th>\n",
" <th>state</th>\n",
" <th>start_dt</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>c30</td>\n",
" <td>1704410731</td>\n",
" <td>0_g</td>\n",
" <td>33</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:25:31</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>c30</td>\n",
" <td>1704410731</td>\n",
" <td>0_y</td>\n",
" <td>4</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:25:31</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>c30</td>\n",
" <td>1704410731</td>\n",
" <td>1__r</td>\n",
" <td>1</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:25:31</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>c30</td>\n",
" <td>1704410731</td>\n",
" <td>1_g</td>\n",
" <td>34</td>\n",
" <td>GGGGGG</td>\n",
" <td>2024-01-05 08:25:31</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>c30</td>\n",
" <td>1704410731</td>\n",
" <td>1_y</td>\n",
" <td>4</td>\n",
" <td>GGGGGG</td>\n",
" <td>2024-01-05 08:25:31</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1204</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>3__r</td>\n",
" <td>1</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1205</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>3_g</td>\n",
" <td>60</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1206</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>3_y</td>\n",
" <td>4</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1207</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>4__r</td>\n",
" <td>1</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1208</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>4_g</td>\n",
" <td>18</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>1209 rows × 6 columns</p>\n",
"</div>"
],
"text/plain": [
" node_id start_unix phase_sumo duration state start_dt\n",
"0 c30 1704410731 0_g 33 rrrrrr 2024-01-05 08:25:31\n",
"1 c30 1704410731 0_y 4 rrrrrr 2024-01-05 08:25:31\n",
"2 c30 1704410731 1__r 1 rrrrrr 2024-01-05 08:25:31\n",
"3 c30 1704410731 1_g 34 GGGGGG 2024-01-05 08:25:31\n",
"4 c30 1704410731 1_y 4 GGGGGG 2024-01-05 08:25:31\n",
"... ... ... ... ... ... ...\n",
"1204 u60 1704411629 3__r 1 ggggggggr 2024-01-05 08:40:29\n",
"1205 u60 1704411629 3_g 60 ggggggggr 2024-01-05 08:40:29\n",
"1206 u60 1704411629 3_y 4 ggggggggr 2024-01-05 08:40:29\n",
"1207 u60 1704411629 4__r 1 ggggggggr 2024-01-05 08:40:29\n",
"1208 u60 1704411629 4_g 18 ggggggggr 2024-01-05 08:40:29\n",
"\n",
"[1209 rows x 6 columns]"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Sigtable"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"node_id = 175\n",
"group = Sigtable[Sigtable.node_id==node_id]\n",
"offsets = {}\n",
"SIGTABLE = []\n",
"lsbs = group[group['start_unix'] < sim_start]['start_unix'].max() # the last start_unix before sim_start\n",
"offsets[node_id] = lsbs - sim_start\n",
"group = group[(group['start_unix'] < sim_end) & (group['start_unix'] >= lsbs)]\n",
"SIGTABLE.append(group)\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"def finalize_sigtable(Sigtable, sim_start, sim_end):\n",
" offsets = {}\n",
" SIGTABLE = []\n",
" for node_id, group in Sigtable.groupby('node_id'):\n",
" lsbs = group[group['start_unix'] < sim_start]['start_unix'].max() # the last start_unix before sim_start\n",
" offsets[node_id] = lsbs - sim_start\n",
" group = group[(group['start_unix'] < sim_end) & (group['start_unix'] >= lsbs)]\n",
" SIGTABLE.append(group)\n",
" SIGTABLE = pd.concat(SIGTABLE)\n",
" return SIGTABLE, offsets"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>node_id</th>\n",
" <th>start_unix</th>\n",
" <th>phase_sumo</th>\n",
" <th>duration</th>\n",
" <th>state</th>\n",
" <th>start_dt</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>59</th>\n",
" <td>c30</td>\n",
" <td>1704411510</td>\n",
" <td>0__r</td>\n",
" <td>1</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:38:30</td>\n",
" </tr>\n",
" <tr>\n",
" <th>60</th>\n",
" <td>c30</td>\n",
" <td>1704411510</td>\n",
" <td>0_g</td>\n",
" <td>33</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:38:30</td>\n",
" </tr>\n",
" <tr>\n",
" <th>61</th>\n",
" <td>c30</td>\n",
" <td>1704411510</td>\n",
" <td>0_y</td>\n",
" <td>4</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:38:30</td>\n",
" </tr>\n",
" <tr>\n",
" <th>62</th>\n",
" <td>c30</td>\n",
" <td>1704411510</td>\n",
" <td>1__r</td>\n",
" <td>1</td>\n",
" <td>rrrrrr</td>\n",
" <td>2024-01-05 08:38:30</td>\n",
" </tr>\n",
" <tr>\n",
" <th>63</th>\n",
" <td>c30</td>\n",
" <td>1704411510</td>\n",
" <td>1_g</td>\n",
" <td>34</td>\n",
" <td>GGGGGG</td>\n",
" <td>2024-01-05 08:38:30</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1204</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>3__r</td>\n",
" <td>1</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1205</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>3_g</td>\n",
" <td>60</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1206</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>3_y</td>\n",
" <td>4</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1207</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>4__r</td>\n",
" <td>1</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1208</th>\n",
" <td>u60</td>\n",
" <td>1704411629</td>\n",
" <td>4_g</td>\n",
" <td>18</td>\n",
" <td>ggggggggr</td>\n",
" <td>2024-01-05 08:40:29</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>360 rows × 6 columns</p>\n",
"</div>"
],
"text/plain": [
" node_id start_unix phase_sumo duration state start_dt\n",
"59 c30 1704411510 0__r 1 rrrrrr 2024-01-05 08:38:30\n",
"60 c30 1704411510 0_g 33 rrrrrr 2024-01-05 08:38:30\n",
"61 c30 1704411510 0_y 4 rrrrrr 2024-01-05 08:38:30\n",
"62 c30 1704411510 1__r 1 rrrrrr 2024-01-05 08:38:30\n",
"63 c30 1704411510 1_g 34 GGGGGG 2024-01-05 08:38:30\n",
"... ... ... ... ... ... ...\n",
"1204 u60 1704411629 3__r 1 ggggggggr 2024-01-05 08:40:29\n",
"1205 u60 1704411629 3_g 60 ggggggggr 2024-01-05 08:40:29\n",
"1206 u60 1704411629 3_y 4 ggggggggr 2024-01-05 08:40:29\n",
"1207 u60 1704411629 4__r 1 ggggggggr 2024-01-05 08:40:29\n",
"1208 u60 1704411629 4_g 18 ggggggggr 2024-01-05 08:40:29\n",
"\n",
"[360 rows x 6 columns]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"SIGTABLE, offsets = finalize_sigtable(Sigtable, sim_start, sim_end)\n",
"SIGTABLE"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def make_signals(SIGTABLE, offsets, present_time):\n",
" strings = ['<additional>\\n']\n",
" for node_id, group in SIGTABLE.groupby('node_id'):\n",
" strings.append(f' <tlLogic id=\"{node_id}\" type=\"static\" programID=\"{node_id}_prog\" offset=\"{offsets[node_id]}\">\\n')\n",
" for i, row in group.iterrows():\n",
" duration = row.duration\n",
" state = row.state\n",
" strings.append(f' <phase duration=\"{duration}\" state=\"{state}\"/>\\n')\n",
" strings.append(' </tlLogic>\\n')\n",
" strings.append('</additional>')\n",
" strings = ''.join(strings)\n",
" # 저장\n",
" path_output = f'../Results/sn_{present_time}.add.xml'\n",
" with open(path_output, 'w') as f:\n",
" f.write(strings)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def generate_signals(m):\n",
" midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
" next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
" fmins = range(midnight, next_day, 300)\n",
"\n",
" # 현재시각\n",
" present_time = fmins[m]\n",
" sigtable_start = fmins[m] - 600\n",
" sim_start = fmins[m] - 300\n",
" sim_end = fmins[m]\n",
" \n",
" # network and dataframes\n",
" net = sumolib.net.readNet('../Data/networks/sn.net.xml')\n",
" inter_node = pd.read_csv('../data/tables/inter_node.csv', index_col=0)\n",
" match6 = pd.read_csv('../Intermediates/match6.csv', index_col=0)\n",
" match6 = match6[['node_id', 'phase_no', 'ring_type', 'inc_edge', 'out_edge']].reset_index(drop=True)\n",
" histid = pd.read_csv(f'../Intermediates/histid/histid_{present_time}.csv', index_col=0)\n",
" histid = histid.reset_index(drop=True).drop(columns=['inter_no'])\n",
" \n",
" # helper dictionaries and lists\n",
" inter2node = dict(zip(inter_node['inter_no'], inter_node['node_id']))\n",
" node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
" pa2ch = {'i0':['u00'], 'i1':[], 'i2':['u20'], 'i3':['c30', 'u30', 'u31', 'u32'], 'i6':['u60'], 'i7':[], 'i8':[], 'i9':[]}\n",
" node_ids = sorted(inter_node.node_id.unique())\n",
" parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
" nodes = [net.getNode(node_id) for node_id in node_ids]\n",
"\n",
" with open('../Intermediates/node2num_ptags.json', 'r') as file:\n",
" node2num_ptags = json.load(file)\n",
"\n",
" # histids\n",
" histids = attach_children(histid, match6, parent_ids, pa2ch)\n",
"\n",
" # node2init\n",
" node2init = initialize_states(net, nodes, histids)\n",
"\n",
" # sigtable\n",
" sigtable = assign_signals(histids, node2init, net)\n",
"\n",
" # Sigtable\n",
" Sigtable = assign_red_yellow(sigtable)\n",
"\n",
" # SIGTABLE\n",
" SIGTABLE, offsets = finalize_sigtable(Sigtable, sim_start, sim_end)\n",
"\n",
" make_signals(SIGTABLE, offsets, present_time)\n",
" print(f'A signal file (add.xml) has been created for the timeslot between {datetime.fromtimestamp(sim_start)} and {datetime.fromtimestamp(sim_end)} ({sim_start} ~ {sim_end})')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generate_signals(164)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"inter2node"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for m in range(105, 107):\n",
" generate_signals(m)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "rts",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
}
},
"nbformat": 4,
"nbformat_minor": 2
}