tsp的理論和實踐(8)派件時間窗和held-karp動態規劃

tsp目錄算法

  1. 最簡單的實踐 juejin.im/post/5d1b14…
  2. 最簡單的理論 juejin.im/post/5d1b15…
  3. 當前tsp的現狀 juejin.im/post/5d1b19…
  4. 單起點任務分配 juejin.im/post/5d1c6d…
  5. 多起點任務分配 juejin.im/post/5d1dbe…
  6. 更簡潔的多起點分配 juejin.im/post/5d1dc2…
  7. 起點時間窗 juejin.im/post/5d1f1f…
  8. 終點時間窗和hk juejin.im/post/5d1f44…
  9. LK簡介 juejin.im/post/5d25b8…
  10. tsp系列暫停一下 juejin.im/post/5d302e…

tsp領域的問題, 並不都是tsp問題, 可是, tsp相關的算法通常都能解決, 只要你能爲某一個充滿個性的問題兒子找到他親生的解決方案爸爸.數組

通過前面7篇的努力, 咱們實際上已經解決了訂單分配問題, 由於派件時間窗其實不是一個分配問題. 下面咱們詳細分析一下bash

需求概述
  1. 某樣物品, 客戶要求在下午4:00前收到.
  2. 某樣物品, 客戶要求在中午12:00前收到.
分析
  • 這些其實並非需求, 緣由是: 咱們沒法保證知足, 除非用相似無人機這樣的設備, 直接空投過去. 否則, 受各類因素干擾, 咱們通常狀況下只能說, 預計某一天到達. 快遞的目標就是把這個某一天儘可能提早, 好比全球第二天達.
  • 而後, 當單量上升到必定地步的時候, 咱們能夠把工做時間段逐步拆碎, 好比天天分紅3段, 這個貨預計上午9:00-12:00到. 單量再上升, 甚至能夠半個小時一段. 好比配餐服務.
  • 若是客人必定要求咱們更快速配送, 好比支付不少費用, 那麼能夠經過路線調整來知足.
  • 可是, 實際上配送效率仍是咱們服務的總體質量中最核心的內容, 所以, 咱們應該針對全部客戶給一個至關快的配送效率, 而不是針對某些客戶提供付費服務.
結論
  • 咱們應該提供更高效的服務.
  • 好比當日達, 咱們要保證當日能到達, 而且當日能讓儘可能多的訂單到達.
  • 由此, 線路規劃仍是很是有用的. 並且有與實際工做中咱們的訂單有諸多的限制, 所以, 這個線路規劃不能使用生成類方法好比:
    • 插入類算法, 如: 最遠插入法…...
    • 生成樹類算法, 包括christofides
  • 可使用嘗試類算法例如
    • 線性規劃LP
    • LK交換算法
    • 遺傳算法
    • 動態規劃
  • 這些算法裏面, LP, LK和遺傳咱們後文討論, 這裏咱們先聊一下動態規劃.
動態規劃 held-karp算法

這個算法很優雅, 也是目前精確算法中理論速度最好的, 惋惜的是, 他的開銷是2的n次方. 因此, 他不實用, 很遺憾, 我試過了, 確實不實用, 可是他的思路對咱們仍是有不少啓發的.數據結構

  • 每一步都計算全部的點位最後一個點的可能性.
  • 每一步都依賴前一步的結果.

例如ide

  • 一共有10個點.
  • 假設如今是第六步,
    • 我要計算4爲最後一步的全部結果.
    • 那麼, 以 1, 2, 3, 5, 6, 7, 8, 9, 10爲最後一個點的5個點的集合, 而且是不包含4的集合.
    • 而後能夠獲得以4爲終點的全部含有6個點的結果.

整體思路post

  • 關鍵是編碼規則. 建議規則ui

    _id1_id2_id3_
    複製代碼
  • 好比已經生成了3個元素的全部集合.編碼

  • (1, 2, 3) 這三個元素的集合能夠順序生成,spa

    • ((1, 2, 3,) 4,) , ((1, 2, 3,) 5,) , ((1, 2, 3,) 6,)…… 等等.
  • 而後同理(1, 2, 4), 能夠順序生成 ((1, 2, 4,) 3,),3d

  • ((1, 2, 3,) 4,) 和 ((1, 2, 4,) 3,) 都是(1,2,3,4)的一部分, (1,2,3,4)包含了全部的狀況.

時間開銷: 以((1, 2, 3,) 4,)舉例, 最後一步.

  1. (1, 2, 3) 這裏是c43, 是四個挑3個. cnm, n是總數, m是當前的輪次.
  2. 而後, 和最後一個數字的結合是p42, 是排列, 4*3的排列=n * (n-1)

整體步驟

  • 初始化:

    • 生成(1), (2), (3),…….(10)

    • 生成((1), 2), ((1), 3)……((10),9)

    • 此時(1, 2), 包含((1), 2)和 ((2), 1)

    • 這裏(1, 2)是一個karp, 他的id

      _id1_id2_
      複製代碼
  • 實際運算

    • 生成(1, 2, 3), (1, 2, 4)……(8,9,10)

    • 順序生成4個元素…...

    • 一直到所有10個元素的一個karp, 他的id:

      _id1_id2_id3_id4_id5_id6_id7_id8_id9_id10_
      複製代碼
  • 數據定義

    • 全部的karp都在一個held結構裏面.
    • 能夠快速的索引到, 指望的karp, 若是對應的karp沒有索引到, 就新建一個.

算法

  • 一個for循環
    • 每一個層次都處理當前層次的held結構.
    • 處理的過程當中生成下一個層次的held.

數據結構

  • held結構包含本層次的全部karp,
    • 好比held(2)包含全部的karp(1, 2), karp(1, 3)….. karp(9,10)
    • held裏面能夠順序遍歷本身的全部karp.
    • held能夠索引本身的karp.
      • 如何索引到合適的karp.
      • 根據一組key數組, 索引到合適的karp.
      • 這一個數組key, 能夠組合爲一個字符串. 用這個串做爲karp的key
  • karp
    • 插入
      • 插入某個包含key的值.
    • key, 總體包括全部key(element->e).
      • 包含的key,
        • 反正都要indexof, 不如就用array吧.
      • 不包含的key
function algorithm TSP (G, n)
  for k := 2 to n do
    C({k}, k) := d1,k
  end for

  for s := 2 to n-1 do
    for all S ⊆ {2, . . . , n}, |S| = s do
      for all k ∈ S do
        C(S, k) := minm≠k,m∈S [C(S\{k}, m) + dm,k]
      end for
    end for
  end for

  opt := mink≠1 [C({2, 3, . . . , n}, k) + dk,1]
  return (opt)
end
複製代碼
相關文章
相關標籤/搜索