云计算百科
云计算领域专业知识百科平台

python的先进制造技术工业场景模拟第二十九篇:使用Networkx构建并行工程协同网络图,节点包含设计,工艺,加工,质检工程师。

周五下午,技术部会议室。

"这批新夹具从设计到首件合格,走了 23 天,"项目经理老刘把甘特图投影在墙上,"设计 5 天,工艺 4 天,加工 8 天,质检 6 天——看起来各干各的,串行排队。可实际上设计改了第三版的时候工艺就已经在审第二版了,加工那边提前看了三维模型在准备毛坯,质检也提前介入了公差评审。问题是这些'并行'全靠微信群里吼,没人说得清到底谁和谁在协同、协同强度多大、哪条链路是瓶颈。"

我翻了翻邮件和微信群记录。

"这有什么问题?"老刘问。

"问题是协同是隐性的,"我说,"设计改了尺寸,工艺要跟着改夹具方案,加工要重新选刀路,质检要重新定检具。这条'变更传播链'你看得见吗?哪个工程师跟哪个工程师交互最多?哪次变更触发了最多的下游返工?"

"我就想干一件事,"老刘说,"把设计、工艺、加工、质检四个角色的协同关系画出来——谁跟谁沟通最多、每次沟通涉及哪些变更、变更传播了几跳才稳定。我想知道并行工程里到底哪条协同链路最活跃、哪个人是枢纽节点。"

"比如设计改了定位销孔径,工艺要改定位方案,加工要换钻头,质检要换塞规,"我接话,"这就是一条传播链:设计→工艺→加工→质检,四跳。如果设计改了三次才定稿,每次都全链路传播,那就是 12 次交互。把这些交互频次建成网络图,谁的度数最高谁就是枢纽。"

"对,"老刘点头,"还有,我想看'变更传播深度'——有的变更只影响工艺,有的变更一路传到质检。传播越深的变更,说明前期设计评审没做到位。最好还能聚类,看哪些工程师是一个'协同社区'。"

"用 networkx 建四角色协同网络,节点是工程师,边是协同交互频次,边权=交互次数,节点大小=度数中心性,"我开工程,"pandas 管协同日志,numpy 算中心性指标,scipy 做社区发现后的模块度检验,scikit-learn 对工程师做聚类分群,matplotlib 画网络图+传播深度直方图。数据自包含,合成一批并行工程协同记录,下载就能跑。"

敲了行原型:

G.add_edge("设计-张三", "工艺-李四", weight=12, changes=["孔径变更","公差调整"])

centrality = nx.degree_centrality(G)

communities = nx.community.greedy_modularity_communities(G)

 

"完整版用 OOP 封好,"我说,"一个类管协同日志加载,一个类建网络,一个类算中心性,一个类做社区发现,一个类分析变更传播,一个类出图。输出协同网络图、枢纽节点排名、社区划分、变更传播深度分布,存 results/。"

老刘凑近看:"那以后看报告:工艺-李四是枢纽(度数 8,介数中心性最高),设计-张三和传播深度最深的变更链(平均 3.2 跳),四个工程师形成两个社区(设计和工艺一组、加工和质检一组),模块度 0.42。说明设计和工艺黏性够,但加工和质检之间协同偏弱,变更到加工就断了,质检只能被动等结果。"

"对,"我接话,"并行工程不是'同时开工'就完了,是信息流要通畅。网络图就是信息流的 X 光片。数字孪生里协同设计平台要做流程优化,这张网络就是现状基线。"

 

一、实际应用场景(真实痛点)

 

场景设定:多品种工装夹具开发项目,采用并行工程模式,设计/工艺/加工/质检四角色同步推进。协同依赖微信群、邮件、口头沟通,无结构化记录。项目经理无法量化协同强度、识别信息孤岛、定位变更传播瓶颈。

 

现场原话(叙事化):

 

"不是我们不并行,"老刘说,"是并行了但看不见。设计改了个尺寸,工艺那边不知道,照样按旧图做方案,等发现了已经白干了两天。后来我们规定'设计变更必须通知工艺和加工',可通知了没跟踪,质检那边还是最后才知道。我想知道到底谁跟谁协同最密、哪次变更传播最远、哪个人是信息黑洞。"

"还有社区问题,"老刘补充,"设计三个人、工艺两个、加工三个、质检两个,一共十个人。我感觉设计和工艺是一伙的,加工自己玩,质检最后才进来。可这是感觉,我要数据证明,才能调整人员搭配。"

