【问题标题】:Multistage manufacturing and sales model in graph图中的多阶段制造和销售模型
【发布时间】:2014-11-14 17:47:20
【问题描述】:

这是一个公司制造和销售流程模型的简化可重现示例,其中包含 R 中的图形。

library(igraph)

# Create graph
graph= graph.formula(
  R --+ P1,
  P1 --+ M1,
  R --+ P2,
  P2 --+ M2,
  P1 --+ P3,
  P2 --+ P3,
  P3 --+ M2,
  R --+ P4,
  P3 --+ P5,
  P4 --+ P5,
  P5 --+ M3,
  P5 --+ M4
  )

# Change colors for pretty plot
V(graph)$color= "gray"
V(graph)[name== "R"]$color= "cyan"
V(graph)[grepl(x= name, pattern= "M")]$color= "green"
V(graph)[name %in% c("P1", "P2", "P4")]$color= "red"

# Add sales volume as attribute and add to edge label in plot
E(graph)[4]$sales= 100
E(graph)[4]$label= paste("Sales:\n", E(graph)[4]$sales, "tons")
E(graph)[6]$sales= 200
E(graph)[6]$label= paste("Sales:\n", E(graph)[6]$sales, "tons")
E(graph)[8]$sales= 500
E(graph)[8]$label= paste("Sales:\n", E(graph)[8]$sales, "tons")
E(graph)[11]$sales= 1000
E(graph)[11]$label= paste("Sales:\n", E(graph)[11]$sales, "tons")
E(graph)[12]$sales= 2000
E(graph)[12]$label= paste("Sales:\n", E(graph)[12]$sales, "tons")

# Add bill of material share as attribute and add to edge label in plot
E(graph)[1:3]$share= 1.0
E(graph)[1:3]$label= paste("Share:\n", E(graph)[1:3]$share*100, "%")
E(graph)[7]$share= 0.8
E(graph)[7]$label= paste("Share:\n", E(graph)[7]$share*100, "%")
E(graph)[5]$share= 1 - 0.8
E(graph)[5]$label= paste("Share:\n", E(graph)[5]$share*100, "%")
E(graph)[9]$share= 0.4
E(graph)[9]$label= paste("Share:\n", E(graph)[9]$share*100, "%")
E(graph)[10]$share= 1 - 0.4
E(graph)[10]$label= paste("Share:\n", E(graph)[10]$share*100, "%")

# Add preliminary NA vol attribute to nodes and add label in plot
V(graph)$vol= NA
V(graph)$label= paste(V(graph)$name, "\nVolume:\n", V(graph)$vol, "tons")

# Plot
E(graph)$label.cex=0.8
V(graph)$label.cex=0.8
V(graph)$size=20
layout= layout.reingold.tilford(graph, root=1)
layout[3,2]=0
layout[5,2]=0
plot(graph, layout= layout)

模型网络由以下组件组成:

  • R:制作产品所需的青色原料P1, P2, P4
  • P1...P5:红色产品直接从R 一步制成(P1, P2, P4)或作为多阶段制成品(P3, P5)。每个产品都有一个带有配方的物料清单。
  • M...P1...5 产品销售到的绿色市场。唯一的例外是P4,它没有出售,它只是作为P5 的前身(与P3 结合使用)。

该网络中边缘的已知属性是:

  • Sales:以吨为单位的 P1, P2, P3, P5 对市场 M1, M2, M3, M4 的销量。
  • 配方Share:制造特定产品所需的前体量(百分比)。示例:制作 1 吨P1, P2, P4 需要 1 吨原材料(因此分享 100%)。需要 10 吨 P3 8 吨 (=80%) P2 和 2 吨 (=20%) P1

我正在寻找一种解决方案来计算节点产品 P1 ... P5 和原材料 R 的体积属性 vol。目前它们设置为NAvol 应与销售量和产品配方的份额保持一致。

评论:我正在寻找一个通用的解决方案,它既适用于这个简化的示例,也适用于更复杂(更多节点和更多制造阶段)的现实世界模型。我在考虑一种多级传播算法。首先sales 数据将被聚合以产生产品顶点vol 属性的产品被销售到市场。然后另一个步骤将根据share 计算上游的要求,以使产品达到上一步的产量,依此类推。一个通用的解决方案超出了我的R 知识。任何想法如何完成任务?

