Stanford CS224W: Machine Learning with Graphs

By Elijah Schacter and Ryan Wu as part of the Stanford CS 224W Final Project


代码下载:https://t.zsxq.com/bMeHd

请索引第41个项目



现代电网是庞大的互联系统,由数千台发电机、输电设备和负荷中心实时运行组成。系统运营商的任务是时刻维持电力供需之间的微妙平衡,因为即使是微小的不平衡也会导致系统频率偏差,从而造成设备损坏或大规模停电。为了防止这种不稳定性,运营商必须持续进行电力市场清算,并根据物理、经济和监管约束条件调度资源。随着可再生能源、电池储能和电动汽车充电在电网中扮演越来越重要的角色,资源调度管理也面临着日益复杂的挑战。


For energy systems that power a reliable grid, the future is all about  location | MIT News | Massachusetts Institute of Technology


解决这个问题的一个简单方法是获取每个发电厂的发电容量和价格(美元/兆瓦),然后以最小化总成本的方式为各发电厂分配负荷。然而,这种方法忽略了几个重要的约束条件。首先,输电线路的容量有限,如果无法将电力输送到用户,那么发电就毫无意义。其次,发电厂的运行方式与灯泡的调光开关不同——开关电厂都需要成本,而且发电厂无法瞬间完成负荷切换。提前告知电厂运行人员何时需要启动以及切换速度,这就是所谓的机组组合问题。我们致力于利用机器学习技术解决这一难题。


组合


首先,是什么使得机组组合问题难以高效求解?机组组合约束实际上是在基本发电容量问题之上增加了一个二进制掩码,因此对于每个组合掩码(即哪些电厂开启/关闭),每个电厂的最优发电量都必须作为一个子问题来求解。这种问题形式是非凸的,这意味着局部最小值不一定是全局最小值。当电网规模增长到数百个需要开启或关闭的电厂时,需要求解的掩码数量呈组合式增长,使得穷举搜索成为不可能。因此,通常采用以下两种方法之一:混合整数规划求解器或启发式组合算法。


混合整数规划求解器将二进制承诺掩码作为可优化变量,该变量必须被视为整数约束。许多商业软件都采用“分支定界”算法来求解这种问题。分支定界算法的详细解释超出了本文的范围,更多信息请参考相关资源,例如[ 1]。实际上,混合整数规划求解器能够提供最优性保证,并且相比穷举搜索算法性能更优,但随着决策变量数量的增加,其扩展性仍然较差,并且比求解不包含二进制约束的等效问题慢得多。下面展示了一个将机组组合问题建模为混合整数规划问题的示例:



混合整数规划模型通常适用于实时运行的电网运营商,但当运行对电网规划和确定未来项目经济价值至关重要的前瞻性模拟时,计算成本会显著增加。目前,解决该问题的行业标准方法之一是使用启发式机组组合图。与混合整数规划不同,启发式机组组合图在优化之前,先使用一个展望未来24-72小时的启发式算法求解机组组合。通过启发式算法设定的机组组合约束,问题变为凸问题,可以快速求解。



鉴于第二种方法(将启发式算法与凸线性规划求解相结合)相对简单,因此有必要更详细地探讨启发式算法。一个好的启发式算法应该能够接收相关的约束条件和权重(例如容量限制、启动成本、预测需求),并输出一个二元承诺映射,该映射能够生成一个可行解和一个近似最优解(与计算成本更高的混合整数规划相比)。对于需要大量评估的应用(例如电网规划),启发式算法还必须能够快速评估,并能随着电网复杂性的增加而良好扩展。


图神经网络


为此,我们采用了图神经网络(GNN)。电力系统中的输电线路、发电机和负荷构成了一个图。负荷和发电机位于母线上,母线是图中的节点,而输电线路(用边表示)连接着这些母线。图神经网络是一种机器学习架构,它能够充分利用图结构的连通性,在单个节点和边的层面或整个图的层面上执行学习推理任务。GNN 的复杂度与边的数量呈线性关系,并且能够通过归纳方式学习图结构的变化。这些特性使得训练数据可以从各种示例电力系统架构中获取,并能够很好地扩展到实际的大型电力系统。