核心矛盾:"隐式协同交互流水" 与 "协同网络拓扑 + 中心性分析 + 社区发现 + 变更传播深度 + 信息孤岛定位" 之间的断层。

 

二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)

 

《先进制造技术》模块 本篇痛点对应

先进制造新模式:并行工程(CE)、协同设计、DFX 多角色协同网络建模与优化

先进制造技术基础:系统工程、信息流分析 协同交互的结构化量化

CAD/CAM技术:设计-工艺-制造信息集成 变更传播链分析

智能制造与数字孪生:协同平台信息流仿真 网络拓扑作为流程优化基线

FMS与先进生产管理:项目管理、并行任务调度 枢纽节点识别与资源调配

 

一句话总结:我们需要一个"并行工程多角色协同网络分析程序",用 

"networkx" 建图+中心性+社区发现,

"pandas" 管协同日志,

"numpy" 算传播深度,

"scipy" 做模块度评估,

"scikit-learn" 聚类工程师分群,实现从"微信群吼"到"协同网络拓扑 + 枢纽定位 + 信息孤岛识别"。

 

三、核心逻辑讲解(大白话)

 

3.1 问题本质:把协同想成"朋友圈"

 

把并行工程团队想成一个微信群:

 

* 节点 = 群成员(设计张三、工艺李四、加工王五、质检赵六…)

* 边 = 聊天频次(张三@李四 12 次 = 边权 12)

* 度数 = 谁最活跃(被 @ 最多的人 = 枢纽)

* 介数中心性 = 谁是不可替代的中间人(绕过他就断联)

* 社区 = 谁跟谁是一伙的(设计+工艺黏一起,加工+质检各玩各)

* 变更传播 = 一条消息从设计发出,经过几跳才到质检(跳数=传播深度)

* 信息孤岛 = 度数低+介数低+不在主社区的节点(被遗忘的人)

 

3.2 业务逻辑 → 代码映射

 

导入协同交互日志

   │

   ▼ CollabLoader (pandas)

读取 CSV:

  source, target, role_source, role_target,

  interaction_count, change_type, change_depth

  校验角色合法(设计/工艺/加工/质检)

   │

   ▼ CollabNetworkBuilder (networkx)

建图:

  节点=工程师,边=交互频次

  节点属性=角色,边属性=变更类型+传播深度

   │

   ▼ CentralityAnalyzer (networkx/numpy)

中心性计算:

  度数中心性(谁最活跃)

  介数中心性(谁是不可替代的桥)

  接近中心性(谁离所有人最近)

  特征向量中心性(谁跟重要的人连接)

   │

   ▼ CommunityDetector (networkx)

社区发现:

  greedy_modularity_communities

  模块度评估(scipy)

   │

   ▼ PropagationAnalyzer

变更传播分析:

  按变更类型统计传播深度分布

  找最深传播链

   │

   ▼ CollabVisualizer (matplotlib)

可视化:

  1. 协同网络拓扑图(节点大小=度数, 颜色=角色, 边宽=频次)

  2. 中心性雷达图(枢纽节点对比)

  3. 社区分布条形图

  4. 变更传播深度直方图

  5. 角色间交互热力图

   │

   ▼ SyntheticCollabGenerator (numpy)

合成数据:

  10工程师×4角色,交互频次幂律分布

  含枢纽节点+信息孤岛

  变更传播深度 1~4 跳

 

3.3 为什么需要网络分析

 

方法 问题

数邮件/微信 只能看自己参与的,看不到全局

画组织架构图 是汇报关系,不是协同关系

网络拓扑 真实信息流,谁跟谁真在协作

 

3.4 分析前后对比

 

维度 现状 本程序

协同强度 感觉 边权定量

枢纽人物 领导指定 中心性排名

信息孤岛 没人提 低度数+低介数自动识别

社区划分 凭经验 模块度优化自动聚类

变更传播 无记录 传播深度分布+最长链

 

四、OOP 代码实现

 

4.1 项目结构

 

parallel_collab_network/

├── parallel_collab_network/

│ ├── __init__.py

│ ├── collab_loader.py # 协同日志加载

│ ├── network_builder.py # 网络构建

│ ├── centrality_analyzer.py # 中心性分析

│ ├── community_detector.py # 社区发现

│ ├── propagation_analyzer.py # 变更传播分析

│ ├── visualizer.py # 可视化

│ └── synthetic_data.py # 合成数据

├── tests/

