<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python數(shù)學(xué)建模系列(八):圖論

          共 16028字,需瀏覽 33分鐘

           ·

          2021-09-06 04:31

          1 圖論模型 - Dijkstra

          Dijkstra算法能求一個(gè)頂點(diǎn)到另一頂點(diǎn)最短路徑。

          基礎(chǔ)概念

          • 無(wú)向圖:若圖中的每條邊都是沒(méi)有方向的,則稱(chēng)該圖為無(wú)向圖。
          • 有向圖:若圖中的每條邊都是有方向的,則稱(chēng)該圖為有向圖。
          • 混合圖:若圖中的部分邊是有方向的,而部分邊是無(wú)方向的,則稱(chēng)該圖為混合圖。

          樣例1

          如下圖所示,我們需要從①點(diǎn)走到⑨點(diǎn),每條邊的紅色數(shù) 字代表這條邊的長(zhǎng)度,我們?nèi)绾握业舰俚舰岬淖疃搪窂侥兀?/p>

          步驟:

          1. 將①標(biāo)記為P,其它標(biāo)記為T(mén),找出從①出發(fā)當(dāng)前最短的邊所到的點(diǎn),將該點(diǎn)的T改為P
          2. 將所有P點(diǎn)找到可以到達(dá)的T標(biāo)記點(diǎn)上最短的邊,將到達(dá)的點(diǎn)T改為P
          3. 重復(fù)步驟,指導(dǎo)終點(diǎn)的T變?yōu)镻

          過(guò)程展示:圈加數(shù)字代表每個(gè)頂點(diǎn),()內(nèi)數(shù)字代表當(dāng)前行走的距離

          ?

          1.①(0)

          2.①②(1)

          3.①②⑤(3)

          4.①②⑤(3)      ①④(3)

          5.①②⑤⑦(5)     ①④(3)

          6.①②⑤⑦⑥(6)     ①④(3)

          7.①②⑤⑦⑥(6)     ①②⑤③(6)     ①④(3)

          8.①②⑤⑦⑥(6)     ①②⑤③④(7)     ①④(3)

          9.①②⑤⑦⑥⑧(8)     ①②⑤③④(7)     ①④(3)

          10.①②⑤⑦⑥⑧(8)     ①②⑤⑦⑨(8)     ①②⑤③④(7)     ①④(3)

          ?

          「所以最短的路徑是 ① ② ⑤ ⑦ ⑨, 長(zhǎng)度為8」

          帶權(quán)鄰接矩陣:帶權(quán)鄰接矩陣是表示頂點(diǎn)相鄰關(guān)系的矩陣,例如上面那個(gè)圖的帶權(quán)鄰接矩陣如下

          ?

          注意:原PPT中有錯(cuò)誤, 點(diǎn)9 -> 點(diǎn)7 應(yīng)該為inf  (上圖已經(jīng)修改)

          ?

          每個(gè)點(diǎn)和自己的距離為0(主對(duì)角線上元素都是零)

          在圖上相鄰兩個(gè)點(diǎn)的如果是連通的,距離就是矩陣的值,無(wú)向 的關(guān)于主對(duì)角線對(duì)稱(chēng);有向的只有可以過(guò)去的路有數(shù)值

          無(wú)法連通的距離就是無(wú)窮,記為inf

          Demo代碼

          # 運(yùn)行環(huán)境:Vs Code
          # PPT中代碼有點(diǎn)錯(cuò)誤 已經(jīng)修改~ 
          # 以下代碼經(jīng)測(cè)試 可行
          from collections import defaultdict 
          from heapq import * 
          inf = 99999 # 不連通值 
          mtx_graph = [[01, inf, 3, inf, inf, inf, inf, inf],
                       [105, inf, 2, inf, inf, inf, inf],
                       [inf, inf, 01, inf, 6, inf, inf, inf],
                       [inf, inf, inf, 0, inf, 7, inf, 9, inf],
                       [inf, 23, inf, 042, inf, 8],
                       [inf, inf, 67, inf, 0, inf, 2, inf],
                       [inf, inf, inf, inf, inf, 10, inf, 3],
                       [inf, inf, inf, inf, inf, inf, 102], 
                       [inf, inf, inf, inf, 8, inf, inf, 20]]
          m_n = len(mtx_graph)#帶權(quán)連接矩陣的階數(shù) 
          edges = [] #保存連通的兩個(gè)點(diǎn)之間的距離(點(diǎn)A、點(diǎn)B、距離) 
          for i in range(m_n): 
              for j in range(m_n): 
                  if i!=j and mtx_graph[i][j]!=inf: 
                      edges.append((i,j,mtx_graph[i][j])) 

          def dijkstra(edges, from_node, to_node): 
              go_path = [] 
              to_node = to_node-1 
              g = defaultdict(list) 
              for l,r,c in edges:
                  # l:點(diǎn)A r:點(diǎn)B c:距離 
                  # 字典: 點(diǎn)A -> (距離,點(diǎn)B)
                  g[l].append((c,r)) 
              q, seen = [(0, from_node-1, ())], set()
              while q: 
                  (cost, v1, path) = heappop(q)#堆彈出當(dāng)前路徑最小成本 
                  if v1 not in seen: 
                      seen.add(v1) 
                      path = (v1, path) 
                      if v1 == to_node: 
                          break 
                      for c, v2 in g.get(v1, ()): 
                          if v2 not in seen: 
                              heappush(q, (cost+c, v2, path)) 
                          
              if v1!=to_node:   #無(wú)法到達(dá) 
                  return float('inf'), []
              if len(path)>0
                  left=path[0
                  go_path.append(left) 
                  right=path[1
                  while len(right)>0
                      left=right[0
                      go_path.append(left) 
                      right=right[1
                      
                  go_path.reverse() #逆序變換 
                  for i in range(len(go_path)): #標(biāo)號(hào)加1 
                      go_path[i]=go_path[i]+1 
              return cost, go_path 
          leght, path = dijkstra(edges, 19
          print('最短距離為:'+str(leght)) 
          print('前進(jìn)路徑為:'+str(path))

          運(yùn)行結(jié)果

          最短距離為:8
          前進(jìn)路徑為:[12579]

          2 圖論模型-Floyd

          Floyd算法通過(guò)動(dòng)態(tài)規(guī)劃解決任意兩點(diǎn)間的最短路徑(多源最短路徑)的問(wèn)題,「可以正確處理負(fù)權(quán)的最短路徑問(wèn)題」

          關(guān)鍵原理:

          ?

          枚舉中間點(diǎn)k,找到最小的,作為的最小值

          ?

          關(guān)鍵結(jié)論:

          ?

          假設(shè)i和j之間的最短路徑上的結(jié)點(diǎn)集里(不包含i,j),編號(hào)最大的一個(gè)是x.那么在外循環(huán)k = x時(shí), 肯定得到了最小值.

          ?

          強(qiáng)歸納法 :

          ?

          設(shè)i到x中間編號(hào)最大的是x1,x到j(luò)中間編號(hào)最大的是x2.由于x是i到j(luò)中間編號(hào)最大的,那么顯然

          ?

          根據(jù)結(jié)論,時(shí)候已經(jīng)取得最小值,時(shí)候已經(jīng)取得最 小值

          那么時(shí),已經(jīng)都取得最小值.

          因此時(shí),執(zhí)行

          樣例2

          與樣例1相似,只是這次我們「求出從每一個(gè)點(diǎn)到其他點(diǎn)的最短距離和路徑」,每條邊的紅色數(shù)字代表這條邊的長(zhǎng)度。

          Demo代碼

          from collections import defaultdict 
          from heapq import * 
          import numpy as np
          inf = 99999 # 不連通值 
          mtx_graph = [[01, inf, 3, inf, inf, inf, inf, inf],
                       [105, inf, 2, inf, inf, inf, inf],
                       [inf, inf, 01, inf, 6, inf, inf, inf],
                       [inf, inf, inf, 0, inf, 7, inf, 9, inf],
                       [inf, 23, inf, 042, inf, 8],
                       [inf, inf, 67, inf, 0, inf, 2, inf],
                       [inf, inf, inf, inf, inf, 10, inf, 3],
                       [inf, inf, inf, inf, inf, inf, 102], 
                       [inf, inf, inf, inf, 8, inf, inf, 20]]
          def Floyd(graph): 
              N=len(graph) 
              A=np.array(graph)
              path=np.zeros((N,N)) 
              for i in range(0,N): 
                  for j in range(0,N): 
                      if A[i][j]!=inf: 
                          path[i][j]=j 
              for k in range(0,N): 
                  for i in range(0,N): 
                      for j in range(0,N):
                          # 原PPT這一句代碼有錯(cuò) 寫(xiě)成了 A[i][j]+A[k][j]<A[i][j]
                          # 正確應(yīng)該是:A[i][k]+A[k][j]<A[i][j]
                          if A[i][k]+A[k][j]<A[i][j]: 
                              A[i][j]=A[i][k]+A[k][j] 
                              path[i][j]=path[i][k]
              for i in range(0,N): 
                  for j in range(0,N): 
                      path[i][j]=path[i][j]+1 
              print('距離 = '
              print(A) 
              print('路徑 = '
              print(path) 

          Floyd(mtx_graph)

          運(yùn)行結(jié)果

          ?

          注意:原PPT 結(jié)果中 最后一行有錯(cuò) 應(yīng)該是 5. 5. 8. 8. 5. 8. 8. 8. 9. PPT中是:5. 5. 7.7. 5. 7. 7. 8. 9.  因?yàn)樵谧畛醯?mtx_graph 設(shè)置就錯(cuò)了:點(diǎn)9到點(diǎn)7 應(yīng)該是inf 而不是 3

          ?

          結(jié)論:

          • 從點(diǎn)1 到 點(diǎn)9 的距離為8(結(jié)果中“距離”矩陣中第一行第九列數(shù)值)
          • 路徑為【1 - 2 - 5 - 7 - 9】

          怎么看路徑呢?

          • 從最后結(jié)果中查看”路徑“矩陣
          • 點(diǎn)1 到 點(diǎn)9 首先看第一行第九列 數(shù)值為2
          • 這是中間位置2,再看第二行第九列,數(shù)值為5
          • 再看第五行第九列,數(shù)值為7
          • 再看第七行第九列,數(shù)值為9
          • 得到最終路徑【1 - 2 - 5 - 7 - 9】

          3 機(jī)場(chǎng)航線設(shè)計(jì)

          數(shù)據(jù)集來(lái)自航空業(yè),有一些關(guān)于航線的基本信息。有某段旅程的起始點(diǎn)和目的地。還有一些列表示每段旅程的到達(dá)和起飛時(shí)間。這個(gè)數(shù)據(jù)集非常適合作為圖進(jìn)行分析。想象一下通過(guò)航線(邊)連接的幾個(gè)城市(節(jié)點(diǎn))。

          如果你是航空公司,你可以問(wèn)如下幾個(gè)問(wèn)題:

          • 從A到B的最短途徑是什么?分別從距離和時(shí)間角度考慮。
          • 有沒(méi)有辦法從C到D?
          • 哪些機(jī)場(chǎng)的交通最繁忙?
          • 哪個(gè)機(jī)場(chǎng)位于大多數(shù)其他機(jī)場(chǎng)“之間”?這樣它就可以變成當(dāng)?shù)氐囊粋€(gè)中轉(zhuǎn)站。

          0、Airlines.csv數(shù)據(jù)

          在這里插入圖片描述

          1、數(shù)據(jù)導(dǎo)入、觀察變量

          import numpy as np 
          import pandas as pd 
          data = pd.read_csv('../Profile/Airlines.csv'
          data.shape #數(shù)據(jù)大小 

          # (100, 16) 100行16列

          運(yùn)行結(jié)果「查看各個(gè)變量的類(lèi)型」

          data.dtypes # 各變量的類(lèi)型

          運(yùn)行結(jié)果

          在這里插入圖片描述

          2、數(shù)據(jù)清洗

          #將sched_dep_time轉(zhuǎn)換為'std'—預(yù)定的出發(fā)時(shí)間 
          data['std'] = data.sched_dep_time.astype(str).str.replace('(\d{2}$)''') + ':' + data.sched_dep_time.astype(str).str.extract('(\d{2}$)', expand=False) + ':00'
           
          #將sched_arr_time轉(zhuǎn)換為“sta”—預(yù)定到達(dá)時(shí)間
          data['sta'] = data.sched_arr_time.astype(str).str.replace('(\d{2}$)''') + ':' + data.sched_arr_time.astype(str).str.extract('(\d{2}$)', expand=False) + ':00'
           
          #將dep_time轉(zhuǎn)換為'atd' -實(shí)際出發(fā)時(shí)間 
          data['atd'] = data.dep_time.fillna(0).astype(np.int64).astype(str).str.replace('(\d{2}$)''') + ':' + data.dep_time.fillna(0).astype(np.int64).astype(str).str.extract('(\d{2}$)', expand=False) + ':00'
           
          #將arr_time轉(zhuǎn)換為'ata' -實(shí)際到達(dá)時(shí)間
          data['ata'] = data.arr_time.fillna(0).astype(np.int64).astype(str).str.replace('(\d{2}$)''') + ':' + data.arr_time.fillna(0).astype(np.int64).astype(str).str.extract('(\d{2}$)', expand=False) + ':00'

          3、時(shí)間信息合并

          data['date'] = pd.to_datetime(data[['year''month''day']]) 
          data = data.drop(columns = ['year''month''day']) 

          4、創(chuàng)建圖

          import networkx as nx
           
          FG = nx.from_pandas_edgelist(data, source='origin', target='dest', edge_attr=True,)
          # 查看所有節(jié)點(diǎn) 
          FG.nodes()

          運(yùn)行結(jié)果

          #NodeView(('EWR', 'MEM', 'LGA', 'FLL', 'SEA', 'JFK', 'DEN', 'ORD', 'MIA', 'PBI', 'MCO', 'CMH', 'MSP', 'IAD', 'CLT', 'TPA', 'DCA', 'SJU', 'ATL', 'BHM', 'SRQ', 'MSY', 'DTW', 'LAX', 'JAX', 'RDU', 'MDW', 'DFW', 'IAH', 'SFO', 'STL', 'CVG', 'IND', 'RSW', 'BOS', 'CLE'))

          「查詢圖中的所有邊」

          # 查看所有邊 
          FG.edges()

          運(yùn)行結(jié)果

          #EdgeView([('EWR', 'MEM'), ('EWR', 'SEA'), ('EWR', 'MIA'), ('EWR', 'ORD'), ('EWR', 'MSP'), ('EWR', 'TPA'), ('EWR', 'MSY'), ('EWR', 'DFW'), ('EWR', 'IAH'), ('EWR', 'SFO'), ('EWR', 'CVG'), ('EWR', 'IND'), ('EWR', 'RDU'), ('EWR', 'IAD'), ('EWR', 'RSW'), ('EWR', 'BOS'), ('EWR', 'PBI'), ('EWR', 'LAX'), ('EWR', 'MCO'), ('EWR', 'SJU'), ('LGA', 'FLL'), ('LGA', 'ORD'), ('LGA', 'PBI'), ('LGA', 'CMH'), ('LGA', 'IAD'), ('LGA', 'CLT'), ('LGA', 'MIA'), ('LGA', 'DCA'), ('LGA', 'BHM'), ('LGA', 'RDU'), ('LGA', 'ATL'), ('LGA', 'TPA'), ('LGA', 'MDW'), ('LGA', 'DEN'), ('LGA', 'MSP'), ('LGA', 'DTW'), ('LGA', 'STL'), ('LGA', 'MCO'), ('LGA', 'CVG'), ('LGA', 'IAH'), ('FLL', 'JFK'), ('SEA', 'JFK'), ('JFK', 'DEN'), ('JFK', 'MCO'), ('JFK', 'TPA'), ('JFK', 'SJU'), ('JFK', 'ATL'), ('JFK', 'SRQ'), ('JFK', 'DCA'), ('JFK', 'DTW'), ('JFK', 'LAX'), ('JFK', 'JAX'), ('JFK', 'CLT'), ('JFK', 'PBI'), ('JFK', 'CLE'), ('JFK', 'IAD'), ('JFK', 'BOS')])
          在這里插入圖片描述

          「計(jì)算圖的平均邊密度」

          #注意我們的100行數(shù)據(jù)都來(lái)自3個(gè)機(jī)場(chǎng)
          nx.draw_networkx(FG, with_labels=True
          nx.algorithms.degree_centrality(FG) 

          # 圖的平均邊密度 
          nx.density(FG)

          # 0.09047619047619047

          運(yùn)行結(jié)果(對(duì)圖進(jìn)行可視化)「求圖中所有路徑的平均最短路徑長(zhǎng)度」

          #圖中所有路徑的平均最短路徑長(zhǎng)度
          nx.average_shortest_path_length(FG) 

          # 2.36984126984127

          運(yùn)行結(jié)果

          「對(duì)于一個(gè)度為k的節(jié)點(diǎn)-求的鄰居度的平均值」

          #對(duì)于一個(gè)度為k的節(jié)點(diǎn)-它的鄰居度的平均值是多少
          nx.average_degree_connectivity(FG) # For a node of degree k - What is the average of its neighbours' degree?

          #{20: 1.95, 1: 19.307692307692307, 2: 19.0625, 17: 2.0588235294117645, 3: 19.0}

          運(yùn)行結(jié)果

          在這里插入圖片描述

          5、計(jì)算航線

          # 找出所有 JAX 到 DFW 的航線
          for path in nx.all_simple_paths(FG, source='JAX', target='DFW'):
              print(path)

          #找出從JAX到DFW的dijkstra路徑。
          dijpath = nx.dijkstra_path(FG, source='JAX', target='DFW')
          dijpath # ['JAX', 'JFK', 'SEA', 'EWR', 'DFW'] 下圖中的最后一行

          運(yùn)行結(jié)果

          「從所有航線中找出 飛行時(shí)間最短的路徑」

          # 從所有航線中找出 飛行時(shí)間最短的路徑
          shortpath = nx.dijkstra_path(FG, source='JAX', target='DFW', weight='air_time')
          shortpath
          # ['JAX', 'JFK', 'BOS', 'EWR', 'DFW']

          運(yùn)行結(jié)果:

          注意事項(xiàng)

          • 起始點(diǎn)和目的地可以作為節(jié)點(diǎn),其他信息應(yīng)當(dāng)作為節(jié)點(diǎn)或邊屬性;單條邊可以被認(rèn)為是一段旅程。這樣的旅程將有不同的時(shí)間,航班號(hào),飛機(jī)尾號(hào)等相關(guān)信息。
          • 注意到年,月,日和時(shí)間信息分散在許多列;想創(chuàng)建一 個(gè)包含所有這些信息的日期時(shí)間列,還需要將預(yù)計(jì)的 (scheduled)和實(shí)際的(actual)到達(dá)離開(kāi)時(shí)間分開(kāi);最終 應(yīng)該有4個(gè)日期時(shí)間列(預(yù)計(jì)到達(dá)時(shí)間、預(yù)計(jì)起飛時(shí)間、 實(shí)際到達(dá)時(shí)間和實(shí)際起飛時(shí)間)
          • 時(shí)間格式問(wèn)題
          • 數(shù)據(jù)類(lèi)型問(wèn)題
          • NaN值的麻煩

          結(jié)語(yǔ)

          學(xué)習(xí)來(lái)源:B站及其課堂PPT,對(duì)其中代碼進(jìn)行了復(fù)現(xiàn)

          ?

          https://www.bilibili.com/video/BV12h411d7Dm

          PPT中錯(cuò)誤有點(diǎn)多 用了挺久的時(shí)間學(xué)習(xí)原理找錯(cuò)誤 哎~

          以上代碼均已運(yùn)行成功!環(huán)境:Vs Code

          ?

          「文章僅作為學(xué)習(xí)筆記,記錄從0到1的一個(gè)過(guò)程」

          希望對(duì)您有所幫助,如有錯(cuò)誤歡迎小伙伴指正~

          瀏覽 82
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  岛国在线看片 | 韩国三级电影久久久 | 婷婷亚洲五月色综 | AA片免费看 | 天堂操屄 |