Network Flows(藉助ortools)

注意事項

TypeError: in method 'SimpleMinCostFlow_SetNodeSupply', argument 3 of type 'operations_research::FlowQuantity'

如上報錯,是由於傳入AddArcWithCapacityAndUnitCost 的參數中含了 numpy.int64numpy數據類型,須要轉成內置類型 int算法

Maximum Flows

"""From Taha 'Introduction to Operations Research', example 6.4-2."""

from __future__ import print_function
from ortools.graph import pywrapgraph

def main():
  """MaxFlow simple interface example."""

  # Define three parallel arrays: start_nodes, end_nodes, and the capacities
  # between each pair. For instance, the arc from node 0 to node 1 has a
  # capacity of 20.

  start_nodes = [0, 0, 0, 1, 1, 2, 2, 3, 3]
  end_nodes = [1, 2, 3, 2, 4, 3, 4, 2, 4]
  capacities = [20, 30, 10, 40, 30, 10, 20, 5, 20]

  # Instantiate a SimpleMaxFlow solver.
  max_flow = pywrapgraph.SimpleMaxFlow()
  # Add each arc.
  for i in range(0, len(start_nodes)):
    max_flow.AddArcWithCapacity(start_nodes[i], end_nodes[i], capacities[i])

  # Find the maximum flow between node 0 and node 4.
  if max_flow.Solve(0, 4) == max_flow.OPTIMAL:
    print('Max flow:', max_flow.OptimalFlow())
    print('')
    print('  Arc    Flow / Capacity')
    for i in range(max_flow.NumArcs()):
      print('%1s -> %1s   %3s  / %3s' % (
          max_flow.Tail(i),
          max_flow.Head(i),
          max_flow.Flow(i),
          max_flow.Capacity(i)))
    print('Source side min-cut:', max_flow.GetSourceSideMinCut())
    print('Sink side min-cut:', max_flow.GetSinkSideMinCut())
  else:
    print('There was an issue with the max flow input.')

if __name__ == '__main__':
  main()

Minimum Cost Flows

task

欲構造data center的traffic變換仿真,輸入爲二維矩陣,根據論文中的算法給定一些限定條件,求解獲得新的拓撲結構。ide

單純算Minimum Cost Flows的Demo

與 maximum flows 問題比較,多了 unit_costs 和 suppliesoop

  • 若用強約束的 Solve() 求解,則supplies 流入總和等於流出總和,即 supplies 中元素和爲0。而且要求 source 流出的supply不能大於其全部流出links上的capacities總和。
  • 若用若約束的 SolveMaxFlowWithMinCost()求解,則沒有上述兩條限制。將以最小的成本計算最大流量。

SolveMaxFlowWithMinCost() Same as Solve(), but does not have the restriction that the supply must match the demand or that the graph has enough capacity to serve all the demand or use all the supply. This will compute a maximum-flow with minimum cost. The value of the maximum-flow will be given by MaximumFlow().rest

supply 中的負數元素即表明了 demand.code

or-tools 中的 AddArcWithCapacityAndUnitCost 支持有向圖,節點索引和容量(capacity)必須是非負的,花費 unit cost 能夠是任意整數,支持自循環和重複弧。blog

Adds a directed arc from tail to head to the underlying graph with a given capacity and cost per unit of flow. * Node indices and the capacity must be non-negative (>= 0). * The unit cost can take any integer value (even negative). * Self-looping and duplicate arcs are supported. * After the method finishes, NumArcs() == the returned ArcIndex + 1.索引

# """From Bradley, Hax, and Magnanti, 'Applied Mathematical Programming', figure 8.1."""

from __future__ import print_function
from ortools.graph import pywrapgraph

def main():
  """MinCostFlow simple interface example."""

  # Define four parallel arrays: start_nodes, end_nodes, capacities, and unit costs
  # between each pair. For instance, the arc from node 0 to node 1 has a
  # capacity of 15 and a unit cost of 4.

  start_nodes = [ 0, 0,  1, 1,  1,  2, 2,  3, 4]
  end_nodes   = [ 1, 2,  2, 3,  4,  3, 4,  4, 2]
  capacities  = [15, 8, 20, 4, 10, 15, 4, 20, 5]
  unit_costs  = [ 4, 4,  2, 2,  6,  1, 3,  2, 3]

  # Define an array of supplies at each node.

  supplies = [20, 0, 0, -5, -15]


  # Instantiate a SimpleMinCostFlow solver.
  min_cost_flow = pywrapgraph.SimpleMinCostFlow()

  # Add each arc.
  for i in range(0, len(start_nodes)):
    min_cost_flow.AddArcWithCapacityAndUnitCost(start_nodes[i], end_nodes[i],
                                                capacities[i], unit_costs[i])

  # Add node supplies.

  for i in range(0, len(supplies)):
    min_cost_flow.SetNodeSupply(i, supplies[i])


  # Find the minimum cost flow between node 0 and node 4.
  # if min_cost_flow.Solve() == min_cost_flow.OPTIMAL:
  if min_cost_flow.SolveMaxFlowWithMinCost() == min_cost_flow.OPTIMAL:
    print('Minimum cost:', min_cost_flow.OptimalCost())
    print('')
    print('  Arc    Flow / Capacity  Cost')
    for i in range(min_cost_flow.NumArcs()):
      cost = min_cost_flow.Flow(i) * min_cost_flow.UnitCost(i)
      print('%1s -> %1s   %3s  / %3s       %3s' % (
          min_cost_flow.Tail(i),
          min_cost_flow.Head(i),
          min_cost_flow.Flow(i),
          min_cost_flow.Capacity(i),
          cost))
  else:
    print('There was an issue with the min cost flow input.')

if __name__ == '__main__':
  main()

封裝和改造

相關文章
相關標籤/搜索