│ ├── __init__.py

│ └── test_collab_network.py

├── results/

│ ├── collab_network.png

│ ├── centrality_radar.png

│ ├── community_bar.png

│ ├── propagation_hist.png

│ ├── role_heatmap.png

│ ├── centrality_ranking.csv

│ ├── communities.csv

│ ├── propagation_depth.csv

│ └── collab_report.txt

└── run_collab_network.py

 

4.2 核心源码

 

<details>

 

<summary></summary>

 

"""并行工程协同日志加载器"""

 

import pandas as pd

from pathlib import Path

from typing import Optional

 

VALID_ROLES = {"设计", "工艺", "加工", "质检"}

 

 

class CollabLoader:

    """加载协同交互日志"""

 

    def __init__(self, filepath: str = "collab_log.csv",

                 encoding: str = "utf-8"):

        self.filepath = Path(filepath)

        self.encoding = encoding

        self._raw: Optional[pd.DataFrame] = None

 

    def load(self) -> pd.DataFrame:

        if not self.filepath.exists():

            raise FileNotFoundError(f"文件不存在: {self.filepath}")

        self._raw = pd.read_csv(self.filepath, encoding=self.encoding)

 

        rename = {}

        for tgt, al in {

            "source": ["source", "发起方", "from"],

            "target": ["target", "接收方", "to"],

            "role_source": ["role_source", "发起角色", "role_from"],

            "role_target": ["role_target", "接收角色", "role_to"],

            "interaction_count": ["interaction_count", "交互次数", "count"],

            "change_type": ["change_type", "变更类型", "change"],

            "change_depth": ["change_depth", "传播深度", "depth"],

        }.items():

            if tgt not in self._raw.columns:

                for a in al:

                    if a in self._raw.columns:

                        rename[a] = tgt

                        break

        self._raw = self._raw.rename(columns=rename)

 

        req = ["source", "target", "role_source", "role_target",

               "interaction_count"]

        miss = [c for c in req if c not in self._raw.columns]

        if miss:

            raise ValueError(f"缺少必要列: {miss}")

 

        self._raw["interaction_count"] = pd.to_numeric(

            self._raw["interaction_count"], errors="coerce").fillna(1).astype(int)

        self._raw["change_depth"] = pd.to_numeric(

            self._raw.get("change_depth"), errors="coerce").fillna(0).astype(int)

        self._raw["change_type"] = self._raw.get("change_type", "无变更").fillna("无变更")

 

        # 角色校验

        for col in ["role_source", "role_target"]:

            if col not in self._raw.columns:

                self._raw[col] = "未知"

            self._raw[col] = self._raw[col].str.strip()

        return self._raw.reset_index(drop=True)

 

</details>

 

<details>

 

<summary></summary>

 

"""协同网络构建 (networkx)"""

 

import networkx as nx

import pandas as pd

from typing import Optional

 

 

class CollabNetworkBuilder:

    """从协同日志构建有向/无向图"""

 

    def __init__(self, directed: bool = False):

        self.directed = directed

        self.G = nx.DiGraph() if directed else nx.Graph()

 

    def build(self, df: pd.DataFrame) -> nx.Graph:

        self.G.clear()

        for _, r in df.iterrows():

            src = str(r["source"])

            tgt = str(r["target"])

            # 节点属性

            self.G.add_node(src, role=str(r.get("role_source", "未知")))

            self.G.add_node(tgt, role=str(r.get("role_target", "未知")))

            # 边属性

            w = int(r["interaction_count"])

            if self.G.has_edge(src, tgt):

                self.G[src][tgt]["weight"] += w

                self.G[src][tgt]["changes"].append(str(r.get("change_type", "")))

            else:

                self.G.add_edge(src, tgt, weight=w,

                                changes=[str(r.get("change_type", ""))],

                                depth=int(r.get("change_depth", 0)))

        return self.G

 

    def basic_stats(self) -> dict:

        return {

            "nodes": self.G.number_of_nodes(),

            "edges": self.G.number_of_edges(),

            "density": round(nx.density(self.G), 4),

            "avg_degree": round(

                sum(dict(self.G.degree()).values()) / max(1, self.G.number_of_nodes()), 2

            ),

        }

 

</details>

 

<details>

 

<summary></summary>

 

"""中心性分析 (networkx/numpy)"""

 

import numpy as np

import pandas as pd

import networkx as nx

from typing import Optional, Dict, List

 

 