【问题讨论】:

    标签: r igraph


    【解决方案1】:

    经过大量的实验,看起来我有了第一个解决方案。可重现的例子可以用它来解决。到目前为止还没有在现实世界的复杂案例中进行测试。

    1.重新编码一下任务:

    library(igraph)
    
    # Create graph
    graph= graph.formula(
      R --+ P1,
      P1 --+ M1,
      R --+ P2,
      P2 --+ M2,
      P1 --+ P3,
      P2 --+ P3,
      P3 --+ M2,
      R --+ P4,
      P3 --+ P5,
      P4 --+ P5,
      P5 --+ M3,
      P5 --+ M4
      )
    
    # Change colors for pretty plot
    V(graph)$color= "gray"
    V(graph)[name== "R"]$color= "cyan"
    V(graph)[grepl(x= name, pattern= "M")]$color= "green"
    V(graph)[name %in% c("P1", "P2", "P4")]$color= "red"
    
    # Add sales volume as attribute and add to edge label in plot
    E(graph)$vol= NA # prefill
    E(graph)[4]$vol= 100
    E(graph)[6]$vol= 200
    E(graph)[8]$vol= 500
    E(graph)[11]$vol= 1000
    E(graph)[12]$vol= 2000
    
    # Add bill of material share as attribute and add to edge label in plot
    E(graph)[1:3]$share= 1.0
    E(graph)[7]$share= 0.8
    E(graph)[5]$share= 1 - 0.8
    E(graph)[9]$share= 0.4
    E(graph)[10]$share= 1 - 0.4
    
    # Add preliminary NA vol attribute to nodes and add label in plot
    V(graph)$vol= 0
    
    # Plot
    update.labels= function(graph){
      E(graph)[4]$label= paste("Vol:\n", E(graph)[4]$vol, "tons")
      E(graph)[6]$label= paste("Vol:\n", E(graph)[6]$vol, "tons")
      E(graph)[8]$label= paste("Vol:\n", E(graph)[8]$vol, "tons")
      E(graph)[11]$label= paste("Vol:\n", E(graph)[11]$vol, "tons")
      E(graph)[12]$label= paste("Vol:\n", E(graph)[12]$vol, "tons")
      E(graph)[1:3]$label= paste("Share:\n", E(graph)[1:3]$share*100, "%", "\nVol:\n", E(graph)[1:3]$vol, "tons")
      E(graph)[7]$label= paste("Share:\n", E(graph)[7]$share*100, "%", "\nVol:\n", E(graph)[7]$vol, "tons")
      E(graph)[5]$label= paste("Share:\n", E(graph)[5]$share*100, "%", "\nVol:\n", E(graph)[5]$vol, "tons")
      E(graph)[9]$label= paste("Share:\n", E(graph)[9]$share*100, "%", "\nVol:\n", E(graph)[9]$vol, "tons")
      E(graph)[10]$label= paste("Share:\n", E(graph)[10]$share*100, "%", "\nVol:\n", E(graph)[10]$vol, "tons")
      V(graph)$label= paste(V(graph)$name, "\nVolume:\n", V(graph)$vol, "tons")
      graph
    }
    graph= update.labels(graph)
    E(graph)$label.cex=0.8
    V(graph)$label.cex=0.8
    V(graph)$size=20
    layout= layout.reingold.tilford(graph, root=1)
    layout[3,2]=0
    layout[5,2]=0
    plot(graph, layout= layout)
    

    解决方案:

    # Aggregate sales volumes to markets
    this.vertices.names= V(graph)[grepl(x=name, pattern = "M")]$name
    for (i in this.vertices.names) {
      V(graph)[name== i]$vol= sum(E(graph)[to(i)]$vol, na.rm=T)
    }
    
    # Calculate volumes along the network
    # do stepwise from farthest nodes to nearest (origin is "R")
    # 1.step: aggregate "from" edge vol attributes to product node vol attribute
    # 2.step: distribute node vol attribute to "to" edge vol attribute by vol of node * share of edge 
    
    # Function to sort nodes even if they have same distance from root
    max.out.edges= function(graph, from.node.name) {
      max(shortest.paths(graph= graph, v= V(graph)[name==from.node.name], mode="out")
          [is.finite(shortest.paths(graph= graph, v= V(graph)[name==from.node.name], mode="out"))]) 
    }
    
    # Function to create a list of nodes lists sorted with decending distance from root
    list.farthest.nodes= function(graph, from.node.name) {
      ans= list()
      sp= shortest.paths(graph= graph, v= V(graph)[name==from.node.name], mode="out")
      max.distance= max(sp[is.finite(sp)])  
      for (i in 0:max.distance-1) {
        nodes= sapply(dimnames(sp)[[2]][which(sp==max.distance-i)], function(x) max.out.edges(graph, x), simplify= T)
        ans= c(ans, list (names(nodes[order(nodes)])))
      }
      ans[[1]]= NULL
      ans[[max.distance+1]]= "R"
      ans
    }
    
    
    farthest.nodes= list.farthest.nodes(graph, "R")
    
    for (i in farthest.nodes) {
      print(paste("Levels:", i))
      for (j in i) {
        print(paste("Single Level",j))
        if (!grepl(x=j, pattern="M")) {
          V(graph)[name== j]$vol= V(graph)[name== j]$vol + sum(E(graph)[from(j)]$vol, na.rm=T)
          if (!grepl(x=j, pattern="R")) {
            E(graph)[to(j)]$vol= E(graph)[to(j)]$share * V(graph)[name== j]$vol        
          }
        }
      }  
    }
    
    graph= update.labels(graph); plot(graph, layout=layout)
    

    【讨论】:

      猜你喜欢
      • 2021-08-16
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 2017-06-19
      • 1970-01-01
      相关资源
      最近更新 更多