图神经网络在电力传输问题上已取得显著成功。最优潮流(Optimal power flow,OPF)是输电网运行中的一个经典问题,它描述了在给定实际输电网及其负荷分布的情况下,如何最优地发电。实时求解OPF问题成本极高,因此电网运营商通常求解简化版本,但这会降低精度。CANOS (Constraint-Augmented Neural OPF Solver)是一种图神经网络架构,它能够生成接近最优解,并且能够很好地扩展到公用事业规模的电网。[2] 此外,图神经网络已被应用于电力电网的图级任务,例如预测给定电网运行状态是否容易发生级联故障。[3]


对于机组组合启发式算法,我们希望模型能够预测给定发电机在特定时间是否处于运行状态,其所用信息与混合整数优化问题相同。这是一个节点级推理问题,其中图神经网络 (GNN) 预测一个二元分类结果,表示发电机节点的运行状态。在开始研究 GNN 架构之前,我们先来看看将要用于该问题的训练数据。


UnitCommitment.jl 和 PSTCA


我们将使用来自UnitCommitment.jl 包的数据进行训练。[4] 该包编译了机组组合问题的基准实例,以及使用混合整数规划技术求解这些实例的公式。具体来说,该包使用安全约束机组组合公式,该公式旨在找到对一系列突发事件(例如输电线路故障)具有鲁棒性的最优机组组合。这些突发事件将用于后续扩充我们的数据集。对于真实机组组合解,我们将使用 UnitCommitment.jl 中的内置工具。


我们使用的具体数据集是华盛顿大学编制的电力系统测试用例库(Power Systems Test Case Archive,PSTCA),该数据集已转换为标准的 UnitCommitment.jl json 数据格式。[5] 这些用例代表了 20 世纪 60 年代美国电力系统维护的部分电网,规模从 14 个母线到 300 个母线不等。每个样本年份的每一天都有一个对应的用例,其中包含从当日午夜开始的未来 36 小时内每个母线的用电需求预测。以下是一个描述简单 14 母线用例的 json 文件片段。


我们在标题中可以看到一些关于案例设置的信息:

"SOURCE":"- University of Washington, Dept. of Electrical Engineering. \"Power Systems Test Case Archive\". Available at: http://www.ee.washington.edu/research/pstca/ (Accessed: Nov 14, 2020)\n\n- D. Zimmerman, C. E. Murillo-Sandnchez and R. J. Thomas. \"Matpower: Steady-state operations, planning, and analysis tools forpower systems research and education\", IEEE Transactions on PowerSystems, vol. 26, no. 1, pp. 12 \u201319, Feb. 2011. DOI: 10.1109/TPWRS.2010.2051168\n\n- A. S. Xavier, A. M. Kazachkov, O. Yurdakul, F. Qiu. \"UnitCommitment.jl: A Julia/JuMP Optimization Package for Security-Constrained Unit Commitment (Version 0.3)\". Zenodo (2022). DOI: 10.5281/zenodo.4269874\n",
"Parameters":{
"Version":"0.3",
"Power balance penalty ($/MW)":1000.0,
"Time horizon (h)":36
}


然后,列出案例中的生成器:

"Generators": {
"g1": {
"Bus""b1",
"Production cost curve (MW)": [
        36.75123365792352,
        110.10634590601819,
        183.46145815411288,
        256.8165704022076,
        330.1716826503023
      ],
"Production cost curve ($)": [
        1160.1370560288465,
        4051.592909653724,
        7310.413973593571,
        10614.711162105745,
        14293.941140664052
      ],
"Startup costs ($)": [
        25056.51,
        29059.15,
        34238.45
      ],
"Startup delays (h)": [
        1,
        2,
        4
      ],
"Ramp up limit (MW)": 231.12,
"Ramp down limit (MW)": 231.12,
"Startup limit (MW)": 231.12,
"Shutdown limit (MW)": 231.12,
"Minimum uptime (h)": 1,
"Minimum downtime (h)": 1,
"Reserve eligibility": [
"r1"
      ],
"Initial status (h)": 24,
"Initial power (MW)": 230.74887999999999
    },
# etc.
}