class CentralityAnalyzer:

    """计算多种中心性指标"""

 

    def __init__(self):

        pass

 

    def analyze(self, G: nx.Graph) -> pd.DataFrame:

        deg = nx.degree_centrality(G)

        betw = nx.betweenness_centrality(G, weight="weight", normalized=True)

        close = nx.closeness_centrality(G)

        try:

            eig = nx.eigenvector_centrality_numpy(G, weight="weight")

        except Exception:

            eig = {n: 0.0 for n in G.nodes()}

 

        rows = []

        for n in G.nodes():

            rows.append({

                "node": n,

                "role": G.nodes[n].get("role", "未知"),

                "degree_centrality": round(deg.get(n, 0), 4),

                "betweenness_centrality": round(betw.get(n, 0), 4),

                "closeness_centrality": round(close.get(n, 0), 4),

                "eigenvector_centrality": round(eig.get(n, 0), 4),

                "degree": G.degree(n),

            })

        return pd.DataFrame(rows).sort_values("degree_centrality",

                                              ascending=False).reset_index(drop=True)

 

    def hub_nodes(self, df: pd.DataFrame, top_n: int = 3) -> pd.DataFrame:

        """枢纽节点 = 介数中心性最高"""

        return df.nlargest(top_n, "betweenness_centrality").reset_index(drop=True)

 

    def info_islands(self, df: pd.DataFrame,

                     deg_thresh: float = 0.15,

                     betw_thresh: float = 0.1) -> pd.DataFrame:

        """信息孤岛 = 度数和介数都低的节点"""

        return df[

            (df["degree_centrality"] < deg_thresh) &

            (df["betweenness_centrality"] < betw_thresh)

        ].reset_index(drop=True)

 

</details>

 

<details>

 

<summary></summary>

 

"""社区发现 (networkx)"""

 

import networkx as nx

import pandas as pd

from typing import Optional, List, Dict

 

 

class CommunityDetector:

    """基于模块度优化的社区发现"""

 

    def __init__(self):

        pass

 

    def detect(self, G: nx.Graph) -> List[set]:

        """贪婪模块度社区发现"""

        if G.number_of_edges() == 0:

            return [set(G.nodes())]

        communities = nx.community.greedy_modularity_communities(G)

        return [set(c) for c in communities]

 

    def modularity(self, G: nx.Graph, communities: List[set]) -> float:

        """计算模块度"""

        if len(communities) <= 1:

            return 0.0

        return round(nx.community.modularity(G, communities), 4)

 

    def community_summary(self, G: nx.Graph,

                          communities: List[set]) -> pd.DataFrame:

        """社区汇总"""

        rows = []

        for i, comm in enumerate(communities):

            roles = {}

            for n in comm:

                r = G.nodes[n].get("role", "未知")

                roles[r] = roles.get(r, 0) + 1

            rows.append({

                "community_id": i + 1,

                "size": len(comm),

                "members": ", ".join(sorted(comm)),

                "role_distribution": ", ".join(f"{k}:{v}" for k, v in roles.items()),

                "internal_edges": sum(1 for u in comm

                                      for v in comm if u != v and G.has_edge(u, v)) // 2,

            })

        return pd.DataFrame(rows)

 

</details>

 

<details>

 

<summary></summary>

 

"""变更传播分析"""

 

import numpy as np

import pandas as pd

from collections import defaultdict

from typing import Optional

 

 

class PropagationAnalyzer:

    """分析变更传播深度和路径"""

 

    def __init__(self):

        pass

 

    def depth_distribution(self, df: pd.DataFrame) -> pd.DataFrame:

        """传播深度分布"""

        depths = df[df["change_depth"] > 0]["change_depth"]

        if depths.empty:

            return pd.DataFrame()

        dist = depths.value_counts().sort_index().reset_index()

        dist.columns = ["depth", "count"]

        dist["ratio"] = (dist["count"] / dist["count"].sum()).round(4)

        return dist

 

    def deepest_chains(self, df: pd.DataFrame,

                       top_n: int = 5) -> pd.DataFrame:

        """传播深度最大的交互"""

        sub = df[df["change_depth"] > 0].copy()

        if sub.empty:

            return pd.DataFrame()

        sub = sub.sort_values("change_depth", ascending=False).head(top_n)

        return sub[["source", "target", "change_type",

                     "change_depth", "interaction_count"]].reset_index(drop=True)

 

    def change_type_stats(self, df: pd.DataFrame) -> pd.DataFrame:

        """按变更类型统计"""

        sub = df[df["change_type"] != "无变更"].copy()

        if sub.empty:

            return pd.DataFrame()

        rows = []

        for ct, g in sub.groupby("change_type"):

            rows.append({

                "change_type": ct,

                "count": len(g),

                "avg_depth": round(g["change_depth"].mean(), 2),

                "max_depth": int(g["change_depth"].max()),

                "total_interactions": int(g["interaction_count"].sum()),

            })

        return pd.DataFrame(rows).sort_values("avg_depth",

                                              ascending=False).reset_index(drop=True)

 

