这个Riddler公司是关于如何准确地确定红绿灯的时间,这是我们都必须处理的问题!
你正在一条平坦笔直的道路上开车。你是路上唯一的一个,你可以完美地看到前方的一切。当时间t=0时,您处于A点,以每小时100公里的速度巡航,这是整个道路的速度限制。你想在尽可能短的时间内到达C点,正好前方4公里。但是,在你前面2公里的B点,有一个红绿灯。
当时间t=0时,灯是绿色的,但您不知道它变绿了多久。你知道,在每一秒的开始,有1%的几率灯会变黄。一旦变黄,它会保持黄色5秒钟,然后变红20秒钟。你的汽车可以以每秒2米的最大速度加速或减速。你必须始终以或低于限速行驶。当红绿灯为黄色时,你可以通过十字路口,但红绿灯时不行。
尽快到达目的地的最佳策略是什么?
这是我的解决方案:
[显示解决方案]
让我们给变量命名,这样单位转换就不会变得麻烦。定义:
\开始{align}
x_\text{light}&=\text{红绿灯位置(2公里)}\\
x_\text{end}&=\text{终点线位置(4km)}\\
v_\text{max}&=\text{限速(100 km/h)}\\
a_\text{max}&=\text{最大加速度(2米/秒}^2\text{)}\\
\tauy&=\text{黄灯持续时间(5秒)}\\
\taur&=\text{红灯持续时间(20秒)}
\结束{对齐}
在这个问题中,我们隐含地假设我们永远不会闯红灯。所以即使我们不知道什么时候灯会变黄,我们也不能冒险;我们必须确保,即使是最不可能出现的最不合时宜的黄灯也不会导致我们闯红灯。
解决这个问题有很多不同的方法,但由于我目前正在教一门关于优化建模,我想我会走那条路。建模方法背后的想法是想象汽车的位置、速度和加速度是必须满足几个约束的决策变量。
基本变量和约束
让我们离散化时间间隔,并假设我们每$\Delta t$秒进行一次决策。因此,如果$\Delta t=1$,我们每秒都会做出决定。然后,定义以下决策变量:
\开始{align}
x_t&\ge 0&&\text{时间位置}t\\
0\le v_t&\le v_\text{max}&&\text{速度\\
-a_\text{max}\lea_t&\lea_\text{max}&&\text{时间加速度}t
\结束{align}其中时间指数范围超过$t=0,1,\dots,t$,其中$t$足够大。当然,我们不能任意选择位置和速度;它们必须是一致的。通过将加速度近似为每个$\Delta t$步的常数,我们可以得出:
\开始{align}
v_{t+1}&=v_t+a_t\增量t&&\text{(以恒定加速度改变速度)}\\
x_{t+1}&=x_t+v_t\增量t+\tfrac{1}{2} a _ t\Delta t^2&&\text{(位置随加速度变化)}
\结束{对齐}我们还具有位置和速度的初始条件:
\[
x_0=0\qquad\text{和}\qquad v_0=v_\text{max}
\]注意,我们将速度限制为非负。事实证明,这无关紧要,允许向后运动也无济于事。不管怎样,我们都得到了相同的答案!
应急计划
既然我们永远不能冒闯红灯的风险,我们必须确保在每一刻,必须发生两件事中的一件。要么:
- 我们可以在$\tau_y$秒内到达$x_\text{light}$。(我们运行黄色)或:
- 我们从不在$\tau_y+\tau_r$sec内传递$x_\text{light}$(我们可以避免运行红色)。
这些约束可以用代数编码。对于每个$t$,我们将定义一组新的位置、速度和加速度,持续时间为$\tau_y+\tau_r$秒。这些是应急变量,使我们能够确保在$t$时间灯变黄时不会出现任何问题。因此,我们定义了变量:
\开始{align}
\帽子x{t,k}&\ge0&&\text{(应急位置)}\\
0\le\hat v_{t,k}&\lev_\text{max}&&\text{(偶然速度)}\\
-a_\text{max}\le\hat a{t,k}&\lea_\text{max}&&\text{(偶然加速度)}
\结束{align}这些新的应急变量定义在$0\le t$和$0\ler k\le tau_y+\tau_r$上。就像普通的位置和速度一样,它们必须满足偶然性约束:
\开始{align}
\hatv{t,k+1}&=\hatv}t,k}+\hata{t,k}\Deltat&&\text{(速度随恒定加速度变化)}\\
\hat x{t,k+1}&=\hat x_{t,k}+\hat v{t,k-}\增量t+\tfrac{1}{2}\hat a{t,k.}\增量t ^2&&\text{(用常数加速度改变位置)}
\结束{对齐}我们还具有位置和速度的初始条件:
\[
\hatx{t,0}=x_t\qquad\text{和}\qqua2\hatv{t,0}=v_t
\]现在我们已经设置了偶然轨迹,我们必须对二进制约束进行编码。要么我们可以运行黄色,要么我们可以安全运行红色。让我们定义二进制变量:
\开始{align}
z^y_t\in\{0,1\}&\qquad\text{(如果灯在}t\text{变黄,我们可以运行黄色吗?)}\\
z^r_t\in\{0,1\}&\qquad\text{(如果灯在}t\text{变黄,我们可以安全运行红色吗?)}
\结束{align}我们可以运行黄色而不运行红色的约束是:
\开始{align}
\帽子x{t,tau_y}&\gex_\text{light}z^y_t&\quad\text{for-all}t\text{,和}\\
\帽子x{t,tau_y+tau_r}&lex_\text{light}+(1-z^r_t)x_\text{end}&&quad\text{代表所有}t\text{。}
\结束{对齐}在一起对于所有$t$,使用逻辑约束$z^y_t+z^r_t\ge 1$,这确保我们可以运行黄色的OR,我们可以安全地运行红色的OR。就这样!
目标函数
上述工作描述了一组可行的位置、速度和加速度曲线,这些曲线保证我们永远不会违反定律。在这些配置文件中,我们应该选择一个能让我们以平均最快的速度到达终点的配置文件。我努力寻找一个简单的目标函数来精确地捕捉这个概念。作为一种妥协,我只是尽量缩短了旅行的时间假设灯永远不会变红。这应该是与真实解决方案的适当近似,因为黄灯相对较少。大多数时候,当光线变黄时,它实际上并不影响我们;当我们靠近它时,如果灯变黄,这只是一个问题,这种情况不会经常发生。
为了描述完成时间,我定义了二进制变量:
\[
z^e_t\in\{0,1\}\qquad\text{(我们在时间}t\text{完成了吗?)}
\]连同约束:
\[
x_t\gex_\text{end}z^e_t\qquad\text{forall}t。
\]现在,只要我们越过终点线,我们的二进制变量就会是$1$。因此,通过最大化$\sum_{t=0}^Tz^e_t$,我们可以尽快到达末尾。
解决方案
从建模的角度来看,我们所有的约束都是线性的,这很好。我们确实有一些二进制变量,这使得混合整数线性规划(MILP)。然而,使用标准求解器相对容易解决该问题。对于这个问题,我将模型编码为朱莉娅连同JuMP公司包和古罗比求解器。一些细节:
- 用$\Delta t=1$求解。预解后,问题有:3492个约束、6216个连续变量和108个二进制变量。在笔记本电脑上解决问题大约需要0.3秒。
- 用$\Delta t=0.5$求解。预解后,问题有:15499个约束、29602个连续变量和216个二进制变量。在笔记本电脑上求解大约需要1.3秒。
- 用$\增量t=0.25$求解。预解后,问题有:63925个约束、125250个连续变量和436个二进制变量。在笔记本电脑上求解大约需要12秒钟。
无论时间离散化如何,所有解看起来都是一样的。这里是$\Delta t=0.25$的解决方案图,放大到汽车靠近红绿灯的点附近。
该绘图在此范围之外看起来是恒定的。因此,最佳做法是保持100 km/h的速度65秒,然后尽可能大幅度减速2.5秒,再尽可能大力度加速2.5秒,然后继续保持100 km/h。速度下降的原因是,如果灯变黄,我们将无法及时停车,因此,我们必须规避风险。67.5秒后,我们可以安全地加速,因为我们知道如果灯变黄,我们将在接下来的5秒内到达。
如果您有兴趣查看我的代码的全部细节,可以查看/下载我的笔记本在这里.