分段线性成本曲线用于插值计算发电量与发电成本之间的关系。同样,电厂停机时间过长会导致重启成本增加,因此也使用另一条分段线性成本曲线来表示电厂停机一定小时数后重新启动的成本。


最后,我们可以看一下连接成对公交车的输电线路,以及未来 36 小时内公交车的预计负荷:

"Transmission lines": {
"l1": {
"Source bus""b1",
"Target bus""b2",
"Reactance (ohms)": 0.05917,
"Susceptance (S)": 29.49686
  },
#etc.
}
"Buses": {
"b1": {
"Load (MW)": 0.0
    },
"b2": {
"Load (MW)": [
        19.33301,
        18.57311,
        18.06675,
        17.76778,
        17.95852,
        18.33015,
        19.37086,
        20.13001,
#etc.
      ]
    },
#etc.
}


接下来,我们需要将这些数据转换成我们的 GNN 可以使用的格式。


生成训练数据


为了从给定的 UnitCommitment.jl 案例中获得真实解,我们可以使用内置的 `optimize()` 方法求解该问题。该方法会为 36 个未来小时分别生成一个二值掩码,并将预测需求作为解,然后我们将使用这些掩码来训练图神经网络 (GNN)。感兴趣的读者可以了解,我们使用的是 JuMP 框架中的 HiGHS 混合整数求解器,其求解策略在Xavier 等人 2019 年发表的论文[6]中有详细描述。

using HiGHS
using UnitCommitment

# load a benchmark case
instance = UnitCommitment.read_benchmark("matpower/case14/2017-01-01")

# build optimization model
model = UnitCommitment.build_model(instance = instance, optimizer = HiGHS.Optimizer)

# solve the built model
UnitCommitment.optimize!(model)

# extract the solution
solution = UnitCommitment.solution(model)


解决方案被打印到一个 json 文件中,其中包含我们关心的变量“is on”,即我们的二元单位承诺。

"Is on":{
"g1":[
1.0,
1.0,
1.0,
1.0,
1.0,
# etc.
],
}


我们来看一个输入和求解的示例图。在下图中,发电机母线用橙色表示,负荷母线用蓝色表示。每条母线都通过输电线路与其他母线连接,输电线路用集总元件电阻和电纳表示。图中未显示其他节点级信息,例如发电资产的启动成本和爬坡速率。



下图所示为对应于上述情况的机组组合的解图。该图构成了一个覆盖所有发电机节点的二进制掩码,作为图神经网络(GNN)的优化目标。需要注意的是,只有包含发电机节点的母线才会受到机组组合状态的影响。



然而,目前我们仅考察了基准测试实例中四种可用的电网架构(14、57、118 和 300 个节点的网络),每种架构仅有 365 个样本。为了确保我们的图神经网络 (GNN) 能够适应未知的输电网结构,我们利用了故障情况。UnitCommitment.jl 包含每个输电网络案例的可用故障情况集,其中包括所有不会导致输电网络图不相交的单条输电线路移除操作。我们为每个数据点随机抽取五个故障情况,求解这些故障,并将它们添加到数据集中进行训练。


现在我们已经解决了一些案例,接下来必须将它们转换为与 PyTorch Geometric 兼容的格式,PyTorch Geometric 是我们计划用来实现图神经网络 (GNN) 的机器学习包。我们使用以下代码来实现这一点。首先,我们对生成器节点进行编码,并将它们连接到总线上:

generators = data["Generators"]
buses = data["Buses"]
lines = data["Transmission lines"]

data_hetero = HeteroData()

