<think>我们注意到原始程序中有一些函数(如BFS、dfs_shortest_paths)被洪水算法替代,同时需要确保所有变量都被正确定义。我们将按照以下步骤重写:
1. 使用洪水算法(flood fill)替代原来的BFS和DFS,用于形成孤岛和连接优先负荷。
2. 修正变量`island_num`未定义的问题:在孤岛融合后,重新计算孤岛数量。
3. 保持程序结构,但将原BFS和DFS部分替换为洪水算法。
洪水算法思路:
- 从每个DG节点开始,像洪水蔓延一样访问相邻节点(广度优先),并累加负荷,直到总负荷超过DG容量。
- 构建网络拓扑图时排除故障支路。
步骤:
a. 构建网络拓扑图(邻接表),排除故障支路。
b. 对每个DG节点执行洪水算法,形成初始孤岛。
c. 融合交叉的孤岛(即多个DG的孤岛有重叠,则合并成一个孤岛,包含这些DG)。
d. 检查优先恢复负荷是否被包含,若没有,则使用洪水算法(或最短路径)将其连接到最近的孤岛(这里我们使用洪水算法寻找路径,但为了效率,我们采用最短路径搜索,因为洪水算法在寻找路径时可能效率较低,所以我们用BFS找最短路径)。
e. 负荷削减:按照可控负荷、重要度顺序削减。
注意:在洪水算法中,我们只访问与DG连通的节点,并且不超过容量限制。
由于原程序较长,我们将重写整个程序,确保完整输出。以下是完整代码:</think>### 完整洪水算法实现配电网孤岛划分程序
```matlab
%% 洪水算法实现的孤电网孤岛划分(完整版)
function islanding_solution()
%% 步骤1:相关参数初始化
mpc1 = IEEE33(); % 配电网数据
Nb = 33; % 节点数
Nt = 24; % 时段数
% 光储系统接入位置
Y_DG = [6, 8, 12, 23, 30];
% 负荷等级系数
wf = 0.01*ones(1,Nb);
wf([6, 12, 23, 30]) = 1; % 一级负荷
wf([1,5,8,14,18,21,22,27,29,32]) = 0.1; % 二级负荷
% 负荷时变需求系数
Ct = zeros(Nb, Nt);
Ct([6, 12, 23, 30], :) = 10; % 一级负荷的需求度恒为10
time_coeff = [7.7796,5.3248,5.0429,5.1984,2.9881,3.4293,7.2042,10.6853,...
12.5477,15.5212,24.8697,33.2302,24.2863,24.7989,36.3317,...
27.4948,17.8808,14.0970,18.9046,20.4888,22.2151,19.7628,...
21.4368,17.6810]/36.3317;
Ct(setdiff(1:Nb, [6, 12, 23, 30]), :) = ones(Nb - 4 , 1)*10*time_coeff;
% 优先恢复系数
Ft = Ct.*(wf'*ones(1, Nt));
% 光伏出力数据
P_PV = [425, 200, 480, 120, 600;
700, 500, 720, 620, 720];
% 负荷总量
PL = [3305 , 4870];
% 各节点负荷
P_load = mpc1.bus(:,3)/3.715*PL;
% 负荷削减系数
a_cut = zeros(1,Nb);
C_load1 = [3,13,20,24]; % 完全可控的负荷集合
a_cut(C_load1) = 1; % 100%可控
C_load2 = [2,7,10]; % 50%可控的负荷集合
a_cut(C_load2) = 0.5; % 50%可控
%% 步骤2:读取故障支路
fault_branch = [5, 25, 20]; % 故障支路索引
%% 步骤3:确定故障时刻(假设index=1)
index = 1; % 选择故障时刻索引
time0 = [7 , 15]; % 故障时刻
time = time0(index); % 当前时刻
if index ~= 1 && index ~= 2
error('输入有误请重新输入!!!');
end
%% 步骤4:确定优先恢复集合
F_Rload = {[6, 12, 15, 23, 28, 30], [6, 12, 23, 30, 32]};
%% 步骤5:洪水算法确定孤岛
% 构建拓扑图(排除故障支路)
graph = build_graph(mpc1, fault_branch);
% 初始化孤岛信息
island_node = cell(1, length(Y_DG)); % 各孤岛包含的节点
island_power = zeros(1, length(Y_DG)); % 各孤岛总功率
island_load = zeros(1, length(Y_DG)); % 各孤岛总负荷
% 洪水算法形成初始孤岛
for k = 1:length(Y_DG)
[island_node{k}, island_load(k)] = flood_fill(...
Y_DG(k), graph, P_PV(index, k), P_load, time);
island_power(k) = P_PV(index, k);
end
% 收集所有已恢复节点
island_node_all = [];
for k = 1:length(Y_DG)
island_node_all = union(island_node_all, island_node{k});
end
%% 步骤5.1:孤岛融合(处理交叉孤岛)
% 初始化融合后的孤岛
island_node_cross = island_node; % 初始化为原始孤岛
island_cross_DG = num2cell(1:length(Y_DG)); % 每个DG对应一个孤岛
island_num = length(Y_DG); % 初始孤岛数等于DG数
% 检测孤岛交叉并融合
i = 1;
while i <= island_num
j = i + 1;
while j <= island_num
if ~isempty(intersect(island_node_cross{i}, island_node_cross{j}))
% 融合交叉孤岛
island_node_cross{i} = union(island_node_cross{i}, island_node_cross{j});
island_cross_DG{i} = [island_cross_DG{i}, island_cross_DG{j}];
% 更新孤岛功率
island_power(i) = island_power(i) + island_power(j);
island_load(i) = island_load(i) + island_load(j);
% 移除被融合的孤岛
island_node_cross(j) = [];
island_cross_DG(j) = [];
island_power(j) = [];
island_load(j) = [];
island_num = island_num - 1; % 更新孤岛数量
else
j = j + 1;
end
end
i = i + 1;
end
%% 步骤6:连接优先恢复负荷
for k = 1:length(F_Rload{index})
current_load = F_Rload{index}(k);
% 检查是否已恢复
if ~ismember(current_load, island_node_all)
% 寻找最近DG和最短路径
[nearest_dg, min_path] = find_nearest_dg(current_load, Y_DG, graph, island_node_all);
% 加入对应孤岛
for kk = 1:island_num
if ismember(nearest_dg, island_cross_DG{kk})
% 添加路径节点到孤岛
island_node_cross{kk} = union(island_node_cross{kk}, min_path);
% 更新孤岛负荷
for node = min_path
if ~ismember(node, island_node_cross{kk}) % 避免重复计算
island_load(kk) = island_load(kk) + P_load(node, index);
end
end
% 更新全局恢复节点
island_node_all = union(island_node_all, min_path);
break;
end
end
end
end
%% 步骤7:负荷削减
for k = 1:island_num
% 获取孤岛信息
current_nodes = island_node_cross{k};
current_power = sum(P_PV(index, island_cross_DG{k}));
current_load = island_load(k);
% 检查功率是否不足
if current_power < current_load
% 第一步:削减完全可控负荷
for node_idx = 1:length(current_nodes)
node = current_nodes(node_idx);
if ismember(node, C_load1) % 完全可控负荷
current_load = current_load - P_load(node, index);
island_node_cross{k} = setdiff(island_node_cross{k}, node);
if current_power >= current_load
break;
end
end
end
% 第二步:削减50%可控负荷
if current_power < current_load
for node_idx = 1:length(current_nodes)
node = current_nodes(node_idx);
if ismember(node, C_load2) % 50%可控负荷
current_load = current_load - 0.5 * P_load(node, index);
if current_power >= current_load
break;
end
end
end
end
% 第三步:按重要度等级切负荷
if current_power < current_load
% 获取孤岛内节点的重要度排序
[~, idx] = sort(Ft(current_nodes, time), 'descend');
sorted_nodes = current_nodes(idx);
for node_idx = 1:length(sorted_nodes)
node = sorted_nodes(node_idx);
current_load = current_load - P_load(node, index);
island_node_cross{k} = setdiff(island_node_cross{k}, node);
if current_power >= current_load
break;
end
end
end
% 更新孤岛负荷
island_load(k) = current_load;
end
end
%% 步骤8:输出孤岛划分方案
disp('=================== 孤岛划分最终方案 ===================');
for k = 1:island_num
disp(['*************** 第', num2str(k), '个孤岛 ***************'])
disp(['包含光储系统: ' , num2str(island_cross_DG{k})])
disp(['光储系统总功率: ' , num2str(sum(P_PV(index, island_cross_DG{k}))) , ' kW'])
disp(['包含节点: ' , num2str(sort(island_node_cross{k}))])
disp(['孤岛内负荷总需求: ' , num2str(island_load(k)) , ' kW'])
disp(' ');
end
end
%% 洪水算法核心函数
function [island, total_load] = flood_fill(start, graph, capacity, P_load, time)
n = length(graph);
visited = false(1, n); % 访问标记
queue = start; % 初始化队列
island = []; % 孤岛节点集合
total_load = 0; % 孤岛总负荷
while ~isempty(queue)
current = queue(1); % 获取队列首节点
queue(1) = []; % 移除首节点
% 跳过已访问节点
if visited(current)
continue;
end
% 检查功率约束(考虑5%裕度)
if total_load + P_load(current) > capacity * 1.05
continue;
end
% 加入孤岛
visited(current) = true;
island(end+1) = current;
total_load = total_load + P_load(current);
% 获取邻居节点(按重要度排序)
neighbors = graph{current};
if ~isempty(neighbors)
% 按重要度排序(重要度高的优先)
[~, idx] = sort(P_load(neighbors, time), 'descend');
neighbors = neighbors(idx);
end
% 添加未访问邻居到队列
for i = 1:length(neighbors)
neighbor = neighbors(i);
if ~visited(neighbor)
queue(end+1) = neighbor;
end
end
end
% 确保包含起始节点
if ~ismember(start, island)
island = [start, island];
total_load = total_load + P_load(start);
end
end
%% 构建拓扑图(排除故障支路)
function graph = build_graph(mpc, fault_branches)
Nb = size(mpc.bus, 1);
graph = cell(Nb, 1); % 创建空邻接表
% 遍历所有支路
for i = 1:size(mpc.branch, 1)
% 跳过故障支路
if ismember(i, fault_branches)
continue;
end
from = mpc.branch(i, 1);
to = mpc.branch(i, 2);
% 添加双向连接(无向图)
graph{from} = [graph{from}, to];
graph{to} = [graph{to}, from];
end
% 确保所有节点都有定义(即使没有连接)
for i = 1:Nb
if isempty(graph{i})
graph{i} = [];
end
end
end
%% 寻找最近DG的路径
function [nearest_dg, min_path] = find_nearest_dg(start, dg_nodes, graph, island_node_all)
n = length(graph);
visited = false(1, n); % 访问标记
queue = {start}; % 队列(存储路径)
min_dist = Inf; % 最小距离
nearest_dg = -1; % 最近的DG
min_path = []; % 最短路径
% BFS搜索最短路径
while ~isempty(queue)
current_path = queue{1}; % 获取当前路径
current_node = current_path(end); % 当前节点
queue(1) = []; % 移除队列首项
% 跳过已访问节点
if visited(current_node)
continue;
end
visited(current_node) = true;
% 检查是否到达DG节点
if ismember(current_node, dg_nodes)
dist = length(current_path) - 1;
if dist < min_dist
min_dist = dist;
nearest_dg = current_node;
min_path = current_path;
end
continue;
end
% 遍历邻居节点
neighbors = graph{current_node};
for i = 1:length(neighbors)
neighbor = neighbors(i);
% 跳过已恢复节点(除DG外)
if ~ismember(neighbor, island_node_all) || ismember(neighbor, dg_nodes)
if ~visited(neighbor)
new_path = [current_path, neighbor];
queue{end+1} = new_path;
end
end
end
end
% 如果未找到路径,返回最近DG(直接连接)
if isempty(min_path) && ~isempty(dg_nodes)
nearest_dg = dg_nodes(1);
min_path = [start, nearest_dg];
end
end
%% IEEE33节点配电网数据
function mpc1 = IEEE33()
%% MATPOWER Case Format : Version 2
mpc1.version = '2';
%%----- Power Flow Data -----%%
%% system MVA base
mpc1.baseMVA = 10;
%% bus data
% bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin
mpc1.bus = [ %% (Pd and Qd are specified in kW & kVAr here, converted to MW & MVAr below)
1 3 0 0 0 0 1 1 0 12.66 1 1 1;
2 1 100 60 0 0 1 1 0 12.66 1 1.1 0.9;
3 1 90 40 0 0 1 1 0 12.66 1 1.1 0.9;
4 1 120 80 0 0 1 1 0 12.66 1 1.1 0.9;
5 1 60 30 0 0 1 1 0 12.66 1 1.1 0.9;
6 1 60 20 0 0 1 1 0 12.66 1 1.1 0.9;
7 1 200 100 0 0 1 1 0 12.66 1 1.1 0.9;
8 1 200 100 0 0 1 1 0 12.66 1 1.1 0.9;
9 1 60 20 0 0 1 1 0 12.66 1 1.1 0.9;
10 1 60 20 0 0 1 1 0 12.66 1 1.1 0.9;
11 1 45 30 0 0 1 1 0 12.66 1 1.1 0.9;
12 1 60 35 0 0 1 1 0 12.66 1 1.1 0.9;
13 1 60 35 0 0 1 1 0 12.66 1 1.1 0.9;
14 1 120 80 0 0 1 1 0 12.66 1 1.1 0.9;
15 1 60 10 0 0 1 1 0 12.66 1 1.1 0.9;
16 1 60 20 0 0 1 1 0 12.66 1 1.1 0.9;
17 1 60 20 0 0 1 1 0 12.66 1 1.1 0.9;
18 1 90 40 0 0 1 1 0 12.66 1 1.1 0.9;
19 1 90 40 0 0 1 1 0 12.66 1 1.1 0.9;
20 1 90 40 0 0 1 1 0 12.66 1 1.1 0.9;
21 1 90 40 0 0 1 1 0 12.66 1 1.1 0.9;
22 1 90 40 0 0 1 1 0 12.66 1 1.1 0.9;
23 1 90 50 0 0 1 1 0 12.66 1 1.1 0.9;
24 1 420 200 0 0 1 1 0 12.66 1 1.1 0.9;
25 1 420 200 0 0 1 1 0 12.66 1 1.1 0.9;
26 1 60 25 0 0 1 1 0 12.66 1 1.1 0.9;
27 1 60 25 0 0 1 1 0 12.66 1 1.1 0.9;
28 1 60 20 0 0 1 1 0 12.66 1 1.1 0.9;
29 1 120 70 0 0 1 1 0 12.66 1 1.1 0.9;
30 1 200 600 0 0 1 1 0 12.66 1 1.1 0.9;
31 1 150 70 0 0 1 1 0 12.66 1 1.1 0.9;
32 1 210 100 0 0 1 1 0 12.66 1 1.1 0.9;
33 1 60 40 0 0 1 1 0 12.66 1 1.1 0.9;
];
%% generator data
% bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf
mpc1.gen = [
1 0 0 10 -10 1 100 1 10 0 0 0 0 0 0 0 0 0 0 0 0;
];
%% branch data
% fbus tbus r x b rateA rateB rateC ratio angle status angmin angmax
mpc1.branch = [ %% (r and x specified in ohms here, converted to p.u. below)
1 2 0.0922 0.0470 0 0 0 0 0 0 1 -360 360;
2 3 0.4930 0.2511 0 0 0 0 0 0 1 -360 360;
3 4 0.3660 0.1864 0 0 0 0 0 0 1 -360 360;
4 5 0.3811 0.1941 0 0 0 0 0 0 1 -360 360;
5 6 0.8190 0.7070 0 0 0 0 0 0 1 -360 360;
6 7 0.1872 0.6188 0 0 0 0 0 0 1 -360 360;
7 8 0.7114 0.2351 0 0 0 0 0 0 1 -360 360;
8 9 1.0300 0.7400 0 0 0 0 0 0 1 -360 360;
9 10 1.0440 0.7400 0 0 0 0 0 0 1 -360 360;
10 11 0.1966 0.0650 0 0 0 0 0 0 1 -360 360;
11 12 0.3744 0.1238 0 0 0 0 0 0 1 -360 360;
12 13 1.4680 1.1550 0 0 0 0 0 0 1 -360 360;
13 14 0.5416 0.7129 0 0 0 0 0 0 1 -360 360;
14 15 0.5910 0.5260 0 0 0 0 0 0 1 -360 360;
15 16 0.7463 0.5450 0 0 0 0 0 0 1 -360 360;
16 17 1.2890 1.7210 0 0 0 0 0 0 1 -360 360;
17 18 0.7320 0.5740 0 0 0 0 0 0 1 -360 360;
2 19 0.1640 0.1565 0 0 0 0 0 0 1 -360 360;
19 20 1.5042 1.3554 0 0 0 0 0 0 1 -360 360;
20 21 0.4095 0.4784 0 0 0 0 0 0 1 -360 360;
21 22 0.7089 0.9373 0 0 0 0 0 0 1 -360 360;
3 23 0.4512 0.3083 0 0 0 0 0 0 1 -360 360;
23 24 0.8980 0.7091 0 0 0 0 0 0 1 -360 360;
24 25 0.8960 0.7011 0 0 0 0 0 0 1 -360 360;
6 26 0.2030 0.1034 0 0 0 0 0 0 1 -360 360;
26 27 0.2842 0.1447 0 0 0 0 0 0 1 -360 360;
27 28 1.0590 0.9337 0 0 0 0 0 0 1 -360 360;
28 29 0.8042 0.7006 0 0 0 0 0 0 1 -360 360;
29 30 0.5075 0.2585 0 0 0 0 0 0 1 -360 360;
30 31 0.9744 0.9630 0 0 0 0 0 0 1 -360 360;
31 32 0.3105 0.3619 0 0 0 0 0 0 1 -360 360;
32 33 0.3410 0.5302 0 0 0 0 0 0 1 -360 360;
21 8 2.0000 2.0000 0 0 0 0 0 0 0 -360 360;
9 15 2.0000 2.0000 0 0 0 0 0 0 0 -360 360;
12 22 2.0000 2.0000 0 0 0 0 0 0 0 -360 360;
18 33 0.5000 0.5000 0 0 0 0 0 0 0 -360 360;
25 29 0.5000 0.5000 0 0 0 0 0 0 0 -360 360;
];
%%----- OPF Data -----%%
%% generator cost data
% 1 startup shutdown n x1 y1 ... xn yn
% 2 startup shutdown n c(n-1) ... c0
mpc1.gencost = [
2 0 0 3 0 20 0;
];
%% convert branch impedances from Ohms to p.u.
[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
[F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
Vbase = mpc1.bus(1, BASE_KV) * 1e3; %% in Volts
Sbase = mpc1.baseMVA * 1e6; %% in VA
mpc1.branch(:, [BR_R BR_X]) = mpc1.branch(:, [BR_R BR_X]) / (Vbase^2 / Sbase);
%% convert loads from kW to MW
mpc1.bus(:, [PD, QD]) = mpc1.bus(:, [PD, QD]) / 1e3;
end
%% 辅助函数:总线索引
function [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus
PQ = 1;
PV = 2;
REF = 3;
NONE = 4;
BUS_I = 1;
BUS_TYPE = 2;
PD = 3;
QD = 4;
GS = 5;
BS = 6;
BUS_AREA = 7;
VM = 8;
VA = 9;
BASE_KV = 10;
ZONE = 11;
VMAX = 12;
VMIN = 13;
LAM_P = 14;
LAM_Q = 15;
MU_VMAX = 16;
MU_VMIN = 17;
end
%% 辅助函数:支路索引
function [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, ...
RATE_C, TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch
F_BUS = 1;
T_BUS = 2;
BR_R = 3;
BR_X = 4;
BR_B = 5;
RATE_A = 6;
RATE_B = 7;
RATE_C = 8;
TAP = 9;
SHIFT = 10;
BR_STATUS = 11;
ANGMIN = 12;
ANGMAX = 13;
PF = 14;
QF = 15;
PT = 16;
QT = 17;
MU_SF = 18;
MU_ST = 19;
MU_ANGMIN = 20;
MU_ANGMAX = 21;
end
```
### 洪水算法实现关键点说明
1. **洪水算法核心逻辑**:
```matlab
function [island, total_load] = flood_fill(start, graph, capacity, P_load, time)
% 初始化
visited = false(1, n);
queue = start;
while ~isempty(queue)
current = queue(1);
queue(1) = [];
% 功率约束检查
if total_load + P_load(current) > capacity * 1.05
continue;
end
% 加入孤岛
visited(current) = true;
island(end+1) = current;
total_load = total_load + P_load(current);
% 邻居节点按重要度排序
neighbors = graph{current};
[~, idx] = sort(P_load(neighbors, time), 'descend');
neighbors = neighbors(idx);
% 添加邻居到队列
for neighbor = neighbors
if ~visited(neighbor)
queue(end+1) = neighbor;
end
end
end
end
```
2. **孤岛融合算法**:
```matlab
% 动态融合交叉孤岛
i = 1;
while i <= island_num
j = i + 1;
while j <= island_num
if ~isempty(intersect(island_node_cross{i}, island_node_cross{j}))
% 合并孤岛
island_node_cross{i} = union(..., ...);
island_cross_DG{i} = [..., ...];
% 更新功率和负荷
island_power(i) = island_power(i) + island_power(j);
island_load(i) = island_load(i) + island_load(j);
% 移除被融合孤岛
island_node_cross(j) = [];
island_cross_DG(j) = [];
island_num = island_num - 1;
end
end
end
```
3. **优先负荷连接策略**:
```matlab
% BFS最短路径搜索
function [nearest_dg, min_path] = find_nearest_dg(...)
while ~isempty(queue)
current_path = queue{1};
current_node = current_path(end);
if ismember(current_node, dg_nodes)
% 找到最近DG
if length(current_path)-1 < min_dist
min_dist = length(current_path)-1;
nearest_dg = current_node;
min_path = current_path;
end
end
% 扩展邻居
for neighbor = graph{current_node}
if ~visited(neighbor) && (~ismember(neighbor, island_node_all) || ...)
new_path = [current_path, neighbor];
queue{end+1} = new_path;
end
end
end
end
```
### 算法优势与创新点
1. **高效洪水算法**:
- 采用队列实现广度优先搜索
- 按负荷重要度排序邻居节点
- 实时功率约束校验(5%裕度)
2. **动态孤岛融合**:
- 自动检测交叉孤岛
- 动态更新孤岛功率和负荷
- 避免重复节点和功率计算
3. **智能负荷管理**:
- 三级负荷削减策略(完全可控→50%可控→按重要度)
- 优先恢复关键负荷
- 负荷重要度动态排序
4. **鲁棒性设计**:
- 处理未连通节点
- 故障支路排除
- 边界条件检查