%% 粒子群算法求解最小生成树
function [best_mst, best_weight] = pso_mst(graph, pop_size, max_iter)
% 输入: graph - 邻接矩阵
% pop_size - 粒子群大小
% max_iter - 最大迭代次数
% 输出: best_mst - 最佳MST边列表
% best_weight - 最佳权重
n = size(graph, 1); % 节点数量 num_edges = n - 1; % MST边数量 % 初始化粒子群 particles = cell(pop_size, 1); velocities = cell(pop_size, 1); pbest = cell(pop_size, 1); pbest_weight = inf(1, pop_size); % 全局最佳 gbest_weight = inf; gbest = []; % 初始化粒子 for i = 1:pop_size % 随机生成树作为粒子 particles{i} = generate_random_spanning_tree(graph); velocities{i} = zeros(size(particles{i})); pbest{i} = particles{i}; pbest_weight(i) = tree_weight(graph, particles{i}); % 更新全局最佳 if pbest_weight(i) < gbest_weight gbest_weight = pbest_weight(i); gbest = particles{i}; end end % PSO参数 w = 0.7; % 惯性权重 c1 = 1.5; % 个体学习因子 c2 = 1.5; % 社会学习因子 % 迭代优化 for iter = 1:max_iter for i = 1:pop_size % 更新速度 r1 = rand(); r2 = rand(); velocities{i} = w * velocities{i} + ... c1 * r1 * (pbest{i} - particles{i}) + ... c2 * r2 * (gbest - particles{i}); % 更新位置 (离散化处理) new_tree = update_tree(particles{i}, velocities{i}, graph); % 计算适应度 weight = tree_weight(graph, new_tree); % 更新个体最佳 if weight < pbest_weight(i) pbest_weight(i) = weight; pbest{i} = new_tree; % 更新全局最佳 if weight < gbest_weight gbest_weight = weight; gbest = new_tree; end end particles{i} = new_tree; end % 动态调整惯性权重 w = w * 0.99; fprintf('迭代 %d: 最佳权重 = %.2f\n', iter, gbest_weight); end % 转换结果为边列表 [best_mst, best_weight] = tree_to_edges(gbest, graph);
end
%% 辅助函数
function tree = generate_random_spanning_tree(graph)
% 生成随机生成树 (Prim变体)
n = size(graph, 1);
visited = false(1, n);
tree = zeros(n); % 邻接矩阵表示树
start = randi(n); visited(start) = true; nodes_in_tree = start; while sum(visited) < n candidates = []; for node = nodes_in_tree neighbors = find(graph(node, :) > 0 & ~visited); for nbr = neighbors candidates = [candidates; node, nbr, graph(node, nbr)]; end end if isempty(candidates) break; end % 随机选择一条边 idx = randi(size(candidates, 1)); edge = candidates(idx, :); tree(edge(1), edge(2)) = edge(3); tree(edge(2), edge(1)) = edge(3); visited(edge(2)) = true; nodes_in_tree = [nodes_in_tree, edge(2)]; end
end
function weight = tree_weight(graph, tree)
% 计算树的权重
weight = sum(sum(tree)) / 2; % 邻接矩阵对称,除以2避免重复计算
end
function new_tree = update_tree(tree, velocity, graph)
% 基于速度更新树结构
n = size(tree, 1);
new_tree = tree;
% 概率性添加/删除边 for i = 1:n for j = i+1:n if velocity(i, j) > rand() % 添加边 (如果存在且不在树中) if graph(i, j) > 0 && tree(i, j) == 0 % 检查是否形成环 temp_tree = new_tree; temp_tree(i, j) = graph(i, j); temp_tree(j, i) = graph(i, j); if ~has_cycle(temp_tree) new_tree = temp_tree; end end elseif velocity(i, j) < -rand() % 删除边 (如果存在) if tree(i, j) > 0 % 检查是否保持连通 temp_tree = new_tree; temp_tree(i, j) = 0; temp_tree(j, i) = 0; if is_connected(temp_tree) new_tree = temp_tree; end end end end end
end
function [edges, weight] = tree_to_edges(tree, graph)
% 将邻接矩阵转换为边列表
n = size(tree, 1);
edges = [];
weight = 0;
for i = 1:n for j = i+1:n if tree(i, j) > 0 edges = [edges; i, j, tree(i, j)]; weight = weight + tree(i, j); end end end
end
%% 连通性和环检测函数
function connected = is_connected(tree)
% 检查图是否连通 (BFS)
n = size(tree, 1);
visited = false(1, n);
queue = 1; % 从节点1开始
while ~isempty(queue) node = queue(1); queue(1) = []; visited(node) = true; neighbors = find(tree(node, :) > 0); for nbr = neighbors if ~visited(nbr) queue = [queue, nbr]; end end end connected = all(visited);
end
function cycle = has_cycle(tree)
% 检查图是否有环 (DFS)
n = size(tree, 1);
visited = false(1, n);
for i = 1:n if ~visited(i) if dfs_cycle(tree, i, visited, -1) cycle = true; return; end end end cycle = false;
end
function found = dfs_cycle(tree, node, visited, parent)
% DFS环检测辅助函数
visited(node) = true;
neighbors = find(tree(node, :) > 0); for nbr = neighbors if ~visited(nbr) if dfs_cycle(tree, nbr, visited, node) found = true; return; end elseif nbr ~= parent found = true; return; end end found = false;
end
%% 测试PSO算法
[best_mst, best_weight] = pso_mst(graph, 20, 50);
fprintf(‘\nPSO算法MST结果:\n’);
disp(array2table(best_mst, ‘VariableNames’, {‘Node1’, ‘Node2’, ‘Weight’}));
fprintf(‘总权重: %.2f\n’, best_weight);
请用以上的PSO算法替换下列洪水算法解决IEEE33节点的孤岛划分问题,并对比总结优缺点:%% IEEE33节点孤岛划分程序(修复版)
function island_division(varargin)
% 输入参数:
% index - 时段索引(1或2),可选
% visualize_flood - 是否可视化洪水算法扩散过程(true/false),可选
% 使用示例:
% island_division() % 默认时段1,不可视化扩散
% island_division(1) % 时段1,不可视化扩散
% island_division(2, true) % 时段2,可视化扩散过程
% island_division(‘visualize’, true) % 时段1,可视化扩散
%% 步骤1:处理输入参数
visualize_flood = false; % 默认不可视化扩散过程
index = 1; % 默认时段1
for i = 1:length(varargin)
if ischar(varargin{i}) && strcmpi(varargin{i}, ‘visualize’)
visualize_flood = varargin{i+1};
elseif isnumeric(varargin{i}) && ismember(varargin{i}, [1, 2])
index = varargin{i};
end
end
fprintf(‘运行时段: %d, 可视化扩散: %d\n’, index, visualize_flood);
%% 步骤2:加载完整IEEE33节点数据
mpc = load_case_ieee33(); % 加载完整IEEE33数据
Nb = 33; % 节点数
Nt = 24; % 时段数
%% 步骤3:系统参数设置
% 光储系统接入位置和出力
Y_DG = [6, 8, 12, 23, 30]; % 光储系统接入位置
P_PV = [425, 200, 480, 120, 600; % 时段1各光伏出力
700, 500, 720, 620, 720]; % 时段2各光伏出力
% 负荷等级和需求系数
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
Ct(setdiff(1:Nb, [6, 12, 23, 30]), 😃 = ones(Nb-4,1)10…
[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;
Ft = Ct.*(wf’*ones(1, Nt)); % 优先恢复系数
% 负荷总量和节点负荷
PL = [3305, 4870]; % 负荷总量
total_original_load = sum(mpc.bus(:,3)); % 原始总负荷3715 kW
P_load = zeros(Nb, 2);
for t = 1:2
P_load(:, t) = mpc.bus(:,3) * (PL(t) / total_original_load);
end
% 可控负荷设置
a_cut = zeros(1,Nb); % 削减系数
C_load1 = [3,13,20,24]; % 完全可控的负荷集合
a_cut(C_load1) = 1; % 完全可控
C_load2 = [2,7,10]; % 50%可控的负荷集合
a_cut(C_load2) = 0.5; % 50%可控
%% 步骤4:故障支路设置
fault_branch = [5, 25, 20]; % 故障支路
%% 步骤5:确定当前时段
time0 = [7, 15]; % 故障发生时刻
time_value = time0(index); % 当前时刻值
time_idx = index; % 当前时段索引
%% 步骤6:确定优先恢复集合
F_Rload = {[6, 12, 15, 23, 28, 30], [6, 12, 23, 30, 32]};
%% 步骤7:构建邻接矩阵(考虑故障支路断开)
branch = mpc.branch;
A = zeros(Nb);
for i = 1:size(branch, 1)
from = branch(i, 1);
to = branch(i, 2);
A(from, to) = 1;
A(to, from) = 1; % 无向图
end
% 断开故障支路
for i = 1:length(fault_branch)
br = fault_branch(i);
from = branch(br, 1);
to = branch(br, 2);
A(from, to) = 0;
A(to, from) = 0;
end
%% 步骤8:使用改进洪水算法形成初始孤岛
visited_global = false(1, Nb); % 全局访问标记
island_node = cell(1, length(Y_DG)); % 各孤岛节点集合
island_power = zeros(1, length(Y_DG)); % 各孤岛光伏出力
island_load = zeros(1, length(Y_DG)); % 各孤岛负荷总量
% 生成节点坐标
node_coords = generate_radial_coords(Nb);
% 修复:创建可视化窗口的句柄数组
fig_handles = gobjects(1, length(Y_DG)); % 预分配图形对象句柄
for k = 1:length(Y_DG)
% 创建洪水算法可视化窗口
if visualize_flood
fig_handles(k) = figure(‘Name’, sprintf(‘洪水算法扩散 - 光储节点%d’, Y_DG(k)), …
‘Position’, [100, 100, 800, 600]);
ax = axes(fig_handles(k));
visualize_graph(ax, A, node_coords, fault_branch);
hold(ax, ‘on’);
plot(ax, node_coords(Y_DG(k), 1), node_coords(Y_DG(k), 2), …
‘p’, ‘MarkerSize’, 20, ‘MarkerFaceColor’, ‘y’, ‘MarkerEdgeColor’, ‘k’);
title(ax, sprintf(‘从节点%d开始扩散 (功率: %.1f kW)’, Y_DG(k), P_PV(time_idx, k)));
drawnow;
else
fig_handles(k) = gobjects(1); % 创建空图形对象
end
% 修复:使用正确的参数调用FLA_power [island_node{k}, island_load(k)] = FLA_power(... Y_DG(k), ... % 光伏节点 P_PV(time_idx, k), ...% 光伏出力 A, ... % 邻接矩阵 P_load, ... % 负荷数据 time_idx, ... % 当前时段索引 visited_global, ... % 全局访问标记 visualize_flood, ... % 可视化标志 node_coords, ... % 节点坐标 fig_handles(k)); % 可视化窗口句柄 % 更新全局访问状态 visited_global(island_node{k}) = true; island_power(k) = P_PV(time_idx, k); % 关闭可视化窗口 if visualize_flood pause(1); % 显示1秒后关闭 close(fig_handles(k)); end
end
%% 步骤9:处理孤岛交叉(融合重叠孤岛)
island_node_cross = {}; % 融合后的孤岛
island_cross_DG = {}; % 融合后的孤岛对应的光伏节点
island_power_cross = []; % 融合后的孤岛总出力
island_load_cross = []; % 融合后的孤岛总负荷
% 初始化:第一个孤岛
if ~isempty(island_node{1})
island_node_cross{1} = island_node{1};
island_cross_DG{1} = 1;
island_power_cross(1) = island_power(1);
island_load_cross(1) = island_load(1);
end
% 处理后续孤岛
for k = 2:length(Y_DG)
merged = false;
% 检查是否与已有孤岛重叠 for i = 1:length(island_node_cross) if ~isempty(intersect(island_node{k}, island_node_cross{i})) % 合并孤岛 island_node_cross{i} = union(island_node_cross{i}, island_node{k}); island_cross_DG{i} = union(island_cross_DG{i}, k); island_power_cross(i) = island_power_cross(i) + island_power(k); island_load_cross(i) = island_load_cross(i) + island_load(k); merged = true; break; end end % 若无重叠,创建新孤岛 if ~merged && ~isempty(island_node{k}) island_node_cross{end+1} = island_node{k}; island_cross_DG{end+1} = k; island_power_cross(end+1) = island_power(k); island_load_cross(end+1) = island_load(k); end
end
%% 步骤10:连接优先恢复负荷
island_node_all = [];
for i = 1:length(island_node_cross)
island_node_all = union(island_node_all, island_node_cross{i});
end
for k = 1:length(F_Rload{index})
node = F_Rload{index}(k);
if ~ismember(node, island_node_all) % 查找最近孤岛 min_dist = inf; target_island = 0; for i = 1:length(island_node_cross) % 使用洪水算法计算距离 dist = FLA_distance(node, island_node_cross{i}, A); if dist < min_dist min_dist = dist; target_island = i; end end % 将节点加入目标孤岛 if target_island > 0 island_node_cross{target_island} = union(... island_node_cross{target_island}, node); island_node_all = union(island_node_all, node); % 更新孤岛负荷 island_load_cross(target_island) = island_load_cross(target_island) + P_load(node, time_idx); end end
end
%% 步骤11:负荷削减(满足功率平衡)
for i = 1:length(island_node_cross)
if island_power_cross(i) < island_load_cross(i)
% 按节点优先级排序(优先切除低优先级负荷)
[~, idx] = sort(Ft(island_node_cross{i}, time_idx), ‘ascend’);
sorted_nodes = island_node_cross{i}(idx);
% 逐步切除负荷直到满足功率平衡 for j = 1:length(sorted_nodes) node = sorted_nodes(j); if ismember(node, C_load1) % 完全可控负荷 island_load_cross(i) = island_load_cross(i) - P_load(node, time_idx); island_node_cross{i} = setdiff(island_node_cross{i}, node); elseif ismember(node, C_load2) % 50%可控负荷 island_load_cross(i) = island_load_cross(i) - 0.5*P_load(node, time_idx); % 更新节点剩余负荷 P_load(node, time_idx) = 0.5*P_load(node, time_idx); end % 检查是否满足功率平衡 if island_power_cross(i) >= island_load_cross(i) break; end end % 如果仍不满足,继续切除其他负荷 if island_power_cross(i) < island_load_cross(i) [~, idx] = sort(Ft(island_node_cross{i}, time_idx), 'ascend'); sorted_nodes = island_node_cross{i}(idx); for j = 1:length(sorted_nodes) node = sorted_nodes(j); island_load_cross(i) = island_load_cross(i) - P_load(node, time_idx); island_node_cross{i} = setdiff(island_node_cross{i}, node); if island_power_cross(i) >= island_load_cross(i) break; end end end end
end
%% 步骤12:输出孤岛划分方案
fprintf(‘\n===== 时段%d (%d:00) 孤岛划分结果 =====\n’, index, time_value);
fprintf(‘故障支路: %s\n’, mat2str(fault_branch));
fprintf(‘优先恢复负荷: %s\n\n’, mat2str(F_Rload{index}));
for i = 1:length(island_node_cross)
fprintf(‘孤岛%d:\n’, i);
fprintf(’ - 光储系统: %s (总功率: %.1f kW)\n’, …
mat2str(Y_DG(island_cross_DG{i})), …
island_power_cross(i));
fprintf(’ - 包含节点: %s\n’, mat2str(sort(island_node_cross{i})));
fprintf(’ - 负荷总量: %.1f kW\n’, island_load_cross(i));
fprintf(’ - 功率平衡: %.1f kW (利用率: %.1f%%)\n’, …
island_power_cross(i) - island_load_cross(i), …
100*island_load_cross(i)/island_power_cross(i));
fprintf(‘----------------------------------------\n’);
end
%% 可视化孤岛划分结果
visualize_islands(mpc, island_node_cross, Y_DG, fault_branch, index);
end
%% 改进洪水算法核心函数(修复版)
function [island_nodes, total_load] = FLA_power(start_node, max_power, A, P_load, idx_time, visited_global, visualize, node_coords, fig_handle)
% FLA洪水算法改进版 - 含可视化功能
queue = [];
island_nodes = [];
total_load = 0;
diffusion_speed = 0.2; % 扩散速度(秒/步)
% 1. 处理起始节点 if ~visited_global(start_node) visited_global(start_node) = true; queue = [queue, start_node]; island_nodes = [island_nodes, start_node]; total_load = total_load + P_load(start_node, idx_time); % 可视化起始节点(添加安全检查和条件判断) if visualize && isvalid(fig_handle) ax = fig_handle.CurrentAxes; plot(ax, node_coords(start_node, 1), node_coords(start_node, 2), ... 'o', 'MarkerSize', 12, 'MarkerFaceColor', 'g', 'MarkerEdgeColor', 'k'); text(ax, node_coords(start_node, 1)+0.2, node_coords(start_node, 2)+0.2, ... sprintf('%.1f kW', P_load(start_node, idx_time)), 'FontSize', 9); drawnow; pause(diffusion_speed); end else return; % 起始节点已访问,直接返回 end % 2. 洪水算法扩散过程 step = 0; while ~isempty(queue) step = step + 1; current = queue(1); queue(1) = []; % 可视化当前节点(添加安全检查和条件判断) if visualize && isvalid(fig_handle) ax = fig_handle.CurrentAxes; plot(ax, node_coords(current, 1), node_coords(current, 2), ... 'o', 'MarkerSize', 10, 'MarkerFaceColor', 'b', 'MarkerEdgeColor', 'k'); drawnow; pause(diffusion_speed); end % 获取当前节点的所有邻居 all_neighbors = find(A(current, :)); % 检查每个邻居的可行性和功率约束 for neighbor = all_neighbors % 跳过已访问节点 if visited_global(neighbor) continue; end % 计算添加该节点后的新负荷 new_load = total_load + P_load(neighbor, idx_time); % 功率约束检查 if new_load <= max_power % 标记为已访问 visited_global(neighbor) = true; % 加入队列和孤岛 queue = [queue, neighbor]; island_nodes = [island_nodes, neighbor]; total_load = new_load; % 更新总负荷 % 可视化新加入节点(添加安全检查和条件判断) if visualize && isvalid(fig_handle) ax = fig_handle.CurrentAxes; plot(ax, node_coords(neighbor, 1), node_coords(neighbor, 2), ... 'o', 'MarkerSize', 8, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k'); text(ax, node_coords(neighbor, 1)+0.2, node_coords(neighbor, 2)+0.2, ... sprintf('%.1f kW', P_load(neighbor, idx_time)), 'FontSize', 8); % 绘制连接线 line(ax, [node_coords(current, 1), node_coords(neighbor, 1)], ... [node_coords(current, 2), node_coords(neighbor, 2)], ... 'Color', 'g', 'LineWidth', 2, 'LineStyle', '-'); % 更新标题 title(ax, sprintf('从节点%d扩散 (已加入%d节点, 负荷:%.1f/%.1f kW)', ... start_node, length(island_nodes), total_load, max_power)); drawnow; pause(diffusion_speed/2); end end end end % 可视化最终孤岛(添加安全检查和条件判断) if visualize && isvalid(fig_handle) && length(island_nodes) >= 3 ax = fig_handle.CurrentAxes; % 绘制孤岛边界 k = convhull(node_coords(island_nodes, 1), node_coords(island_nodes, 2)); plot(ax, node_coords(island_nodes(k), 1), node_coords(island_nodes(k), 2), ... 'Color', 'm', 'LineWidth', 2, 'LineStyle', '--'); % 添加功率平衡信息 text(ax, 0.5, -1.5, sprintf('最终孤岛: %d节点, 负荷: %.1f kW (利用率: %.1f%%)', ... length(island_nodes), total_load, 100*total_load/max_power), ... 'FontSize', 10, 'BackgroundColor', 'w'); drawnow; end
end
%% 洪水算法距离计算函数
function [dist] = FLA_distance(start, targets, A)
% 洪水算法计算最短距离
n = size(A, 1);
visited = false(1, n);
distance = inf(1, n);
queue = [];
visited(start) = true; distance(start) = 0; queue = [queue, start]; while ~isempty(queue) current = queue(1); queue(1) = []; % 检查是否到达目标 if ismember(current, targets) dist = distance(current); return; end % 扩散到邻居节点 neighbors = find(A(current, :) & ~visited); for neighbor = neighbors visited(neighbor) = true; distance(neighbor) = distance(current) + 1; queue = [queue, neighbor]; end end dist = inf; % 未找到路径
end
%% 网络可视化辅助函数
function visualize_graph(ax, A, node_coords, fault_branch)
% 绘制网络基础结构
hold(ax, ‘on’);
grid(ax, ‘on’);
axis(ax, ‘equal’);
% 绘制节点 n = size(A, 1); for i = 1:n plot(ax, node_coords(i, 1), node_coords(i, 2), ... 'ko', 'MarkerSize', 8, 'MarkerFaceColor', 'w'); text(ax, node_coords(i, 1)+0.1, node_coords(i, 2)+0.1, ... num2str(i), 'FontSize', 9); end % 绘制支路 [rows, cols] = find(triu(A)); % 只绘制上三角避免重复 for i = 1:length(rows) from = rows(i); to = cols(i); x = [node_coords(from, 1), node_coords(to, 1)]; y = [node_coords(from, 2), node_coords(to, 2)]; % 检查是否为故障支路 is_fault = false; for j = 1:length(fault_branch) br = fault_branch(j); if (from == br && to == br) || ... % 自环 (from == br || to == br) % 连接故障节点 is_fault = true; break; end end if is_fault plot(ax, x, y, 'r--', 'LineWidth', 1.5); else plot(ax, x, y, 'k-', 'LineWidth', 1); end end title(ax, 'IEEE33节点配电网拓扑'); xlabel(ax, 'X坐标'); ylabel(ax, 'Y坐标');
end
%% 修复版孤岛可视化函数
function visualize_islands(mpc, islands, dg_nodes, fault_branch, index)
% 可视化孤岛划分结果 - 修复凸包计算问题
fig = figure(‘Name’, ['时段 ‘, num2str(index), ’ 孤岛划分’], …
‘Position’, [100, 100, 900, 700]);
ax = axes(fig);
hold(ax, ‘on’);
% 生成节点坐标 node_coords = generate_radial_coords(33); % 绘制基础网络 visualize_graph(ax, mpc2adjacency(mpc), node_coords, fault_branch); % 绘制孤岛 colors = lines(length(islands)); legend_handles = []; legend_labels = {}; for i = 1:length(islands) nodes = islands{i}; if isempty(nodes) continue; end % === 修复凸包计算问题 === % 检查节点是否共线 is_collinear = check_collinear(node_coords(nodes, :)); % 绘制孤岛边界(修复凸包问题) if length(nodes) >= 3 && ~is_collinear % 正常情况:计算凸包 k = convhull(node_coords(nodes, 1), node_coords(nodes, 2)); plot(ax, node_coords(nodes(k), 1), node_coords(nodes(k), 2), ... 'Color', colors(i, :), 'LineWidth', 2, 'LineStyle', '--'); elseif length(nodes) >= 2 % 节点共线或只有2个节点:绘制最小包围矩形 [rect_x, rect_y] = min_bounding_rect(node_coords(nodes, :)); plot(ax, rect_x, rect_y, ... 'Color', colors(i, :), 'LineWidth', 2, 'LineStyle', '--'); end % ====================== % 绘制孤岛节点 for j = 1:length(nodes) h = plot(ax, node_coords(nodes(j), 1), node_coords(nodes(j), 2), ... 'o', 'MarkerSize', 10, 'MarkerFaceColor', colors(i, :), ... 'MarkerEdgeColor', 'k'); % 添加节点负荷标签 text(ax, node_coords(nodes(j), 1)+0.15, node_coords(nodes(j), 2)-0.15, ... sprintf('%.1f', mpc.bus(nodes(j), 3)), 'FontSize', 8); if j == 1 legend_handles(end+1) = h; legend_labels{end+1} = ['孤岛 ', num2str(i)]; end end end % 标记光储系统 for i = 1:length(dg_nodes) h = plot(ax, node_coords(dg_nodes(i), 1), node_coords(dg_nodes(i), 2), ... 'p', 'MarkerSize', 15, 'MarkerFaceColor', 'y', 'MarkerEdgeColor', 'k'); if i == 1 legend_handles(end+1) = h; legend_labels{end+1} = '光储系统'; end end % 标记故障支路 h = plot(ax, NaN, NaN, 'r--', 'LineWidth', 1.5); legend_handles(end+1) = h; legend_labels{end+1} = '故障支路'; % 添加孤岛信息标注 info_str = sprintf('时段 %d 孤岛划分结果', index); text(ax, min(node_coords(:,1))-1, max(node_coords(:,2))+1, info_str, ... 'FontSize', 12, 'FontWeight', 'bold', 'BackgroundColor', 'w'); % 标题和标签 title(ax, ['IEEE33节点孤岛划分 - 时段 ', num2str(index)]); % 图例 legend(ax, legend_handles, legend_labels, 'Location', 'Best'); hold(ax, 'off');
end
%% 检查点集是否共线
function is_collinear = check_collinear(points)
% 检查点集是否共线(位于同一直线上)
if size(points, 1) < 3
is_collinear = true;
return;
end
% 计算向量叉积 v1 = points(2,:) - points(1,:); for i = 3:size(points, 1) v2 = points(i,:) - points(1,:); cross_product = v1(1)*v2(2) - v1(2)*v2(1); % 2D叉积 if abs(cross_product) > 1e-5 is_collinear = false; return; end end is_collinear = true;
end
%% 计算最小包围矩形
function [rect_x, rect_y] = min_bounding_rect(points)
% 计算点集的最小包围矩形
if size(points, 1) == 1
% 单点情况
rect_x = [points(1,1)-0.5, points(1,1)+0.5, points(1,1)+0.5, points(1,1)-0.5, points(1,1)-0.5];
rect_y = [points(1,2)-0.5, points(1,2)-0.5, points(1,2)+0.5, points(1,2)+0.5, points(1,2)-0.5];
return;
end
% 计算凸包(如果可能) try k = convhull(points(:,1), points(:,2)); hull_points = points(k,:); catch % 如果凸包计算失败(共线点),使用所有点 hull_points = points; end % 计算最小包围矩形 min_x = min(hull_points(:,1)); max_x = max(hull_points(:,1)); min_y = min(hull_points(:,2)); max_y = max(hull_points(:,2)); % 创建矩形坐标 rect_x = [min_x, max_x, max_x, min_x, min_x]; rect_y = [min_y, min_y, max_y, max_y, min_y];
end
%% 从mpc生成邻接矩阵
function A = mpc2adjacency(mpc)
branch = mpc.branch;
n = size(mpc.bus, 1);
A = zeros(n);
for i = 1:size(branch, 1) from = branch(i, 1); to = branch(i, 2); A(from, to) = 1; A(to, from) = 1; % 无向图 end
end
%% 完整IEEE33节点系统数据加载
function mpc = load_case_ieee33()
% IEEE33节点系统完整数据
mpc.version = ‘2’;
mpc.baseMVA = 10;
% 节点数据 [节点编号 类型 有功负荷(kW) 无功负荷(kvar)] mpc.bus = [ 1 3 0.00 0.00; 2 1 100.00 60.00; 3 1 90.00 40.00; 4 1 120.00 80.00; 5 1 60.00 30.00; 6 1 60.00 20.00; 7 1 200.00 100.00; 8 1 200.00 100.00; 9 1 60.00 20.00; 10 1 60.00 20.00; 11 1 45.00 30.00; 12 1 60.00 35.00; 13 1 60.00 35.00; 14 1 120.00 80.00; 15 1 60.00 10.00; 16 1 60.00 20.00; 17 1 60.00 20.00; 18 1 90.00 40.00; 19 1 90.00 40.00; 20 1 90.00 40.00; 21 1 90.00 40.00; 22 1 90.00 40.00; 23 1 90.00 50.00; 24 1 420.00 200.00; 25 1 420.00 200.00; 26 1 60.00 25.00; 27 1 60.00 25.00; 28 1 60.00 20.00; 29 1 120.00 70.00; 30 1 200.00 600.00; 31 1 150.00 70.00; 32 1 210.00 100.00; 33 1 60.00 40.00; ]; % 支路数据 [起始节点 终止节点 电阻(Ω) 电抗(Ω)] mpc.branch = [ 1 2 0.0922 0.0470; 2 3 0.4930 0.2511; 3 4 0.3660 0.1864; 4 5 0.3811 0.1941; 5 6 0.8190 0.7070; 6 7 0.1872 0.6188; 7 8 0.7114 0.2351; 8 9 1.0300 0.7400; 9 10 1.0440 0.7400; 10 11 0.1966 0.0650; 11 12 0.3744 0.1238; 12 13 1.4680 1.1550; 13 14 0.5416 0.7129; 14 15 0.5910 0.5260; 15 16 0.7463 0.5450; 16 17 1.2890 1.7210; 17 18 0.7320 0.5740; 2 19 0.1640 0.1565; 19 20 1.5042 1.3554; 20 21 0.4095 0.4784; 21 22 0.7089 0.9373; 3 23 0.4512 0.3083; 23 24 0.8980 0.7091; 24 25 0.8960 0.7011; 6 26 0.2030 0.1034; 26 27 0.2842 0.1447; 27 28 1.0590 0.9337; 28 29 0.8042 0.7006; 29 30 0.5075 0.2585; 30 31 0.9744 0.9630; 31 32 0.3105 0.3619; 32 33 0.3410 0.5302; ];
end
%% 生成放射状拓扑坐标
function coords = generate_radial_coords(n)
% 生成放射状拓扑坐标
coords = zeros(n, 2);
% 主馈线节点(1-18) for i = 1:18 coords(i, :) = [i-1, 0]; end % 分支1(19-22) coords(19, :) = [1, -1]; coords(20, :) = [2, -1]; coords(21, :) = [3, -1]; coords(22, :) = [4, -1]; % 分支2(23-25) coords(23, :) = [2, 1]; coords(24, :) = [3, 1]; coords(25, :) = [4, 1]; % 分支3(26-33) coords(26, :) = [5, 1]; coords(27, :) = [6, 1]; coords(28, :) = [7, 1]; coords(29, :) = [8, 1]; coords(30, :) = [9, 1]; coords(31, :) = [10, 1]; coords(32, :) = [11, 1]; coords(33, :) = [12, 1];
end
最新发布