# Build generator features
gen_features = []
gen_bus_idx = []
for g_name, g in generators.items():
iflen(g.get("Startup costs ($)", [])) < 3:
        g["Startup costs ($)"] = prev_startup_costs.get(g_name, [0.0]*3)
else:
        prev_startup_costs[g_name] = g["Startup costs ($)"]

iflen(g.get("Startup delays (h)", [])) < 3:
        g["Startup delays (h)"] = prev_startup_delays.get(g_name, [0.0]*3)
else:
        prev_startup_delays[g_name] = g["Startup delays (h)"]

    features = (
        g["Production cost curve (MW)"]
        + g["Production cost curve ($)"]
        + g["Startup costs ($)"]
        + g["Startup delays (h)"]
        + [ 
            g["Ramp up limit (MW)"],
            g["Ramp down limit (MW)"],
            g["Startup limit (MW)"],
            g["Shutdown limit (MW)"],
            g["Minimum uptime (h)"],
            g["Minimum downtime (h)"],
            g["Initial status (h)"],
            g["Initial power (MW)"]
        ]
    )
    gen_features.append(features)
    gen_bus_idx.append(bus2idx[g["Bus"]])

gen_features = torch.tensor(gen_features, dtype=torch.float)
gen_features = (gen_features - gen_features.mean(dim=0)) / (gen_features.std(dim=0) + 1e-6)

data_hetero["generator"].x = gen_features
src = torch.arange(len(gen_bus_idx))
dst = torch.tensor(gen_bus_idx)
data_hetero["generator""produces_at""bus"].edge_index = torch.stack([src, dst], dim=0)
data_hetero["bus""served_by""generator"].edge_index = torch.stack([dst, src], dim=0)


然后,我们添加总线负载和传输功能:

bus_features = []
for bus_data in buses.values():
    load_seq = bus_data["Load (MW)"]
ifisinstance(load_seq, (intfloat)):
        load_seq = [load_seq] * lookahead_hours
eliflen(load_seq) < lookahead_hours:
        load_seq = list(load_seq) + [0.0]*(lookahead_hours - len(load_seq))
    bus_features.append(load_seq)

bus_features = torch.tensor(bus_features, dtype=torch.float)
data_hetero["bus"].x = bus_features

# Build transmission edges, removing failed lines if specified
bus_edge_index = []
bus_edge_attr = []
failed_line_set = set(failed_lines) if failed_lines elseset()

for line_id, props in lines.items():
# Skip failed lines in contingency scenarios
if line_id in failed_line_set:
continue

    src = bus2idx[props["Source bus"]]
    dst = bus2idx[props["Target bus"]]
    bus_edge_index.append([src, dst])
    bus_edge_index.append([dst, src])
    bus_edge_attr.append([props["Reactance (ohms)"], props["Susceptance (S)"]])
    bus_edge_attr.append([props["Reactance (ohms)"], props["Susceptance (S)"]])

if bus_edge_index:  # Only add if edges exist
    bus_edge_index = torch.tensor(bus_edge_index, dtype=torch.long).T
    bus_edge_attr = torch.tensor(bus_edge_attr, dtype=torch.float)
    data_hetero["bus""transmission""bus"].edge_index = bus_edge_index
    data_hetero["bus""transmission""bus"].edge_attr = bus_edge_attr


最后,我们加入备用节点。我们之前很少谈到它们,但它们本质上是对整个电网未来36小时内可用发电容量的额外要求。

reserve_features = []
reserve_names = list(data.get("Reserves", {}).keys())
reserve_name2idx = {r: i for i, r inenumerate(reserve_names)}

for r_name in reserve_names:
    r_data = data["Reserves"][r_name]
    amount_seq = r_data["Amount (MW)"]
iflen(amount_seq) < lookahead_hours:
        amount_seq = list(amount_seq) + [0.0]*(lookahead_hours - len(amount_seq))
    reserve_features.append(amount_seq)

if reserve_features:
    reserve_features = torch.tensor(reserve_features, dtype=torch.float)
    data_hetero["reserve"].x = reserve_features