</details>

 

<details>

 

<summary></summary>

 

"""可视化 (matplotlib)"""

 

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pathlib import Path

 

plt.rcParams["font.sans-serif"] = ["SimHei", "DejaVu Sans"]

plt.rcParams["axes.unicode_minus"] = False

 

 

class CollabVisualizer:

    def __init__(self, results_dir: str = "results"):

        self.results_dir = Path(results_dir)

        self.results_dir.mkdir(exist_ok=True)

        self.role_colors = {

            "设计": "#E74C3C", "工艺": "#3498DB",

            "加工": "#27AE60", "质检": "#F39C12", "未知": "#95A5A6"

        }

 

    def network_plot(self, G, centrality_df):

        fig, ax = plt.subplots(figsize=(16, 12))

        pos = nx.spring_layout(G, seed=42, k=0.8)

        # 节点颜色=角色

        nc = [self.role_colors.get(G.nodes[n].get("role", "未知"), "#999")

              for n in G.nodes()]

        # 节点大小=度数中心性

        deg_c = dict(zip(centrality_df["node"], centrality_df["degree_centrality"]))

        ns = [max(300, deg_c.get(n, 0) * 5000) for n in G.nodes()]

        # 边宽=权重

        ew = [max(0.5, G[u][v].get("weight", 1) / 3) for u, v in G.edges()]

 

        nx.draw_networkx_nodes(G, pos, node_color=nc, node_size=ns,

                               ax=ax, alpha=0.9, edgecolors="black", linewidths=1.0)

        nx.draw_networkx_edges(G, pos, width=ew, alpha=0.35, ax=ax,

                                edge_color="#7F8C8D")

        nx.draw_networkx_labels(G, pos, font_size=8, ax=ax,

                                 font_weight="bold")

        # 图例

        for role, color in self.role_colors.items():

            ax.plot([], [], "o", color=color, label=role, markersize=10)

        ax.legend(loc="upper left", framealpha=0.9)

        ax.set_title("并行工程协同网络\\n(颜色=角色 大小=度数中心性 线宽=交互频次)",

                     fontsize=14, fontweight="bold")

        ax.axis("off")

        plt.tight_layout()

        plt.savefig(self.results_dir / "collab_network.png",

                     dpi=150, bbox_inches="tight")

        plt.close()

 

    def centrality_radar(self, centrality_df, top_n=5):

        sub = centrality_df.head(top_n)

        metrics = ["degree_centrality", "betweenness_centrality",

                    "closeness_centrality", "eigenvector_centrality"]

        labels = ["度数", "介数", "接近", "特征向量"]

        angles = np.linspace(0, 2 * np.pi, len(metrics), endpoint=False).tolist()

        angles += angles[:1]

 

        fig, ax = plt.subplots(figsize=(10, 10), subplot_kw=dict(polar=True))

        for _, r in sub.iterrows():

            vals = [r[m] for m in metrics]

            max_val = centrality_df[m].max() if m in centrality_df.columns else 1

            vals = [v / max(centrality_df[m].max(), 1e-6) for m in metrics]

            vals += vals[:1]

            ax.plot(angles, vals, "o-", label=r["node"], linewidth=2)

            ax.fill(angles, vals, alpha=0.1)

        ax.set_xticks(angles[:-1])

        ax.set_xticklabels(labels, fontsize=12)

        ax.set_title(f"Top{top_n} 枢纽节点中心性雷达图", fontsize=14, fontweight="bold")

        ax.legend(loc="upper right", bbox_to_anchor=(1.3, 1.1))

        plt.tight_layout()

        plt.savefig(self.results_dir / "centrality_radar.png",

                     dpi=150, bbox_inches="tight")

        plt.close()

 

    def community_bar(self, comm_df):

        if comm_df.empty:

            return

        fig, ax = plt.subplots(figsize=(10, 6))

        x = range(len(comm_df))

        ax.bar(x, comm_df["size"], color="#3498DB", alpha=0.8)

        ax.set_xticks(list(x))

        ax.set_xticklabels([f"C{i+1}" for i in range(len(comm_df))], fontsize=11)

        ax.set_ylabel("社区人数")

        ax.set_title("社区规模分布", fontsize=14, fontweight="bold")

        for i, r in comm_df.iterrows():

            ax.text(i, r["size"] + 0.1, r["role_distribution"],

                    ha="center", fontsize=8)

        ax.grid(axis="y", alpha=0.3)

        plt.tight_layout()

        plt.savefig(self.results_dir / "community_bar.png",

                     dpi=150, bbox_inches="tight")

        plt.close()

 

    def propagation_hist(self, depth_df):

        if depth_df.empty:

            return

        fig, ax = plt.subplots(figsize=(9, 6))

        ax.bar(depth_df["depth"].astype(str), depth_df["count"],

               color="#E67E22", alpha=0.8)

        ax.set_xlabel("传播深度(跳数)")

        ax.set_ylabel("变更次数")

        ax.set_title("变更传播深度分布", fontsize=14, fontweight="bold")

        ax.grid(axis="y", alpha=0.3)

        total = depth_df["count"].sum()

        for _, r in depth_df.iterrows():

            pct = r["count"] / total * 100

            ax.text(str(r["depth"]), r["count"] + 0.2, f"{pct:.1f}%",

                    ha="center", fontsize=10, fontweight="bold")

        plt.tight_layout()

        plt.savefig(self.results_dir / "propagation_hist.png",

                     dpi=150, bbox_inches="tight")

        plt.close()

 

    def role_heatmap(self, df):

        """角色间交互热力图"""

        df2 = df.copy()

        crosstab = pd.crosstab(

            df2["role_source"], df2["role_target"],

            values=df2["interaction_count"], aggfunc="sum"

        ).fillna(0)

        fig, ax = plt.subplots(figsize=(8, 6))

        im = ax.imshow(crosstab.values, cmap="YlOrRd")

        ax.set_xticks(range(len(crosstab.columns)))

        ax.set_xticklabels(crosstab.columns, fontsize=11)

        ax.set_yticks(range(len(crosstab.index)))

        ax.set_yticklabels(crosstab.index, fontsize=11)

        ax.set_title("角色间交互热力图(频次)", fontsize=14, fontweight="bold")

        for i in range(len(crosstab.index)):

            for j in range(len(crosstab.columns)):

                ax.text(j, i, int(crosstab.values[i, j]),

                        ha="center", va="center", fontsize=10,

                        color="black" if crosstab.values[i, j] < crosstab.values.max()/2 else "white")

        plt.colorbar(im, ax=ax)

        plt.tight_layout()

        plt.savefig(self.results_dir / "role_heatmap.png",

                     dpi=150, bbox_inches="tight")

        plt.close()

 

