<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      如何用隨機方法求解組合優化問題(七)

      模擬退火算法應用舉例

      這是一篇筆記,是對于B站up主馬少平的視頻(第四篇 如何用隨機方法求解組合優化問題(七))的學習與記錄。

      旅行商問題

      一個商人要訪問 \(n\) 個城市,每個城市訪問一次,并且只能訪問一次,最后再回到出發城市。
      問如何規劃才能使得行走的路徑長度最短。

      旅行商問題的解空間非常大,難以使用窮舉法進行求解。

      • 10城市:\(10!=3628800\)
      • 20城市:\(20!\approx 2.43\times 10^{18}\)

      在已知模擬退火算法的基本框架,以及需要確定的參數的情況下,為了解決實際問題,我們需要將實際問題,轉換并抽離出我們需要的參數。

      指標函數

      \[f(\pi_1,\cdots,\pi_n)=\sum\limits_{i=1}^nd_{\pi_i\pi_{i+1}}\quad\quad \pi_{n+1}=\pi_1 \]

      其中 \((\pi_1,\cdots,\pi_n)\) 是表示路徑的序列,\(\pi_i\) 表示第 \(i\) 個訪問的城市,\(d_{\pi_i\pi_i+1}\) 是路徑中相鄰兩個城市的距離。

      新解的產生

      逆序交換法
      • 當前解

      \[(\pi_1,\cdots,\pi_u,\pi_{u+1},\cdots,\pi_{v-1},\pi_v,\cdots,\pi_n)\quad\quad u\ge0,v\le n+1 \]

      • 交換后

      \[(\pi_1,\cdots,\pi_u,\pi_{v-1},\cdots,\pi_{u+1},\pi_v,\cdots,\pi_n)\quad\quad u\ge0,v\le n+1 \]

      \(\pi_u\)\(\pi_v\) 這兩個城市之間的路徑進行逆序, \(\pi_u\)\(\pi_v\) 不變。

      指標函數差

      當新解是較好的解時,百分之百接受;當新解是較差的解時,則按概率接受:

      \[P_{i\Rightarrow j}(t)=e^{-\frac{f(j)-f(i)}{t}}=e^{-\frac{\Delta f}{t}} \]

      為了計算接受概率,需要先計算指標函數差 \(f(j)-f(i)\)

      需要注意的是,這里并不需要完全計算出兩個解的總路徑長度再做差。

      由于我們使用的是逆序交換法,兩個解之間的差別只存在于逆序區間的交界處

      當前解:\((\pi_1,\cdots,\pi_u,\pi_{u+1},\cdots,\pi_{v-1},\pi_v,\cdots,\pi_n)\)

      交換后:\((\pi_1,\cdots,\pi_u,\pi_{v-1},\cdots,\pi_{u+1},\pi_v,\cdots,\pi_n)\)

      因此,有:

      \[\begin{align*} \Delta f &= f(j) - f(i) \\ &= (d_{\pi_u\pi_{v-1}}+d_{\pi_{u+1}\pi_v})-(d_{\pi_u\pi_{u+1}}+d_{\pi_{v-1}\pi_v}) \end{align*} \]

      故從解 \(i\) 到解 \(j\) 的接受概率:

      \[P_{i\Rightarrow j}(t)= \begin{cases} 1 & if \ \Delta f\le 0 \\ e^{-\frac{\Delta f}{t}} & else \end{cases} \]

      參數確定

      • 初始溫度:\(t_0=200\)
      • 溫度衰減系數:\(\alpha=0.95\)\(t_{k+1}=\alpha t_k\)
      • 每個溫度下的迭代次數:\(100n\)\(n\) 為城市數
      • 算法結束條件:無變化控制法(相鄰兩個溫度下結果相等)

      代碼實現

      測試數據

      這里提供了 10 個城市的 xy 坐標。

      A 0.4000 0.4439
      B 0.2439 0.1463
      C 0.1707 0.2293
      D 0.2293 0.7610
      E 0.5171 0.9414
      F 0.8732 0.6536
      G 0.6878 0.5219
      H 0.8488 0.3609
      I 0.6683 0.2536
      J 0.6195 0.2634
      

      City class

      定義 City 類,方便后續操作。

      class City:
          def __init__(self, name: str, x: float, y: float):
              self.name = name
              self.x = x
              self.y = y
      
          def __repr__(self):
              return f"{self.name} {self.x} {self.y}"
      
          def __str__(self):
              return f"{self.name} {self.x} {self.y}"
      
          def distance(self, other: 'City'):
              d = ((self.x - other.x)*(self.x - other.x)
                   + (self.y - other.y)*(self.y - other.y))**0.5
              return d
      

      讀取數據

      假設上面的測試數據保存在10.txt文件中。這里用一個函數來讀取文件數據,并轉換為 City 列表。

      def read_data(path: str):
          data: list[City] = []
          with open(path, 'r', encoding='utf-8') as f:
              for line in f.readlines():
                  information = line.replace('\n', '').split(' ')
                  data.append(City(name=information[0], x=float(information[1]), y=float(information[2])))
          return data
      

      生成隨機序列

      為了隨機地生成一個初始解,使用一個數值列表表示旅行商的城市訪問順序:

      def gen_random_seq(length: int)->list[int]:
          sequence = list(range(length))
          random.shuffle(sequence)
          return sequence
      

      實現對序列片段的逆序交換

      為了生成鄰居解,需要實現逆序交換,函數需要傳入:原序列、逆序區間的起始下標、結束下標。

      def reverse_seq(sequence: list[int], start_idx: int, end_idx: int)->list[int]:
          assert start_idx <= end_idx
          i = start_idx
          j = end_idx
          while i<j:
              sequence[i], sequence[j] = sequence[j], sequence[i]
              i += 1
              j -= 1
          return sequence
      

      生成鄰居解

      根據傳入的原序列,使用逆序交換法生成鄰居解,逆序區間是隨機的。

      這里生成兩個端點ab之后,進行逆序,但是逆序操作并不包含這兩個端點。

      因為類似于[0,...,9][9,...,0]這兩個序列在旅行商問題中是一樣的,路線是首尾相接的環。

      def gen_near_seq(sequence:list[int])->(list[int], int, int):
          n = len(sequence)
          a = math.floor(random.random()*n)
          b = math.floor(random.random()*n)
          start_idx, end_idx = (a, b) if a<b else (b, a)
          # 除去區間端點
          if end_idx - start_idx > 1:
              start_idx += 1
              end_idx -= 1
          return reverse_seq(sequence, start_idx, end_idx), start_idx, end_idx
      

      指標函數

      根據序列和城市列表,計算路徑的總長度。

      def valuate(sequence: list[int], cities: list[City])->float:
          total: float = 0
          length = len(cities)
          for idx in range(length):
              curr_city = cities[sequence[idx]]
              next_city = cities[sequence[(idx+1)%length]]
              d = curr_city.distance(next_city)
              total += d
          return total
      

      最終實現

      根據上面已經編寫好的函數,開始結合算法解決問題。

      數據讀取
      # 文件的路徑根據實際情況進行填寫
      cities = read_data('./dataset/10.txt')
      
      超參數設置
      # 初始溫度
      t = 200
      # 溫度遞減速率
      alpha = 0.95
      # 問題規模(10個城市)
      n = 10
      # 同一溫度的迭代次數
      iteration_times = 100 * n
      
      生成隨機序列

      隨機地生成當前的序列和它的指標:curr_seqcurr_val

      初始化最優解的序列和指標:best_seqbest_val.

      curr_seq: list[int] = gen_random_seq(n)
      curr_val: float = valuate(curr_seq, cities)
      best_seq: list[int] = list()
      best_val: float = float('inf')
      
      內外循環
      while curr_val != best_val:
          i = 0
          while i < iteration_times:
              i += 1
              # 生成相鄰解
              new_seq, start_idx, end_idx = gen_near_seq(curr_seq)
              new_val = valuate(new_seq, cities)
              # 是否接受解
              if new_val <= curr_val:
                  curr_seq, curr_val = new_seq, new_val
              else:
                  if random.random() < math.e ** ((curr_val - new_val) / t):
                      curr_seq, curr_val = new_seq, new_val
              # 記錄當前溫度的最優解
              if curr_val < best_val:
                  best_seq, best_val = curr_seq, curr_val
          t *= alpha
      

      運行結果與相關圖像

      上述 10 個城市的案例,最終結果為

      best_val: 2.6906706370094136
      

      通過在上面代碼的循環中嵌入“導出數據到csv文件”的操作(這里沒有給出代碼),然后結合pandas和matplotlib等庫,可以繪制出下面圖像:

      image-20230821231608416

      這個圖像的橫坐標是迭代次數,縱坐標是指標(即路徑長度)。

      上圖的橫坐標數據中,每一個溫度記錄10000個數據,直到最終滿足外循環的結束條件。

      可以看到,隨著溫度的下降,波動在變小,并最終收斂到最優解。

      前段區間的波動一致,是因為指標本身存在上下界,即十個城市的坐標確認后,最優解和最差解是固定的。

      通過減少數據導出頻率(提高運行速度),并且將溫度的數值進行等比例縮小。將溫度和指標繪制到下面這幅圖:

      image-20230821233329899

      可以更直觀地看出溫度和指標波動的關系。

      posted @ 2023-08-21 23:40  feixianxing  閱讀(113)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品第一页一区二区| 日韩淫片毛片视频免费看| 亚洲国产精品成人综合色| 国产成人精品午夜二三区| 一区二区三区鲁丝不卡| 国产av熟女一区二区三区| 亚洲综合在线日韩av| 无码丰满人妻熟妇区| 免费无码高H视频在线观看| 国产成人精品午夜在线观看| 超清无码一区二区三区| 中文字幕亚洲综合第一页| 麻豆亚州无矿码专区视频| 亚洲精品日韩在线观看| 91中文字幕一区二区| 锡林郭勒盟| 亚洲一级特黄大片在线观看| 国产亚洲欧美在线观看三区| 亚洲国产日韩一区三区| caoporn免费视频公开| 国产在线观看黄| 国产一区二区三区小说| 国产视频精品一区 日本| 久久综合88熟人妻| 亚洲精品专区在线观看| 亚洲精品网站在线观看不卡无广告| 国产午夜精品福利免费不| 西西444www高清大胆| 99久久机热/这里只有精品| 日本免费一区二区三区| 亚洲成av人片在www鸭子| 久热这里只有精品12| 九九日本黄色精品视频| 蜜臀av一区二区精品字幕| 免费一区二区无码东京热| 激情亚洲内射一区二区三区| 国产对白老熟女正在播放| 99久久免费只有精品国产| 日韩无矿砖一线二线卡乱| 国产麻豆精品一区一区三区| 国产精品中文字幕免费|