reserve_src, reserve_dst = [], []
for r_idx, r_name inenumerate(reserve_names):
for g_idx, g inenumerate(generators.values()):
if r_name in g.get("Reserve eligibility", []):
            reserve_src.append(r_idx)
            reserve_dst.append(g_idx)

if reserve_src:
    data_hetero["reserve""backed_by""generator"].edge_index = torch.tensor(
        [reserve_src, reserve_dst], dtype=torch.long
    )


模型架构


我们的模型可以分解为四个不同的部分:


1. 加载多层感知器(MLP)。


首先,我们使用两个多层感知器(MLP)层将24个生成器特征投影到128维空间。储备节点和装载节点类型均不包含特征信息,因此忽略装载步骤。它们被初始化为随机的128维向量。


2. 结构化图神经网络


结构编码器是一个两层的 HEATConv 网络。该模型通过引入边特征和异构节点类型来增强图注意力转换器模型,这些特征和类型对于实现发电机、节点和输电线路之间的交互至关重要。[7] 每个 HEAT 层都对电力系统图执行异构的、感知边的 4 头注意力机制。每一层的更新规则类似于(此处未包含跳跃连接,但已添加到第二层):



重要的是,电抗和电纳等线路参数直接通过边属性嵌入进入。


由于电力网络高度互联,我们发现深度图神经网络(GNN,超过3层)存在过度平滑的问题,导致所有节点嵌入变得难以区分。在示例系统中,使用两个HEAT层效果最佳,但在互联程度较低的大型系统中,增加层数或许也是可以接受的。以下代码片段展示了一个单独的HEAT层以及GNN的前向传播过程。

self.heat1 = HEATConv(
            in_channels=hidden_dim, out_channels=hidden_dim,
            num_node_types=self.num_node_types, num_edge_types=self.num_edge_types,
            edge_type_emb_dim=edge_emb_dim, edge_dim=2, edge_attr_emb_dim=edge_emb_dim,
            heads=num_heads, concat=False
        )
x = self.heat1(x, edge_index, node_type, edge_type, edge_attr)
x1 = torch.relu(x)
x = self.heat2(x1, edge_index, node_type, edge_type, edge_attr)
x_out = torch.relu(x) + x1
x_out = self.dropout(x_out)


3. 时间层


在两层HEAT编码器完成结构化消息传递后,时间动态信息在GNN外部使用轻量级卷积序列模型进行建模(也尝试过GRU,但未显示出任何优势)。这种设计严格地将结构学习与时间学习分离,防止了消息传递过程中任何形式的时间信息泄露。


GNN运行后,通过学习到的线性投影引入36小时的负载和储备轨迹。这些投影序列与相应的静态负载和储备嵌入连接起来,形成时间节点表示。生成器节点不接收直接的时间输入。相反,它们的静态嵌入会随时间广播,这反映了它们的物理特性在时间尺度上保持不变。生成的时间节点序列由一个两层一维卷积网络处理。以下是时间层的构建及其实现方式:

if temporal_method == '1d_conv':
self.temporal = nn.Sequential(
        nn.Conv1d(hidden_dim, hidden_dim, kernel_size=5, padding=2),
        nn.BatchNorm1d(hidden_dim),
        nn.ReLU(),
        nn.Dropout(dropout),
        nn.Conv1d(hidden_dim, hidden_dim, kernel_size=3, padding=1),
        nn.BatchNorm1d(hidden_dim),
        nn.ReLU()
    )
# Get structural embeddings from GNN
z_graph, _, offsets = self.encoder(x_dict_static, graph.edge_index_dict, graph.edge_attr_dict)

# Extract generator structural embeddings (only computed once!)
gen_emb_static = z_graph[offsets['generator']:offsets['generator']+n_gen]  # [n_gen, hidden_dim]
bus_emb_static = z_graph[offsets['bus']:offsets['bus']+n_bus]  # [n_bus, hidden_dim]
res_emb_static = z_graph[offsets['reserve']:offsets['reserve']+n_reserve]  # [n_reserve, hidden_dim]