</details>

 

<details>

 

<summary></summary>

 

"""合成并行工程协同数据生成器"""

 

import numpy as np

import pandas as pd

from pathlib import Path

from typing import Optional

 

 

class SyntheticCollabGenerator:

    """

    生成 10 工程师×4角色 协同日志

    角色: 设计(3人) 工艺(2人) 加工(3人) 质检(2人)

    交互频次: 幂律分布(枢纽多, 边缘少)

    变更传播: 深度1~4跳

    """

 

    def __init__(self, rng: Optional[np.random.RandomState] = None):

        self.rng = rng or np.random.RandomState(42)

 

    def generate(self, output_path: str = "collab_log.csv",

                 n_engineers: int = 10) -> pd.DataFrame:

        roles = {

            "设计": ["张工", "王工", "李工"],

            "工艺": ["赵工", "孙工"],

            "加工": ["周工", "吴工", "郑工"],

            "质检": ["钱工", "冯工"],

        }

        engineers = []

        for role, names in roles.items():

            for name in names:

                engineers.append((f"{role}-{name}", role))

 

        change_types = ["尺寸变更", "公差调整", "材料变更",

                         "表面处理变更", "装配顺序变更", "无变更"]

 

        records = []

        # 生成交互(幂律: 部分人交互多)

        for i, (s, sr) in enumerate(engineers):

            f

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

赞(0)
未经允许不得转载:网硕互联帮助中心 » python的先进制造技术工业场景模拟第二十九篇:使用Networkx构建并行工程协同网络图,节点包含设计,工艺,加工,质检工程师。
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!