diff --git a/0110_pyc_test/0110_pyc_test.py b/0110_pyc_test/0110_pyc_test.py new file mode 100644 index 0000000..a705e24 --- /dev/null +++ b/0110_pyc_test/0110_pyc_test.py @@ -0,0 +1,11 @@ +import numpy as np +# A, B로 나뉘어진 현시시간을 (4현시) 세부현시시간(5현시)로 바꾸는 코드 +durs_A = np.array([37, 55, 45, 23]) +durs_B = np.array([37, 55, 28, 40]) +cums_A = durs_A.cumsum() +cums_B = durs_B.cumsum() +cycle = durs_A.sum() +detailed_cums = [] +combined_row = np.unique(np.concatenate((cums_A, cums_B))) +detailed_durations = np.concatenate(([combined_row[0]], np.diff(combined_row))) +print(detailed_durations) \ No newline at end of file diff --git a/0110_pyc_test/0110_pyc_test_decompiled.py b/0110_pyc_test/0110_pyc_test_decompiled.py new file mode 100644 index 0000000..dea2170 --- /dev/null +++ b/0110_pyc_test/0110_pyc_test_decompiled.py @@ -0,0 +1,24 @@ +import numpy as np + +# 두 개의 배열 생성 +durs_A = np.array([37, 55, 45, 23]) +durs_B = np.array([37, 55, 28, 40]) + +# 두 배열의 누적합 계산 +cums_A = durs_A.cumsum() +cums_B = durs_B.cumsum() + +# durs_A의 합계를 cycle에 저장 +cycle = durs_A.sum() + +# 빈 리스트 생성 +detailed_cums = [] + +# cums_A와 cums_B의 고유한 요소들을 결합 +combined_row = np.unique(np.concatenate((cums_A, cums_B))) + +# combined_row의 각 요소 간 차이 계산 +detailed_durations = np.concatenate(([combined_row[0]], np.diff(combined_row))) + +# 결과 출력 +print(detailed_durations) diff --git a/0110_pyc_test/__pycache__/0110_pyc_test.cpython-38.pyc b/0110_pyc_test/__pycache__/0110_pyc_test.cpython-38.pyc new file mode 100644 index 0000000..166ccc0 Binary files /dev/null and b/0110_pyc_test/__pycache__/0110_pyc_test.cpython-38.pyc differ diff --git a/0110_pyc_test/__pycache__/env.cpython-38.pyc b/0110_pyc_test/__pycache__/env.cpython-38.pyc new file mode 100644 index 0000000..1509088 Binary files /dev/null and b/0110_pyc_test/__pycache__/env.cpython-38.pyc differ diff --git a/0110_pyc_test/env.py b/0110_pyc_test/env.py new file mode 100644 index 0000000..1a89c4f --- /dev/null +++ b/0110_pyc_test/env.py @@ -0,0 +1,189 @@ +import os +import sys +import numpy as np + +from sumolib import checkBinary + +from args import Args + + +class Env: + '''This class is responsible for handling the traffic light optimization environment.''' + def __init__(self, infos, path_config, name=0): + ''' + Initializes the environment with given information, + configuration path and initial state path. + ''' + self.path_config = path_config + self.infos = infos + self.node_ids = Args.node_ids + assert list(self.node_ids) == list(self.infos) + self.path_init_state = f'data/init_state_{name}' + assert not os.path.exists(self.path_init_state) + self.gui = Args.gui + + self.e2_length = Args.e2_length + self.yellow_length = Args.yellow_length + self.step_length = Args.step_length + self.rest_length = self.step_length - self.yellow_length + self.episode_length = Args.episode_length + self.episode_step = Args.episode_step + + self.name = name + + + def _start(self): + ''' + Starts the simulation. + https://sumo.dlr.de/docs/TraCI/Interfacing_TraCI_from_Python.html#importing_traci_in_a_script + ''' + import traci + if 'SUMO_HOME' in os.environ: + tools = os.path.join(os.environ['SUMO_HOME'], 'tools') + sys.path.append(tools) + else: + sys.exit("please declare environment variable 'SUMO_HOME'") + + sumo_binary = checkBinary('sumo-gui' if self.gui else 'sumo') + cmd = [sumo_binary, '-c', self.path_config] + traci.start(cmd, label=self.name) + self.conn = traci.getConnection(self.name) + + + def close(self): + '''Closes the simulation.''' + self.conn.close() + if os.path.exists(self.path_init_state): + os.remove(self.path_init_state) + + + def _save(self): + ''' + Saves the current state of the simulation. + https://sumo.dlr.de/docs/TraCI/Change_Simulation_State.html + ''' + self.conn.simulation.saveState(self.path_init_state) + + + def _load(self): + ''' + Loads the saved state of the simulation. + https://sumo.dlr.de/docs/TraCI/Change_Simulation_State.html + ''' + self.conn.simulation.loadState(self.path_init_state) + + + def _step(self, step_length): + '''Advances the simulation by a given number of steps.''' + for _ in range(step_length): + self.conn.simulationStep() + + + def _get_occupancy(self, detector_id): + ''' + Returns the occupancy of a given detector. + https://sumo.dlr.de/docs/TraCI/Lane_Area_Detector_Value_Retrieval.html + ''' + return self.conn.lanearea.getLastStepOccupancy(detector_id) / 100 + + + def _get_queue(self, detector_id): + ''' + Returns the queue length at a given detector. + https://sumo.dlr.de/docs/TraCI/Lane_Area_Detector_Value_Retrieval.html + ''' + return self.conn.lanearea.getJamLengthMeters(detector_id) / self.e2_length + + + def _get_values(self): + '''Retrieves the occupancy, queue and phase for each node.''' + node2values = {} + for node_id, info in self.infos.items(): + values = {} + values['occupancy'] = [self._get_occupancy(d) for d in info['detectors']] + values['queue'] = [self._get_queue(d) for d in info['detectors']] + values['phase'] = [self.prev_phase_indexes[node_id]] + node2values[node_id] = values + + states, rewards = [], [] + global_reward = 0 + for node_id, info in self.infos.items(): + occupancy = [node2values[node_id]['occupancy']] + queue = [node2values[node_id]['queue']] + phase = [node2values[node_id]['phase']] + reward = -np.sum(node2values[node_id]['queue']) + global_reward -= np.sum(node2values[node_id]['queue']) + for nnode_id in info['neighbors']: + occupancy.append(node2values[nnode_id]['occupancy']) + queue.append(node2values[nnode_id]['queue']) + phase.append(node2values[nnode_id]['phase']) + reward -= np.sum(node2values[nnode_id]['queue']) * 0.5 + + states.append(np.concatenate(occupancy + queue + phase, dtype=np.float32)) + rewards.append(reward) + + return states, rewards, global_reward + + + def _set_yellows(self, actions): + '''Sets the yellow phase for nodes based on the given actions.''' + for node_id, action in zip(self.node_ids, actions): + + if action == 0: + continue + + info = self.infos[node_id] + prev_idx = self.prev_phase_indexes[node_id] + idx = (prev_idx + 1) % len(info['phases']['green']) + self.prev_phase_indexes[node_id] = idx + + y = info['phases']['yellow'][prev_idx] + self._set_phase(node_id, y) + + + def _set_greens(self): + '''Sets the green phase for each node.''' + for node_id, info in self.infos.items(): + idx = self.prev_phase_indexes[node_id] + g = info['phases']['green'][idx] + self._set_phase(node_id, g) + + + def _set_phase(self, node_id, phase): + '''Sets the phase for a specific node.''' + if self.prev_phases.get(node_id) != phase: + self.conn.trafficlight.setRedYellowGreenState(node_id, phase) + self.prev_phases[node_id] = phase + + + def step(self, actions): + '''Performs a step in the simulation based on the given actions.''' + + self._set_yellows(actions) + self._step(self.yellow_length) + self._set_greens() + self._step(self.rest_length) + self.curr_step += 1 + + states, rewards, global_reward = self._get_values() + done = self.curr_step >= self.episode_step + return states, rewards, done, global_reward + + + def reset(self): + '''Resets the simulation to its initial state.''' + + # Initialize simulation + if not os.path.exists(self.path_init_state): + self._start() + self._save() + self._load() + + self.curr_step = 0 + self.prev_phases = {n:'none' for n in self.node_ids} + self.prev_phase_indexes = {n:0 for n in self.node_ids} + + self._set_greens() + self._step(1) + states, _, _ = self._get_values() + return states diff --git a/0110_pyc_test/env_decompiled.py b/0110_pyc_test/env_decompiled.py new file mode 100644 index 0000000..c8e87f7 --- /dev/null +++ b/0110_pyc_test/env_decompiled.py @@ -0,0 +1,171 @@ +# uncompyle6 version 3.9.0 +# Python bytecode version base 3.8.0 (3413) +# Decompiled from: Python 3.8.10 (tags/v3.8.10:3d8993a, May 3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] +# Embedded file name: .\env.py +# Compiled at: 2024-01-10 13:34:11 +# Size of source mod 2**32: 6588 bytes +import os, sys, numpy as np +from sumolib import checkBinary +from args import Args + +class Env: + __doc__ = 'This class is responsible for handling the traffic light optimization environment.' + + def __init__(self, infos, path_config, name=0): + """ + Initializes the environment with given information, + configuration path and initial state path. + """ + self.path_config = path_config + self.infos = infos + self.node_ids = Args.node_ids + assert list(self.node_ids) == list(self.infos) + self.path_init_state = f"data/init_state_{name}" + assert not os.path.exists(self.path_init_state) + self.gui = Args.gui + self.e2_length = Args.e2_length + self.yellow_length = Args.yellow_length + self.step_length = Args.step_length + self.rest_length = self.step_length - self.yellow_length + self.episode_length = Args.episode_length + self.episode_step = Args.episode_step + self.name = name + + def _start(self): + """ + Starts the simulation. + https://sumo.dlr.de/docs/TraCI/Interfacing_TraCI_from_Python.html#importing_traci_in_a_script + """ + import traci + if 'SUMO_HOME' in os.environ: + tools = os.path.join(os.environ['SUMO_HOME'], 'tools') + sys.path.append(tools) + else: + sys.exit("please declare environment variable 'SUMO_HOME'") + sumo_binary = checkBinary('sumo-gui' if self.gui else 'sumo') + cmd = [sumo_binary, '-c', self.path_config] + traci.start(cmd, label=(self.name)) + self.conn = traci.getConnection(self.name) + + def close(self): + """Closes the simulation.""" + self.conn.close() + if os.path.exists(self.path_init_state): + os.remove(self.path_init_state) + + def _save(self): + """ + Saves the current state of the simulation. + https://sumo.dlr.de/docs/TraCI/Change_Simulation_State.html + """ + self.conn.simulation.saveState(self.path_init_state) + + def _load(self): + """ + Loads the saved state of the simulation. + https://sumo.dlr.de/docs/TraCI/Change_Simulation_State.html + """ + self.conn.simulation.loadState(self.path_init_state) + + def _step(self, step_length): + """Advances the simulation by a given number of steps.""" + for _ in range(step_length): + self.conn.simulationStep() + + def _get_occupancy(self, detector_id): + """ + Returns the occupancy of a given detector. + https://sumo.dlr.de/docs/TraCI/Lane_Area_Detector_Value_Retrieval.html + """ + return self.conn.lanearea.getLastStepOccupancy(detector_id) / 100 + + def _get_queue(self, detector_id): + """ + Returns the queue length at a given detector. + https://sumo.dlr.de/docs/TraCI/Lane_Area_Detector_Value_Retrieval.html + """ + return self.conn.lanearea.getJamLengthMeters(detector_id) / self.e2_length + + def _get_values(self): + """Retrieves the occupancy, queue and phase for each node.""" + node2values = {} + for node_id, info in self.infos.items(): + values = {} + values['occupancy'] = [self._get_occupancy(d) for d in info['detectors']] + values['queue'] = [self._get_queue(d) for d in info['detectors']] + values['phase'] = [self.prev_phase_indexes[node_id]] + node2values[node_id] = values + else: + states, rewards = [], [] + global_reward = 0 + for node_id, info in self.infos.items(): + occupancy = [ + node2values[node_id]['occupancy']] + queue = [node2values[node_id]['queue']] + phase = [node2values[node_id]['phase']] + reward = -np.sum(node2values[node_id]['queue']) + global_reward -= np.sum(node2values[node_id]['queue']) + for nnode_id in info['neighbors']: + occupancy.append(node2values[nnode_id]['occupancy']) + queue.append(node2values[nnode_id]['queue']) + phase.append(node2values[nnode_id]['phase']) + reward -= np.sum(node2values[nnode_id]['queue']) * 0.5 + else: + states.append(np.concatenate((occupancy + queue + phase), dtype=(np.float32))) + rewards.append(reward) + + else: + return ( + states, rewards, global_reward) + + def _set_yellows(self, actions): + """Sets the yellow phase for nodes based on the given actions.""" + for node_id, action in zip(self.node_ids, actions): + if action == 0: + pass + else: + info = self.infos[node_id] + prev_idx = self.prev_phase_indexes[node_id] + idx = (prev_idx + 1) % len(info['phases']['green']) + self.prev_phase_indexes[node_id] = idx + y = info['phases']['yellow'][prev_idx] + self._set_phase(node_id, y) + + def _set_greens(self): + """Sets the green phase for each node.""" + for node_id, info in self.infos.items(): + idx = self.prev_phase_indexes[node_id] + g = info['phases']['green'][idx] + self._set_phase(node_id, g) + + def _set_phase(self, node_id, phase): + """Sets the phase for a specific node.""" + if self.prev_phases.get(node_id) != phase: + self.conn.trafficlight.setRedYellowGreenState(node_id, phase) + self.prev_phases[node_id] = phase + + def step(self, actions): + """Performs a step in the simulation based on the given actions.""" + self._set_yellows(actions) + self._step(self.yellow_length) + self._set_greens() + self._step(self.rest_length) + self.curr_step += 1 + states, rewards, global_reward = self._get_values() + done = self.curr_step >= self.episode_step + return (states, rewards, done, global_reward) + + def reset(self): + """Resets the simulation to its initial state.""" + if not os.path.exists(self.path_init_state): + self._start() + self._save() + self._load() + self.curr_step = 0 + self.prev_phases = {n: 'none' for n in self.node_ids} + self.prev_phase_indexes = {n: 0 for n in self.node_ids} + self._set_greens() + self._step(1) + states, _, _ = self._get_values() + return states +# okay decompiling .\env.cpython-38.pyc \ No newline at end of file diff --git a/0217_explore_eval_gtr/0217_explore_eval_gtr.ipynb b/0217_explore_eval_gtr/0217_explore_eval_gtr.ipynb new file mode 100644 index 0000000..06b09f1 --- /dev/null +++ b/0217_explore_eval_gtr/0217_explore_eval_gtr.ipynb @@ -0,0 +1,122 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`node_id = '11053'`는 총 4현시로 구성되어 있고, 1현시와 2현시에서 오버랩이 일어난다.\n", + "\n", + "#### single ring\n", + "\n", + "3현시는 오버랩현시에 포함되지 않으므로\n", + "$a_3=b_3$\n", + "이어야 한다. (단, $a_3$은 A링 3현시의 현시시간.)\n", + "그런데\n", + "\\begin{align*}\n", + "a_3&=ag_3+ar_3+ay_3\\\\\n", + "b_3&=bg_3+br_3+by_3\n", + "\\end{align*}\n", + "에서\n", + "\\begin{align*}\n", + "ag_3+ar_3+ay_3 &= bg_3+br_3+by_3\\\\\n", + "ag_3 - bg_3 &= -ar_3+br_3 -ay_3+by_3\\\\\n", + "\\begin{bmatrix}0\\\\0\\\\1\\\\0\\\\0\\\\0\\\\-1\\\\0\\end{bmatrix}^T\n", + "\\begin{bmatrix}ag_1\\\\ag_2\\\\ag_3\\\\ag_4\\\\bg_1\\\\bg_2\\\\bg_3\\\\bg_4\\end{bmatrix}\n", + "&= (-1)((ar_3+ay_3)-(br_3+by_3))\\tag{$*$}\n", + "\\end{align*}\n", + "이어야 한다.\n", + "한편\n", + "\\begin{align*}\n", + "\\texttt{loss\\_lst}\n", + "&= \\texttt{r\\_lst} + \\texttt{y\\_loss\\_lst} + \\texttt{y\\_lst}\\\\\n", + "&=\\begin{bmatrix}ar_1\\\\ar_2\\\\ar_3\\\\ar_4\\\\br_1\\\\br_2\\\\br_3\\\\br_4\\end{bmatrix}\n", + "+\\begin{bmatrix}0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\end{bmatrix}\n", + "+\\begin{bmatrix}ay_1\\\\ay_2\\\\ay_3\\\\ay_4\\\\by_1\\\\by_2\\\\by_3\\\\by_4\\end{bmatrix}\n", + "\\end{align*}\n", + "이다. ($\\texttt{y\\_loss\\_lst}$는 편의상 0.3으로 이루어진 벡터로 표현함.)\n", + "따라서 식 $(*)$의 우변은\n", + "$$\n", + "(-1)((ar_3+ay_3)-(br_3+by_3))\n", + "=(-1)\\begin{bmatrix}0\\\\0\\\\1\\\\0\\\\0\\\\0\\\\-1\\\\0\\end{bmatrix}^T\\texttt{loss\\_lst}\n", + "$$\n", + "으로 쓸 수 있고, 따라서 식 $(*)$은 \n", + "\n", + "$$\n", + "\\begin{bmatrix}0\\\\0\\\\1\\\\0\\\\0\\\\0\\\\-1\\\\0\\end{bmatrix}^T\n", + "\\begin{bmatrix}ag_1\\\\ag_2\\\\ag_3\\\\ag_4\\\\bg_1\\\\bg_2\\\\bg_3\\\\bg_4\\end{bmatrix}\n", + " = (-1)\\begin{bmatrix}0\\\\0\\\\1\\\\0\\\\0\\\\0\\\\-1\\\\0\\end{bmatrix}^T\\texttt{loss\\_lst}\n", + "$$\n", + "\n", + "이다.\n", + "A링과 B링의 황색/적색시간이 같으면 ($ar_i=br_i$, $ay_i=by_i$ ; 대부분의 경우에 이것이 성립한다.) 위 식의 우변은 0이다.\n", + "이것은 $ag_3=bg_3$이라는 의미이다.\n", + "\n", + "\n", + "이상이 `evaluation_green_time_ratio.py`의 368, 369번째 줄의 의미이다." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### dual ring\n", + "\n", + "1현시와 2현시는 오버랩되므로\n", + "$a_1+a_2=b_1+b_2$\n", + "이어야 한다.\n", + "그러면\n", + "\\begin{align*}\n", + "ag_1+ar_1+ay_1+ag_2+ar_2+ay_2 &= bg_1+br_1+by_1+bg_2+br_2+by_2\\\\\n", + "ag_1 + ag_2 - bg_1 - bg_2 &= -ar_1-ay_1-ar_2-ay_2+br_1+by_1+br_2+by_2\\\\\n", + "\\begin{bmatrix}1\\\\1\\\\0\\\\0\\\\-1\\\\-1\\\\0\\\\0\\end{bmatrix}^T\n", + "\\begin{bmatrix}ag_1\\\\ag_2\\\\ag_3\\\\ag_4\\\\bg_1\\\\bg_2\\\\bg_3\\\\bg_4\\end{bmatrix}\n", + "&= (-1)((ar_1+ay_1+ar_2+ay_2)-(br_1+by_1+br_2+by_2))\\tag{$**$}\n", + "\\end{align*}\n", + "이어야 한다.\n", + "한편\n", + "\\begin{align*}\n", + "\\texttt{loss\\_lst}\n", + "&= \\texttt{r\\_lst} + \\texttt{y\\_loss\\_lst} + \\texttt{y\\_lst}\\\\\n", + "&=\\begin{bmatrix}ar_1\\\\ar_2\\\\ar_3\\\\ar_4\\\\br_1\\\\br_2\\\\br_3\\\\br_4\\end{bmatrix}\n", + "+\\begin{bmatrix}0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\\\0.3 \\end{bmatrix}\n", + "+\\begin{bmatrix}ay_1\\\\ay_2\\\\ay_3\\\\ay_4\\\\by_1\\\\by_2\\\\by_3\\\\by_4\\end{bmatrix}\n", + "\\end{align*}\n", + "에서 식 $(**)$의 우변은\n", + "$$\n", + "(-1)((ar_1+ay_1+ar_2+ay_2)-(br_1+by_1+br_2+by_2))\n", + "=(-1)\\begin{bmatrix}1\\\\1\\\\0\\\\0\\\\-1\\\\-1\\\\0\\\\0\\end{bmatrix}^T\\texttt{loss\\_lst}\n", + "$$\n", + "으로 쓸 수 있고, 따라서 식 $(*)$은 \n", + "\n", + "$$\n", + "\\begin{bmatrix}1\\\\1\\\\0\\\\0\\\\-1\\\\-1\\\\0\\\\0\\end{bmatrix}^T\n", + "\\begin{bmatrix}ag_1\\\\ag_2\\\\ag_3\\\\ag_4\\\\bg_1\\\\bg_2\\\\bg_3\\\\bg_4\\end{bmatrix}\n", + " = (-1)\\begin{bmatrix}1\\\\1\\\\0\\\\0\\\\-1\\\\-1\\\\0\\\\0\\end{bmatrix}^T\\texttt{loss\\_lst}\n", + "$$\n", + "\n", + "이다. 이것이 `evaluation_green_time_ratio.py`의 380, 381번째 줄의 의미이다." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "sts", + "language": "python", + "name": "sts" + }, + "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 +} diff --git a/0217_explore_eval_gtr/0217_explore_eval_gtr.md b/0217_explore_eval_gtr/0217_explore_eval_gtr.md new file mode 100644 index 0000000..dcafe88 --- /dev/null +++ b/0217_explore_eval_gtr/0217_explore_eval_gtr.md @@ -0,0 +1,87 @@ +`node_id = '11053'`는 총 4현시로 구성되어 있고, 1현시와 2현시에서 오버랩이 일어난다. + +#### single ring + +3현시는 오버랩현시에 포함되지 않으므로 +$a_3=b_3$ +이어야 한다. (단, $a_3$은 A링 3현시의 현시시간.) +그런데 +\begin{align*} +a_3&=ag_3+ar_3+ay_3\\ +b_3&=bg_3+br_3+by_3 +\end{align*} +에서 +\begin{align*} +ag_3+ar_3+ay_3 &= bg_3+br_3+by_3\\ +ag_3 - bg_3 &= -ar_3+br_3 -ay_3+by_3\\ +\begin{bmatrix}0\\0\\1\\0\\0\\0\\-1\\0\end{bmatrix}^T +\begin{bmatrix}ag_1\\ag_2\\ag_3\\ag_4\\bg_1\\bg_2\\bg_3\\bg_4\end{bmatrix} +&= (-1)((ar_3+ay_3)-(br_3+by_3))\tag{$*$} +\end{align*} +이어야 한다. +한편 +\begin{align*} +\texttt{loss\_lst} +&= \texttt{r\_lst} + \texttt{y\_loss\_lst} + \texttt{y\_lst}\\ +&=\begin{bmatrix}ar_1\\ar_2\\ar_3\\ar_4\\br_1\\br_2\\br_3\\br_4\end{bmatrix} ++\begin{bmatrix}0.3 \\0.3 \\0.3 \\0.3 \\0.3 \\0.3 \\0.3 \\0.3 \end{bmatrix} ++\begin{bmatrix}ay_1\\ay_2\\ay_3\\ay_4\\by_1\\by_2\\by_3\\by_4\end{bmatrix} +\end{align*} +이다. ($\texttt{y\_loss\_lst}$는 편의상 0.3으로 이루어진 벡터로 표현함.) +따라서 식 $(*)$의 우변은 +$$ +(-1)((ar_3+ay_3)-(br_3+by_3)) +=(-1)\begin{bmatrix}0\\0\\1\\0\\0\\0\\-1\\0\end{bmatrix}^T\texttt{loss\_lst} +$$ +으로 쓸 수 있고, 따라서 식 $(*)$은 + +$$ +\begin{bmatrix}0\\0\\1\\0\\0\\0\\-1\\0\end{bmatrix}^T +\begin{bmatrix}ag_1\\ag_2\\ag_3\\ag_4\\bg_1\\bg_2\\bg_3\\bg_4\end{bmatrix} + = (-1)\begin{bmatrix}0\\0\\1\\0\\0\\0\\-1\\0\end{bmatrix}^T\texttt{loss\_lst} +$$ + +이다. +A링과 B링의 황색/적색시간이 같으면 ($ar_i=br_i$, $ay_i=by_i$ ; 대부분의 경우에 이것이 성립한다.) 위 식의 우변은 0이다. +이것은 $ag_3=bg_3$이라는 의미이다. + + +이상이 `evaluation_green_time_ratio.py`의 368, 369번째 줄의 의미이다. + + +#### dual ring + +1현시와 2현시는 오버랩되므로 +$a_1+a_2=b_1+b_2$ +이어야 한다. +그러면 +\begin{align*} +ag_1+ar_1+ay_1+ag_2+ar_2+ay_2 &= bg_1+br_1+by_1+bg_2+br_2+by_2\\ +ag_1 + ag_2 - bg_1 - bg_2 &= -ar_1-ay_1-ar_2-ay_2+br_1+by_1+br_2+by_2\\ +\begin{bmatrix}1\\1\\0\\0\\-1\\-1\\0\\0\end{bmatrix}^T +\begin{bmatrix}ag_1\\ag_2\\ag_3\\ag_4\\bg_1\\bg_2\\bg_3\\bg_4\end{bmatrix} +&= (-1)((ar_1+ay_1+ar_2+ay_2)-(br_1+by_1+br_2+by_2))\tag{$**$} +\end{align*} +이어야 한다. +한편 +\begin{align*} +\texttt{loss\_lst} +&= \texttt{r\_lst} + \texttt{y\_loss\_lst} + \texttt{y\_lst}\\ +&=\begin{bmatrix}ar_1\\ar_2\\ar_3\\ar_4\\br_1\\br_2\\br_3\\br_4\end{bmatrix} ++\begin{bmatrix}0.3 \\0.3 \\0.3 \\0.3 \\0.3 \\0.3 \\0.3 \\0.3 \end{bmatrix} ++\begin{bmatrix}ay_1\\ay_2\\ay_3\\ay_4\\by_1\\by_2\\by_3\\by_4\end{bmatrix} +\end{align*} +에서 식 $(**)$의 우변은 +$$ +(-1)((ar_1+ay_1+ar_2+ay_2)-(br_1+by_1+br_2+by_2)) +=(-1)\begin{bmatrix}1\\1\\0\\0\\-1\\-1\\0\\0\end{bmatrix}^T\texttt{loss\_lst} +$$ +으로 쓸 수 있고, 따라서 식 $(*)$은 + +$$ +\begin{bmatrix}1\\1\\0\\0\\-1\\-1\\0\\0\end{bmatrix}^T +\begin{bmatrix}ag_1\\ag_2\\ag_3\\ag_4\\bg_1\\bg_2\\bg_3\\bg_4\end{bmatrix} + = (-1)\begin{bmatrix}1\\1\\0\\0\\-1\\-1\\0\\0\end{bmatrix}^T\texttt{loss\_lst} +$$ + +이다. 이것이 `evaluation_green_time_ratio.py`의 380, 381번째 줄의 의미이다. \ No newline at end of file