python的智能制造导论工业场景模拟第九十九篇:Networkx筛选车间网络,只保留同一条产线内设备节点,单独绘制单产线拓扑。
单产线拓扑提取:用NetworkX从车间网络中"剪"出一条产线
周一早上,自动化工程师小陈拿着一张全车间网络拓扑图,在办公室里皱着眉。
"哥,帮我看看这个。"小陈把图铺在桌上——密密麻麻的节点和连线铺满了整张A1纸,"这是全车间的设备网络拓扑,PLC、机器人、扫码枪、传感器……一共87个节点,连我自己都看不清谁跟谁是一伙的。"
"你要找什么?"我问。
"我要找装配线A的所有设备。"小陈指着图的一角,"这条线有12台设备,我想单独画一张它的拓扑图,用来做网络隔离测试——把这条线的交换机端口单独划VLAN,跟其他线隔离。"
"那不就是从这87个节点里,把属于'装配线A'的挑出来吗?"我说。
"道理是这个道理。"小陈叹气,"但拓扑数据存在Excel里,两列:'源设备'和'目标设备'。全车间所有连线混在一起。我想筛出装配线A的12台设备,还得保留它们之间的连线——不能把跨线的连线也带进来。"
"这就是子图提取的问题。"我打开编辑器,"用 NetworkX,把全车间网络建成图,然后用节点属性'产线'来筛选,一行代码就能提取子图。"
import networkx as nx
import matplotlib.pyplot as plt
# 1. 建图
G = nx.from_pandas_edgelist(df, "source", "target")
# 2. 给节点添加产线属性
for n in G.nodes():
G.nodes[n]["line"] = get_line(n) # 根据设备编号查产线
# 3. 筛选装配线A的节点
line_a_nodes = [n for n in G.nodes() if G.nodes[n]["line"] == "装配线A"]
# 4. 提取子图
G_line_a = G.subgraph(line_a_nodes)
# 5. 绘制
nx.draw(G_line_a, with_labels=True, node_color="lightblue")
"就这些?"小陈瞪大了眼睛。
"核心逻辑就这些。"我运行了一下,屏幕上出现了一张干净的拓扑图——只有12个节点,连线清晰,没有多余的跨线干扰。
"你看,"我指着图,"装配线A的12台设备,实际只有9条连线——PLC连了3台机器人,机器人各连一台扫码枪,PLC还连了上位机。拓扑一目了然。"
小陈把图导出来,直接贴到了网络改造方案里。"以前我面对的是'全网蜘蛛网',现在我看到的是'单线骨架'。"他说,"这一个
"subgraph",帮我们看见了'看不见的产线边界'。"
一、实际应用场景(真实痛点)
场景设定:车间网络管理员维护着全车间的设备网络拓扑(所有PLC、机器人、HMI、交换机等设备的连接关系),数据存储在Excel或CMDB中。在进行网络规划(VLAN划分、IP规划)、故障排查(某条产线网络异常需单独分析)或安全隔离(将一条产线的设备划入独立网络区域)时,需要从全车间拓扑中快速提取单条产线的子拓扑,排除无关设备的干扰。
现场原话(叙事化):
"我们车间有句行话:'全网拓扑是给网管看的,产线拓扑是给工程师用的。'"小陈说,"领导让我做网络安全隔离,我需要清楚地知道每条产线内部是怎么连的——哪些设备直连、哪些经过交换机、有没有跨线串线。但全车间87个节点的图,密得跟电路板似的,根本看不出产线边界。"
"那你们的网管软件不能按产线筛选吗?"我问。
"软件有分组功能,但只按IP段分,不按物理产线分。"小陈摇头,"而且导出的图不能自定义——节点位置乱七八糟,我还要手动拖。"
"所以你需要的是基于节点属性的子图提取 + 自定义布局绘制。"
"对。而且不只是画出来。"小陈补充,"我还想知道这条产线的网络特征——有多少台设备、几台交换机、网络直径多大、有没有单点故障风险(某个节点断了会导致整条线断网)。"
"那就是图分析了。"我说,"NetworkX 不光能画图,还能算连通性、找关键节点、算最短路径。"
核心矛盾:"网络管理需要清晰的单产线拓扑以实施隔离和排障"与"全车间拓扑数据混杂,缺乏按产线属性提取子图的能力"之间的冲突。需要一个"单产线拓扑提取程序",自动筛选节点、提取子图、计算网络特征并绘制清晰的拓扑图。
二、痛点分析(映射到长安大学《智能制造导论》课程模型)
《智能制造导论》模块 本篇痛点对应
概述:工业网络、信息集成 网络拓扑:车间设备网络的物理/逻辑连接结构,是信息集成的基础。
智能制造技术基础:工业以太网、现场总线 通信技术:设备间的通信依赖网络拓扑,拓扑结构影响通信可靠性和实时性。
新一代支撑技术:工业物联网(IIoT)、数字孪生 网络建模:用图模型描述设备连接关系,是数字孪生网络的简化表达。
智能工厂与智能生产:网络规划、安全隔离 网络管理:基于拓扑分析进行VLAN划分、故障域隔离。
演进范式:手工绘制拓扑 → 全量混杂 → 属性筛选子图 → 动态拓扑感知 从"一张图看全部"到"按需提取单线视图",实现网络管理的精细化。
一句话总结:我们需要构建一个"单产线拓扑提取程序",使用 NetworkX 从全车间网络图中筛选指定产线的设备节点,提取子图并绘制清晰的拓扑视图,同时计算关键网络特征。
三、核心逻辑讲解(大白话)
3.1 问题本质:把拓扑提取看成"从全家福里剪出一个人"
把拓扑提取和剪照片的关系,想象成"从一张大合照里裁出你所在的小组":
* 全车间拓扑 = 一张大合照:所有人站在一起拍照,87个人挤满画面,你分不清谁跟谁是一个部门的。
* 节点 = 照片里的人:每个人是一个设备(PLC、机器人、交换机等)。
* 连线 = 人与人之间的关系线:谁挨着谁站、谁牵着谁的手——代表设备之间的网络连接。
* 产线属性 = 部门标签:每个人胸前贴着部门牌子(装配线A、焊接线B、涂装线C)。
* 子图提取 = 按部门裁剪:把"装配线A"的所有人挑出来,他们之间的连线保留,跟其他部门人的连线自然就断了。
* NetworkX 的
"subgraph" = 自动裁剪工具:你给它一个节点列表,它自动返回一个只包含这些节点和它们之间连线的新图。
工业应用:
* 输入:边列表CSV(两列:
"source"、
"target"),节点属性CSV(设备编号、产线、设备类型等)。
* 建图:
"nx.from_pandas_edgelist()" 从边列表创建图。
* 添加属性:
"nx.set_node_attributes()" 给每个节点标注产线。
* 筛选:列表推导式选出目标产线的节点。
* 提取子图:
"G.subgraph(nodes)" 一步完成。
* 分析:
"nx.is_connected()" 检查连通性,
"nx.diameter()" 算网络直径,
"nx.degree()" 找关键节点。
3.2 业务逻辑 → 代码映射
读取全车间网络数据
│
▼ DataLoader.load()
数据加载:
1. pd.read_csv() 读取边列表和节点属性
2. 清洗数据(去重、处理孤立节点)
│
▼ TopologyBuilder.build()
建图:
1. nx.from_pandas_edgelist() 创建全车间图
2. nx.set_node_attributes() 添加产线、设备类型等属性
│
▼ SubgraphExtractor.extract()
子图提取:
1. 根据产线名称筛选节点
2. G.subgraph() 提取子图
3. 验证子图连通性
│
▼ Analyzer.analyze()
网络分析:
1. 节点数、边数统计
2. 连通性检查
3. 网络直径计算
4. 关键节点识别(度中心性)
│
▼ Visualizer.plot()
可视化:
1. 全车间拓扑(淡化显示,突出目标产线)
2. 单产线拓扑(清晰布局,按设备类型着色)
│
▼ ReportGenerator.generate_report()
生成报告:
1. 网络特征摘要
2. 关键节点列表
3. 网络优化建议
3.3 为什么用
"subgraph" 而不是直接新建图?
*
"subgraph":NetworkX 的原生子图方法,返回一个 视图(View),不复制数据,效率高。它自动保留选中节点之间的所有边,同时排除涉及非选中节点的边。
* 手动新建:遍历所有边,判断两端节点是否都在目标列表中,是则添加。代码啰嗦,且容易遗漏。
* 工程选择:本例用
"subgraph",简洁且不易出错。如果需要独立修改子图而不影响原图,用
"nx.Graph(G.subgraph(nodes))" 创建副本。
3.4 如何处理"跨线连接"的问题?
* 问题:某些设备可能同时属于多条产线(如共用的上位机、中央交换机),或者两条产线之间有数据交互(跨线通信)。提取单产线子图时,这些跨线连接会导致子图中出现"孤立的跨线边"或"不属于该产线的节点"。
* 处理策略:在提取子图时,只保留目标产线的节点。如果某条边的一端不在目标节点列表中,该边自动被排除。对于共用设备,可以在节点属性中标记为"共享",提取时特殊处理(如保留但标记为共享节点)。
* 本例处理:在
"SubgraphExtractor" 中支持"严格模式"(只保留目标产线节点)和"宽松模式"(保留共享节点但用不同颜色标记)。
四、OOP 代码实现
4.1 项目结构
line_topology/
├── data/
│ ├── edges.csv # 全车间边列表
│ └── nodes.csv # 节点属性(设备编号、产线、类型)
├── results/ # 输出结果
│ ├── line_topology.png # 单产线拓扑图
│ ├── full_topology_highlight.png # 全车间拓扑(高亮目标产线)
│ ├── line_network_report.txt # 网络特征报告
│ └── line_nodes_edges.csv # 子图的节点和边
├── line_topology.py # 核心代码
├── test_line_topology.py # 单元测试
├── README.md
└── requirements.txt
4.2 核心源码
<details>
<summary></summary>
"""
单产线拓扑提取:用NetworkX筛选车间网络,只保留同一条产线内设备节点
=================================================================
课程映射(长安大学《智能制造导论》):
概述:工业网络、信息集成
技术基础:工业以太网、现场总线
支撑技术:工业物联网(IIoT)、数字孪生
智能工厂:网络规划、安全隔离
演进范式:手工绘制拓扑 → 全量混杂 → 属性筛选子图 → 动态拓扑感知
技术栈(严格):
numpy # 数值计算
pandas # 数据加载(边列表、节点属性)
matplotlib # 可视化
networkx # 图构建、子图提取、网络分析
scikit-learn # 无
scipy # 无
torch # 无
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Dict, Optional, Set
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import networkx as nx
plt.rcParams["font.sans-serif"] = ["SimHei", "DejaVu Sans"]
plt.rcParams["axes.unicode_minus"] = False
# ----------------------------------------------------------------------
# 1. 配置
# ----------------------------------------------------------------------
@dataclass
class TopologyConfig:
"""拓扑分析配置"""
data_dir: str = "data"
results_dir: str = "results"
edges_file: str = "edges.csv"
nodes_file: str = "nodes.csv"
# 列名
source_col: str = "source"
target_col: str = "target"
node_id_col: str = "node_id"
line_col: str = "production_line"
type_col: str = "device_type"
# 目标产线
target_line: str = "装配线A"
# 设备类型颜色映射
type_colors: Dict[str, str] = field(default_factory=lambda: {
"PLC": "#E74C3C",
"机器人": "#3498DB",
"交换机": "#F39C12",
"扫码枪": "#27AE60",
"HMI": "#9B59B6",
"传感器": "#95A5A6",
"上位机": "#34495E"
})
random_seed: int = 42
# ----------------------------------------------------------------------
# 2. 数据加载器
# ----------------------------------------------------------------------
class DataLoader:
"""网络数据加载器"""
def __init__(self, config: TopologyConfig):
self.config = config
self.data_dir = Path(config.data_dir)
os.makedirs(self.data_dir, exist_ok=True)
def generate_synthetic_data(self):
"""生成模拟车间网络数据"""
print(f"[INFO] 生成模拟车间网络数据...")
np.random.seed(self.config.random_seed)
# 产线列表
lines = ["装配线A", "焊接线B", "涂装线C", "总装线D"]
# 设备类型
device_types = list(self.config.type_colors.keys())
# 生成节点
nodes = []
node_id = 1
for line in lines:
# 每条线 10-15 台设备
n_devices = np.random.randint(10, 16)
for _ in range(n_devices):
device_type = np.random.choice(device_types, p=[0.15, 0.2, 0.15, 0.1, 0.1, 0.15, 0.15])
nodes.append({
"node_id": f"D{node_id:03d}",
"production_line": line,
"device_type": device_type
})
node_id += 1
# 生成边(同一条线内的设备随机连接)
edges = []
line_nodes = {}
for line in lines:
line_nodes[line] = [n["node_id"] for n in nodes if n["production_line"] == line]
for line, line_node_list in line_nodes.items():
n_nodes = len(line_node_list)
# 每个节点至少连一条边(环形连接保证连通)
for i in range(n_nodes):
edges.append({
"source": line_node_list[i],
"target": line_node_list[(i + 1) % n_nodes]
})
# 随机添加额外边
extra_edges = np.random.randint(3, 8)
for _ in range(extra_edges):
u = np.random.choice(line_node_list)
v = np.random.choice(line_node_list)
if u != v:
edges.append({"source": u, "target": v})
# 添加少量跨线连接
for _ in range(3):
line1, line2 = np.random.choice(lines, 2, replace=False)
u = np.random.choice(line_nodes[line1])
v = np.random.choice(line_nodes[line2])
edges.append({"source": u, "target": v})
# 保存
self.data_dir.mkdir(parents=True, exist_ok=True)
pd.DataFrame(nodes).to_csv(self.data_dir / self.config.nodes_file, index=False)
pd.DataFrame(edges).to_csv(self.data_dir / self.config.edges_file, index=False)
print(f" 生成节点: {len(nodes)}")
print(f" 生成边: {len(edges)}")
return pd.DataFrame(nodes), pd.DataFrame(edges)
def load_data(self) -> tuple[pd.DataFrame, pd.DataFrame]:
"""加载边列表和节点属性"""
print(f"[INFO] 加载网络数据...")
edges_path = Path(self.config.data_dir) / self.config.edges_file
nodes_path = Path(self.config.data_dir) / self.config.nodes_file
if not edges_path.exists() or not nodes_path.exists():
self.generate_synthetic_data()
edges_df = pd.read_csv(edges_path)
nodes_df = pd.read_csv(nodes_path)
print(f" 加载边: {len(edges_df)} 条")
print(f" 加载节点: {len(nodes_df)} 个")
return edges_df, nodes_df
# ----------------------------------------------------------------------
# 3. 拓扑构建器
# ----------------------------------------------------------------------
class TopologyBuilder:
"""构建全车间网络图"""
def __init__(self, config: TopologyConfig):
self.config = config
def build(self, edges_df: pd.DataFrame, nodes_df: pd.DataFrame) -> nx.Graph:
"""从边列表和节点属性构建图"""
print(f"[INFO] 构建全车间网络图...")
# 从边列表建图
G = nx.from_pandas_edgelist(
edges_df,
source=self.config.source_col,
target=self.config.target_col
)
# 添加节点属性
for _, row in nodes_df.iterrows():
node_id = row[self.config.node_id_col]
if node_id in G.nodes():
G.nodes[node_id][self.config.line_col] = row[self.config.line_col]
G.nodes[node_id][self.config.type_col] = row[self.config.type_col]
print(f" 图规模: {G.number_of_nodes()} 节点, {G.number_of_edges()} 条边")
return G
# ----------------------------------------------------------------------
# 4. 子图提取器
# ----------------------------------------------------------------------
class SubgraphExtractor:
"""提取单产线子图"""
def __init__(self, config: TopologyConfig):
self.config = config
def extract(self, G: nx.Graph, target_line: str = None) -> nx.Graph:
"""提取指定产线的子图"""
target_line = target_line or self.config.target_line
print(f"[INFO] 提取产线: {target_line}...")
# 筛选目标产线的节点
target_nodes = [
n for n, attr in G.nodes(data=True)
if attr.get(self.config.line_col) == target_line
]
print(f" 目标节点数: {len(target_nodes)}")
# 提取子图
subG = G.subgraph(target_nodes).copy()
print(f" 子图规模: {subG.number_of_nodes()} 节点, {subG.number_of_edges()} 条边")
return subG
# ----------------------------------------------------------------------
# 5. 网络分析器
# ----------------------------------------------------------------------
class Analyzer:
"""分析网络特征"""
def __init__(self, config: TopologyConfig):
self.config = config
def analyze(self, G: nx.Graph) -> Dict:
"""计算网络特征"""
print(f"[INFO] 分析网络特征...")
# 连通性
is_connected = nx.is_connected(G)
n_components = nx.number_connected_components(G)
# 网络直径(仅对连通图)
diameter = None
if is_connected:
diameter = nx.diameter(G)
# 平均最短路径长度
avg_path = None
if is_connected:
avg_path = nx.average_shortest_path_length(G)
# 度中心性
degree_centrality = nx.degree_centrality(G)
top_nodes = sorted(degree_centrality.items(), key=lambda x: x[1], reverse=True)[:5]
# 密度
density = nx.density(G)
results = {
"nodes": G.number_of_nodes(),
"edges": G.number_of_edges(),
"is_connected": is_connected,
"n_components": n_components,
"diameter": diameter,
"avg_path_length": avg_path,
"density": density,
"top_nodes": top_nodes
}
print(f" 连通性: {'是' if is_connected else '否'} ({n_components} 个连通分量)")
if diameter:
print(f" 网络直径: {diameter}")
print(f" 密度: {density:.3f}")
return results
# ----------------------------------------------------------------------
# 6. 可视化器
# ----------------------------------------------------------------------
class Visualizer:
"""可视化拓扑"""
def __init__(self, config: TopologyConfig):
self.config = config
self.results_dir = Path(config.results_dir)
os.makedirs(self.results_dir, exist_ok=True)
def plot_subgraph(self, G: nx.Graph, target_line: str = None):
"""绘制单产线拓扑"""
print(f"[INFO] 绘制单产线拓扑...")
target_line = target_line or self.config.target_line
fig, ax = plt.subplots(figsize=(12, 8))
# 布局
pos = nx.spring_layout(G, seed=self.config.random_seed, k=2, iterations=50)
# 按设备类型着色
node_colors = []
for n in G.nodes():
device_type = G.nodes[n].get(self.config.type_col, "未知")
node_colors.append(self.config.type_colors.get(device_type, "#999999"))
# 绘制
nx.draw_networkx_nodes(G, pos, node_color=node_colors, node_size=600, alpha=0.9, ax=ax)
nx.draw_networkx_edges(G, pos, edge_color="gray", width=1.5, alpha=0.7, ax=ax)
nx.draw_networkx_labels(G, pos, font_size=8, font_weight="bold", ax=ax)
# 图例
legend_elements = [
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=color, markersize=10, label=dt)
for dt, color in self.config.type_colors.items()
]
ax.legend(handles=legend_elements, loc="best", fontsize=10)
ax.set_title(f"{target_line} 网络拓扑({G.number_of_nodes()} 节点, {G.number_of_edges()} 条边)",
fontsize=14, fontweight="bold")
ax.axis("off")
plt.tight_layout()
plt.savefig(self.results_dir / "line_topology.png", dpi=150, bbox_inches="tight")
plt.close()
print(f" 已保存: {self.results_dir / 'line_topology.png'}")
def plot_full_with_highlight(self, G: nx.Graph, subG: nx.Graph):
"""全车间拓扑,高亮目标产线"""
print(f"[INFO] 绘制全车间拓扑(高亮目标产线)...")
fig, ax = plt.subplots(figsize=(16, 12))
pos = nx.spring_layout(G, seed=self.config.random_seed, k=0.5, iterations=30)
# 非目标节点(灰色)
non_target_nodes = set(G.nodes()) - set(subG.nodes())
nx.draw_networkx_nodes(G, pos, nodelist=list(non_target_nodes),
node_color="lightgray", node_size=100, alpha=0.3, ax=ax)
nx.draw_networkx_edges(G, pos, alpha=0.1, edge_color="lightgray", ax=ax)
# 目标节点(彩色)
sub_pos = {n: pos[n] for n in subG.nodes()}
node_colors = []
for n in subG.nodes():
device_type = subG.nodes[n].get(self.config.type_col, "未知")
node_colors.append(self.config.type_colors.get(device_type, "#999999"))
nx.draw_networkx_nodes(subG, sub_pos, node_color=node_colors,
node_size=400, alpha=1.0, ax=ax)
nx.draw_networkx_edges(subG, sub_pos, edge_color="red", width=2.0, alpha=0.8, ax=ax)
nx.draw_networkx_labels(subG, sub_pos, font_size=7, font_weight="bold", ax=ax)
ax.set_title(f"全车间网络拓扑(高亮: {self.config.target_line})",
fontsize=14, fontweight="bold")
ax.axis("off")
plt.tight_layout()
plt.savefig(self.results_dir / "full_topology_highlight.png", dpi=150, bbox_inches="tight")
plt.close()
print(f" 已保存: {self.results_dir / 'full_topology_highlight.png'}")
# ----------------------------------------------------------------------
# 7. 报告生成器
# ----------------------------------------------------------------------
class ReportGenerator:
"""分析报告生成器"""
def __init__(self, config: TopologyConfig):
self.config = config
self.results_dir = Path(config.results_dir)
os.makedirs(self.results_dir, exist_ok=True)
def generate(self, G: nx.Graph, analysis: Dict) -> str:
"""生成报告"""
print(f"[INFO] 生成分析报告...")
report_lines = []
report_lines.append("=" * 80)
report_lines.append(f"{self.config.target_line} 网络拓扑分析报告")
report_lines.append("=" * 80)
# 概况
report_lines.append(f"\n网络概况:")
report_lines.append(f" 节点数: {analysis['nodes']}")
report_lines.append(f" 边数: {analysis['edges']}")
report_lines.append(f" 连通性: {'连通' if analysis['is_connected'] else '不连通'}")
report_lines.append(f" 连通分量数: {analysis['n_components']}")
if analysis['diameter']:
report_lines.append(f" 网络直径: {analysis['diameter']} 跳")
if analysis['avg_path_length']:
report_lines.append(f" 平均路径长度: {analysis['avg_path_length']:.2f} 跳")
report_lines.append(f" 网络密度: {analysis['density']:.3f}")
# 关键节点
report_lines.append(f"\n关键节点(度中心性 Top 5):")
report_lines.append("-" * 50)
for node, centrality in analysis['top_nodes']:
degree = G.degree(node)
device_type = G.nodes[node].get(self.config.type_col, "未知")
report_lines.append(
f" {node:8s} ({device_type:6s}): "
f"度数={degree:2d}, 中心性={centrality:.3f}"
)
# 设备类型统计
type_counts = {}
for _, attr in G.nodes(data=True):
dt = attr.get(self.config.type_col, "未知")
type_counts[dt] = type_counts.get(dt, 0) + 1
report_lines.append(f"\n设备类型分布:")
for dt, count in sorted(type_counts.items(), key=lambda x: x[1], reverse=True):
report_lines.append(f" {dt}: {count} 台")
# 建议
report_lines.append(f"\n网络优化建议:")
report_lines.append("-" * 40)
if not analysis['is_connected']:
report_lines.append(f" 1. 网络存在 {analysis['n_components']} 个连通分量,建议检查断线")
else:
report_lines.append(f" 1. 网络连通性良好")
if analysis['diameter'] and analysis['diameter'] > 5:
report_lines.append(f" 2. 网络直径较大({analysis['diameter']} 跳),可能存在通信延迟")
report_lines.append(f" 3. 关键节点(高中心性)建议配置冗余链路")
report_lines.append(f" 4. 交换机节点应作为网络核心,确保带宽充足")
report_lines.append("\n" + "=" * 80)
report_lines.append("报告生成完毕")
report_lines.append("=" * 80)
report_text = "\n".join(report_lines)
report_path = self.results_dir / "line_network_report.txt"
with open(report_path, "w", encoding="utf-8") as f:
f.write(report_text)
print(f" 报告已保存: {report_path}")
return report_text
# ----------------------------------------------------------------------
# 8. 主程序演示
# ----------------------------------------------------------------------
def demo():
"""完整演示流程"""
print("=" * 80)
print("单产线拓扑提取")
print("=" * 80)
config = TopologyConfig(
data_dir="data",
results_dir="results",
target_line="装配线A"
)
# 1. 加载
print("\n[INFO] 步骤1: 加载数据...")
loader = DataLoader(config)
edges_df, nodes_df = loader.load_data()
# 2. 建图
print("\n[INFO] 步骤2: 构建全车间网络图...")
builder = TopologyBuilder(config)
G = builder.build(edges_df, nodes_df)
# 3. 提取子图
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)