# Build temporal sequences efficiently (vectorized over time)
bus_temporal = bus_feats.unsqueeze(-1)  # [n_bus, T, 1]
res_temporal = res_feats.unsqueeze(-1)  # [n_reserve, T, 1]

# Project temporal features
bus_temporal_emb = self.bus_temporal_proj(bus_temporal)  # [n_bus, T, hidden_dim]
res_temporal_emb = self.reserve_temporal_proj(res_temporal)  # [n_reserve, T, hidden_dim]

# Combine structural + temporal for bus and reserve
bus_emb_seq = bus_emb_static.unsqueeze(1) + bus_temporal_emb  # [n_bus, T, hidden_dim]
res_emb_seq = res_emb_static.unsqueeze(1) + res_temporal_emb  # [n_reserve, T, hidden_dim]

# Generators: expand static embedding across time (no temporal features for generators)
gen_emb_seq = gen_emb_static.unsqueeze(1).expand(-1self.T, -1)  # [n_gen, T, hidden_dim]

# Concatenate all nodes
z_seq = torch.cat([gen_emb_seq, bus_emb_seq, res_emb_seq], dim=0)  # [total_nodes, T, hidden_dim]
# Apply temporal model
ifself.temporal_method == '1d_conv':
# Conv1d expects [batch, channels, length]
    z_seq_t = z_seq.permute(021)  # [total_nodes, hidden_dim, T]
    z_temporal = self.temporal(z_seq_t)  # [total_nodes, hidden_dim, T]
    z_temporal = z_temporal.permute(021)  # [total_nodes, T, hidden_dim]


4. 解码器


最后,每个时间节点嵌入都通过一个小型多层感知器(MLP)进行解码,生成36步机组组合。仅保留发电机预测结果作为输出:

# Decoder
self.decoder = nn.Sequential(
    nn.Linear(hidden_dim, hidden_dim // 2),
    nn.ReLU(),
    nn.Dropout(dropout),
    nn.Linear(hidden_dim // 2, output_dim)
)
# Decode to predictions
out_seq = self.decoder(z_temporal)  # [total_nodes, T, 1]
out_seq = out_seq.permute(102)  # [T, total_nodes, 1]

# Extract only generator predictions
gen_predictions = out_seq[:, :n_gen, :]  # [T, n_gen, 1]


我们使用二元交叉熵损失作为反向传播指标来评估机组组合预测的准确性。完整的模型流程如下图所示:



流程图展示了GNN预测架构中如何使用不同的特征和层。


结果


我们的主要基准是简单的岭回归。为此,我们简单地将输入数据(发电机特征、36 小时负荷和备用容量展望)展平,并用其预测展平后的机组组合。为了加快训练速度,我们使用高效的 PCA 算法将输入特征降维至一百维。然而,由于该岭回归模型在不同的电网配置下准确率极低,因此需要针对每种不同的情况单独进行训练。因此,我们无法将其用于针对混合系统提供合理的基准,但这种无法适应新系统的缺陷恰恰凸显了我们模型的主要优势:灵活性。



尽管这些结果乍看之下可能并不理想,但实际上却非常出色。需要注意的是,岭回归模型不仅完全无法适应新的电网结构,也无法处理突发事件。突发事件是指电网中出现故障(例如线路或发电机停运),这种情况时有发生。一个强大的电力模型需要能够处理这些问题,并生成有效的机组组合指令。虽然可以通过零填充来重新构建岭回归模型以适应线路突发事件,但其性能(上表未显示)在 70% 到 85% 之间波动,具体取决于数据集中活跃的突发事件集。我们预计,在具有更多独特停电组合和复杂依赖关系的大型电网中,与电网结构无关的机器学习方法(例如岭回归模型)将无法胜任。


回到上表,令人印象深刻的是,我们的通用模型(可以适用于各种不同的电网结构,并能适应任何突发/停电情况的组合)的性能几乎与只能在严格的固定设置下运行的岭模型相当。


后续步骤


我们相信,只需进行一些小的(尽管耗时)改进,我们的模型就能成为比混合整数规划 (MIP) 或目前用于解决机组组合问题的某种笨拙启发式算法更快的替代方案。首先,我们需要对代码进行分解,以便在 GPU 上运行,从而节省时间。代码分解完成后,我们预计训练时间将大幅缩短。训练时间的缩短使我们能够利用多年数据和各种不同的停电情况,在规模更大的电网上训练模型。我们相信,通过这种方式,我们可以创建一个能够推广到各种不同电网的单一模型。最后,我们计划将我们的机组组合输出与实际 MIP 机组组合调度输出进行比较。这究竟意味着什么?机组一旦完成组合,就会实时调度,以确保供需平衡。只有预先组合的机组才能被调度,因此,正确进行机组组合至关重要。方便的是,该调度模型是一个简单的线性规划模型,使我们能够快速比较我们的机组组合模型是否会导致系统故障和能源成本与传统的混合整数规划和启发式机组组合模型相当。


正如本文反复强调的,我们的最终目标是速度。即使我们的模型结果略逊于传统的混合整数规划(MIP)或启发式模型,我们也预期其运行速度将快几个数量级。为什么速度如此重要?实时运行更注重准确性,而对于前瞻性研究而言,速度则更为关键。每项研究都包含数千小时、数百种不同的天气、负荷和发电场景。这还不包括每个场景小时都依赖于随机概率的停电抽样,并通过蒙特卡罗模拟完成!因此,电网研究领域在很大程度上受限于MIP/启发式机组组合问题,亟需一种更快的替代方案。保守估计,与启发式方法相比,使用我们提出的模型(如果针对GPU进行适当优化)求解该问题,每次迭代的速度可以提高50倍,从500毫秒缩短到10毫秒左右。我们希望通过在接下来的一个季度里继续共同完善这一模式,能够为电力行业提供一个急需的快速替代方案。


参考文献

  • [1] Boyd, S., Ghosh, A., & Magnani, A. (2003, November 1). Branch and bound methods (Notes for EE392o, Stanford University). Stanford University. https://web.stanford.edu/class/ee392o/bb.pdf

  • [2] Piloto, L., Liguori, S., Madjiheurem, S., Zgubic, M., Lovett, S., Tomlinson, H., Elster, S., Apps, C., & Witherspoon, S. (2024). CANOS: A fast and scalable neural AC-OPF solver robust to N-1 perturbations (arXiv:2403.17660) [Preprint]. arXiv. https://arxiv.org/abs/2403.17660

  • [3] Varbella, A., Amara, K., Gjorgiev, B., El-Assady, M., & Sansavini, G. (2024). PowerGraph: A power grid benchmark dataset for graph neural networks (arXiv:2402.02827v2) [Preprint]. arXiv. https://arxiv.org/abs/2402.02827v2

  • [4] Xavier, A. S., Kazachkov, A. M., Yurdakul, O., He, J., & Qiu, F. (2025). UnitCommitment.jl: A Julia/JuMP optimization package for security-constrained unit commitment (Version 0.4.2) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.17737778

  • [5] University of Washington Electrical & Computer Engineering. (n.d.). Power Systems Test Case Archive [Data repository]. University of Washington. https://labs.ece.uw.edu/pstca/

  • [6] Xavier, Á. S., Qiu, F., Wang, F., & Thimmapuram, P. R. (2019). Transmission constraint filtering in large-scale security-constrained unit commitment. IEEE Transactions on Power Systems, 34(3), 2457–2460. https://doi.org/10.1109/TPWRS.2019.2892620

  • [7] Mo, X., Xing, Y., & Lv, C. (2021). Heterogeneous edge-enhanced graph attention network for multi-agent trajectory prediction (arXiv:2106.07161) [Preprint]. arXiv. https://arxiv.org/abs/2106.07161

微信群

内容中包含的图片若涉及版权问题,请及时与我们联系删除