04. 深さ制限付き最速降下
最速降下の坂は、深く下って速度を稼ぐほど有利でした。では、ある深さより下には坂を作れないとしたらどうでしょうか。 床に沿って進む区間が現れ、道筋の形が変わります。
| 項目 | 内容 |
|---|---|
| 状態 | 水平位置 、深さ 、速さ |
| 制御 | 坂の向き (真下から測った角度) |
| 目的 | 到着時刻 を最小にする |
| 区間 | 1区間、40ノード、終了時刻は自由 |
| 新しく学ぶこと | 状態の上下限を経路制約として使うこと、制約に沿って進む区間(境界弧)が現れること |
例題03 と同じく、摩擦のない坂を玉が重力だけで転がります。今回は次の2点が違います。
- 終点を1点に決めます。 水平に 1 m、深さ 0.2 m の点です。例題03では深さを自由にしていました。
- 床があります。 深さ 0.3 m より下には坂を作れません。
床がなければ、最速の道は終点より深いところまで下ってから、終点へ向かって上り返します。深く下るほど速くなれるからです。 その最も深い点が床より下にあると、そのままでは通れません。床が答えをどう変えるかを調べます。
この例では重力加速度を地球の値 9.81 m/s² にしています。
深さ は下向きを正、角度 は真下から測ります。 が真下、 が水平、 より大きいと上り坂です。
例題03と同じ式です。上り坂()では3行目が負になり、玉は減速します。 ここでもエネルギー保存により、速さは深さだけで決まります()。
終点の速さは決めません。エネルギー保存から、終点の深さが決まれば速さも m/s に決まります。
1行目の上限 がこの例の主役の床です。この例では、どれも変数の上下限として与えています。 状態の上下限はすべてのノードで課されるので、「途中のどの時刻でも床より下へ行かない」という経路制約として働きます。
、(左へ戻らない)、終了時刻の範囲は、計算が変な方向へ迷い込まないための補助的な制約です。
| 記号 | 意味 | 値 |
|---|---|---|
重力加速度 PARAMETERS["gravity"] | 9.81 m/s² | |
終点の水平距離 PARAMETERS["distance"] | 1 m | |
終点の深さ PARAMETERS["final_depth"] | 0.2 m | |
床の深さ PARAMETERS["max_depth"] | 0.3 m |
時刻は 0 から 0.7 s までとし、その割合を (0 から 1)とします。
水平位置は一定の速さで進み、深さは途中で一度ふくらんでから終点の深さへ戻る形です。 速さはエネルギー保存に合わせています。向き は 0 から 2 rad(約 115°)へ時刻に比例して増やします。


- 到着時刻は 0.6242 s です。床がない場合の 0.6206 s より、わずかに遅くなります。
- 床がなければ深さ 0.358 m まで下りますが、床があると最大深さは 0.300 m に抑えられます。
- 道筋は「下る → 床に沿って水平に進む → 上る」の3つの部分に分かれます。床の上では向きが 90°(水平)で一定、速さも一定です。
- 終点では向きが 125° の上り坂で、速さは 1.981 m/s です。
床に沿って進む区間
Section titled “床に沿って進む区間”床がないときの最速の道は、床より深いところを通ります。床があるとそこへは行けないので、 行ける範囲で最も深いところ、つまり床の上をできるだけ長く通るのが次善の策になります。 床の上では速さが m/s で、これが途中で出せる最大の速さです。
このように、制約が等号で成り立ったまま()進む部分を境界弧といいます。 境界弧の上では制御も制約で決まり、深さを保つために向きは水平()に固定されます。 境界弧の前後は、床のない問題と同じくサイクロイドの一部で、床に接するように入り、接するように出ていきます。
時間の損失が小さい理由
Section titled “時間の損失が小さい理由”床があると、床がない場合の最も深い(最も速い)部分を通れません。ただ、その部分は道のりのごく一部で、 床の上でも速さは 2.43 m/s と十分に大きいので、到着時刻の差は1 % 未満にとどまります。
例題03では終点の深さを自由にしたので、終点でちょうど水平になりました。この例では終点の深さを 0.2 m に固定したので、 その条件はなくなります。床から 0.2 m まで上り返す必要があり、終点では上り坂になっています。
1本の多項式で表す限界
Section titled “1本の多項式で表す限界”境界弧の始まりと終わりでは、向き の変化の仕方が急に変わります(傾きが折れ曲がる)。 1区間の多項式ではこの折れ目を正確に表せないので、向きのグラフでは境界弧の前後が少し丸まっています。 上限はノードでだけ課されるので、ノードの間を通る多項式は床をごくわずかに( m 程度)超えることがあります。 ノードを増やすと折れ目はよりはっきりします。
試してみよう
Section titled “試してみよう”PARAMETERS["max_depth"]を 0.4 にする。床が床なしの最大深さ(約 0.358 m)より深くなるので床に触れず、到着時刻は床なしの値 約 0.6206 s に一致します。PARAMETERS["max_depth"]を 0.25 にする。床に沿う区間が長くなり、到着時刻は約 0.636 s に延びます。main()のsolve()をsolve(nodes=20)にしてノード数を半分にし、向きのグラフの折れ目付近の形を40ノードの場合と比べる。
uv run python examples/04_constrained_descent.pyexamples/04_constrained_descent.py を GitHub で見る