def load_scenario_data(self, raw_file, dyr_file): from stepspy import STEPS self.simulator = STEPS(is_default=False, log_file='.\\simulation\\log_op.txt') self.simulator.load_powerflow_data(raw_file, 'PSS/E') self.simulator.load_dynamic_data(dyr_file, 'PSS/E') self.simulator.solve_powerflow('PQ') self.__loads_p = np.zeros(len(self.loads_shedding)) # 该方式下的负荷量 for i in range(len(self.loads_shedding)): self.__loads_p[i] = self.simulator.get_load_data( self.loads_shedding[i], 'F', 'PP0_MW') return
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.main_table = QTabWidget() self.setCentralWidget(self.main_table) self.setWindowTitle('电力系统紧急切负荷智能优化软件') self.setWindowIcon(QIcon('.\\data\\safety.png')) self.main_table.setStyleSheet('background-color: grey') self.main_table.setTabPosition(QTabWidget.South) self.simulator = STEPS(is_default=False, log_file='.\\simulation\\log_init.txt') self.init_window_menu() self.window_output()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.main_table = QTabWidget() self.setCentralWidget(self.main_table) self.setWindowTitle('电力系统紧急切负荷智能优化软件') self.setWindowIcon(QIcon('.\\data\\safety.png')) self.main_table.setStyleSheet('background-color: grey') self.main_table.setTabPosition(QTabWidget.South) self.simulator = STEPS(is_default=False, log_file='.\\simulation\\log_init.txt') self.init_window_menu() self.window_output() def init_window_menu(self): bar = self.menuBar() basic_parameter = bar.addMenu('基础设置') basic_parameter.addAction('电网模型') basic_parameter.addAction('导入切负荷站') basic_parameter.addAction('保存切负荷站') basic_parameter.addAction('导入直流闭锁') basic_parameter.addAction('保存直流闭锁') basic_parameter.addAction('安全约束') basic_parameter.triggered[QAction].connect(self.set_basic_parameter) basic_model_training = bar.addMenu('基础模型训练') basic_model_training.addAction('样本生成') basic_model_training.addAction('模型训练') basic_model_training.triggered[QAction].connect(self.train_basic_model) model_update = bar.addMenu('模型更新') model_update.addAction('样本生成') model_update.addAction('模型微调') model_update.triggered[QAction].connect(self.update_model) optimizer = bar.addMenu('优化计算') optimizer.addAction('单方案优化') optimizer.addAction('多方案优化') optimizer.triggered[QAction].connect(self.start_scenraio_optimizer) setting = bar.addMenu('帮助') setting.addAction('版权信息') setting.addAction('优化计算说明') def window_output(self): items = QDockWidget('输出', self) self.text_output = QTextBrowser() items.setWidget(self.text_output) items.setFloating(False) items.setFeatures(items.NoDockWidgetFeatures) self.addDockWidget(Qt.BottomDockWidgetArea, items) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) def set_basic_parameter(self, q): if q.text() == '电网模型': openfile_name = QFileDialog.getOpenFileName( self, '选择电网模型', '', 'file(*.raw)') if len(openfile_name[0]) == 0: return path_raw_file = openfile_name[0] if len(path_raw_file) == 0: return self.path_raw_file = path_raw_file self.simulator.load_powerflow_data(path_raw_file, 'PSS/E') self.text_output.append('加载电网模型: ' + path_raw_file) self.display_network_data() elif q.text() == '导入切负荷站': try: object.__getattribute__(self, 'scenario_table') except: dialog = QMessageBox(QMessageBox.Warning, '警告', '未导入电网运行文件!!!') dialog.exec_() return openfile_name = QFileDialog.getOpenFileName( self, '导入切负荷站设置', '', 'file(*.csv)') if len(openfile_name[0]) == 0: return path_name = openfile_name[0] if len(path_name) == 0: return self.scenario_table.set_loads_shedding_location(path_name) self.text_output.append('导入切负荷站设置: ' + path_name) elif q.text() == '保存切负荷站': try: object.__getattribute__(self, 'scenario_table') except: dialog = QMessageBox(QMessageBox.Warning, '警告', '未导入电网运行文件!!!') dialog.exec_() return self.scenario_table.save_loads_shedding_location( '.\\data\\loads_shedding.csv') self.text_output.append('保存切负荷站设置: ' + '.\\data\\loads_shedding.csv') return elif q.text() == '导入直流闭锁': try: object.__getattribute__(self, 'scenario_table') except: dialog = QMessageBox(QMessageBox.Warning, '警告', '未导入电网运行文件!!!') dialog.exec_() return openfile_name = QFileDialog.getOpenFileName( self, '导入直流闭锁设置', '', 'file(*.csv)') if len(openfile_name[0]) == 0: return path_name = openfile_name[0] if len(path_name) == 0: return self.scenario_table.set_block_hvdc_location(path_name) self.text_output.append('导入闭锁直流设置: ' + path_name) elif q.text() == '保存直流闭锁': try: object.__getattribute__(self, 'scenario_table') except: dialog = QMessageBox(QMessageBox.Warning, '警告', '未导入电网运行文件!!!') dialog.exec_() return self.scenario_table.save_hvdc_blocking_location( '.\\data\\hvdc_block.csv') self.text_output.append('保存闭锁直流设置: ' + '.\\data\\hvdc_block.csv') elif q.text() == '安全约束': try: object.__getattribute__(self, 'scenario_table') except: dialog = QMessageBox(QMessageBox.Warning, '警告', '未导入电网运行文件!!!') dialog.exec_() return dialog = SecurityConstraint(self.text_output) dialog.exec_() else: pass return def train_basic_model(self, q): if q.text() == '样本生成': dialog = UI_SGBM() dialog.exec_() elif q.text() == '模型训练': dialog = UI_DBNBM() dialog.exec_() else: return def update_model(self, q): if q.text() == '样本生成': dialog = UI_SGTL() dialog.exec_() elif q.text() == '模型微调': dialog = UI_DBNTL() dialog.exec_() else: return def start_scenraio_optimizer(self, q): if q.text() == '单方案优化': self.text_output.append('启动单方案优化程序') dialog = UI_AAMO() dialog.exec_() elif q.text() == '多方案优化': self.text_output.append('启动多方案优化程序') dialog = UI_AAMOTL() dialog.exec_() else: return def display_network_data(self): self.main_table.setStyleSheet('background-color: white') self.scenario_table = Table_Show(self.main_table, self.simulator, self.text_output) self.scenario_table.display_bus_table() self.scenario_table.display_generator_table() self.scenario_table.display_load_table() self.scenario_table.display_hvdc_table()
# this case in section 2.10 of Power System Control and Stability by P.M. Anderson # April 1, 2021 # Changgang Li from stepspy import STEPS # import modules simulator = STEPS( is_default=True, log_file="ieee9_pf.log" ) # create simulator, use default simulator, and redirect logs to file ieee9.log simulator.set_allowed_maximum_bus_number( 10000 ) # set allowed maximum bus number, no bus with bus number greater than this number is allowed simulator.load_powerflow_data('../ieee9.raw', 'PSS/E') # load powerflow data simulator.set_powerflow_solver_parameter('b', 'FLAT START Logic', True) # enable flat start logic simulator.set_powerflow_solver_parameter( 'b', 'NON DIVERGENT SOLUTION LOGIC', False) # enable non-divergent solution simulator.set_powerflow_solver_parameter( 'd', 'MAX ACTIVE POWER IMBALANCE IN MW', 0.001) # maximum active power mismatch simulator.set_powerflow_solver_parameter( 'd', 'MAX REACTIVE POWER IMBALANCE IN MVAR', 0.001) # maximum reactive power mismatch simulator.solve_powerflow('NR') # solve with Newton-Raphson method simulator.save_extended_powerflow_result( "ieee9_pf.csv") # show powerflow result
# this case in section 2.10 of Power System Control and Stability by P.M. Anderson # April 1, 2021 # Changgang Li from stepspy import STEPS # import modules simulator = STEPS(is_default=True, log_file="ieee9.log") # create simulator, use default simulator, and redirect logs to file ieee9.log simulator.set_allowed_maximum_bus_number(10000) # set allowed maximum bus number, no bus with bus number greater than this number is allowed simulator.load_powerflow_data('../IEEE9.raw','PSS/E') # load powerflow data simulator.set_powerflow_solver_parameter('b','FLAT START Logic', True) # enable flat start logic simulator.set_powerflow_solver_parameter('i','MAX ITERATION', 50) # set up maximum iteration simulator.set_powerflow_solver_parameter('b','EXPORT JACOBIAN LOGIC', False) # disable exporting Jacobian matrix simulator.set_powerflow_solver_parameter('b','NON DIVERGENT SOLUTION LOGIC', True) # enable non-divergent solution simulator.set_powerflow_solver_parameter('d','MAX VOLTAGE CHANGE IN PU', 0.3) # set up maximum voltage change in each iteration simulator.set_powerflow_solver_parameter('d','MAX ANGLE CHANGE IN DEG', 60.0) # set up maximum angle change in each iteration simulator.set_powerflow_solver_parameter('d','MAX ACTIVE POWER IMBALANCE IN MW', 0.001) # maximum active power mismatch simulator.set_powerflow_solver_parameter('d','MAX REACTIVE POWER IMBALANCE IN MVAR', 0.001) # maximum reactive power mismatch simulator.solve_powerflow('NR') # solve with Newton-Raphson method simulator.show_powerflow_result() # show powerflow result simulator.save_network_Y_matrix("y.csv",export_full=True) # export Y matrix, both sparse and full version simulator.set_dynamic_model_database_capacity(1000000) # set dynamic model database capacity, in bytes simulator.load_dynamic_data('../IEEE9_PM.dyr','PSS/E') # load dynamic data buses = simulator.get_all_buses() # get all buses gens = simulator.get_all_generators() # get all generators for bus in buses: # prepare bus voltage and frequency meter for all buses simulator.prepare_bus_meter(bus, "voltage in pu") simulator.prepare_bus_meter(bus, "frequency in Hz") for gen in gens: # prepare rotor angle meter for all generators
from stepspy import STEPS, POUCH_CSV simulator = STEPS(is_default=False, log_file='test.log') simulator.info() simulator.set_toolkit_log_file("newtest.log", log_file_append_mode=False) simulator.set_parallel_thread_number(1) simulator.set_dynamic_model_database_capacity(10000000) max_bus = simulator.get_allowed_maximum_bus_number() info = "The default maximum bus number is: " + str(max_bus) print(info) simulator.set_allowed_maximum_bus_number(10000) max_bus = simulator.get_allowed_maximum_bus_number() info = "The default maximum bus number is changed to: " + str(max_bus) print(info) simulator.load_powerflow_data('IEEE39.raw', 'PSS/E') simulator.check_powerflow_data() simulator.check_network_connectivity() simulator.build_dynamic_network_Y_matrix() simulator.save_dynamic_network_Y_matrix('ymatrix_dyn.csv') simulator.build_network_Z_matrix() simulator.save_network_Z_matrix('zmatrix_dyn.csv') nbus = simulator.get_bus_count() print(nbus)
#coding = utf-8 ''' Here is a demo of showing how to slove powerflow with stepspy. Changgang Li, 2019/08/25 ''' from stepspy import STEPS # import the class 'STEPS' simulator = STEPS(is_default=True) # create a STEPS simulator instance simulator.info() powerflow_data_file = 'IEEE9.raw' # file name of powerflow data. Use absolute path if necessary powerflow_data_type = 'PSS/E' # powerflow data type. Currently, use 'PSS/E' only simulator.load_powerflow_data( powerflow_data_file, powerflow_data_type) # load powerflow data into the simulator data_type = 'D' # if you want to set or get doubule data, set data_type as 'F' or 'D'. data_name = 'MAX ACTIVE POWER IMBALANCE IN MW' # the data name in the powerflow solver of the simulator # the data_type and data_name should be consistent. make sure the data_type is correct. # If the data is double, use 'F' or 'D'. If the data is integer, use 'I'. If the data is boolean, use 'B'. If the data is string, use 'S' ''' (1) when data_type is 'D' or 'F' you can set/get the following data 'MAX ACTIVE POWER IMBALANCE IN MW': maximum allowed active power mismatch at each bus, in MW. This is the powerflow convergence threshold of P equations. 'MAX REACTIVE POWER IMBALANCE IN MVAR': maximum allowed reactive power mismatch at each bus, in MVar. This is the powerflow convergence threshold of Q equations. 'ITERATION ACCELERATOR': acceleration factor for iteration. by default it is 1.0. if >1.0, then the powerflow solver is accelerated. if <1.0, the powerflow solver is decellerated. (2) when data_type is 'I', you can set/get the following data 'MAX ITERATION': maximum iteration count allowed for solving powerflow. If set as 1, you can get the solution step by step.
def generate_load_shedding_sample(self, simulation_pars): from stepspy import STEPS sample_num = simulation_pars['sample_num'] shedding_percent = simulation_pars['shedding_percent'] simulator = STEPS( is_default=False, log_file='.\simulation\log_{}.txt'.format(sample_num)) simulator.load_powerflow_data(self.raw_file, 'PSS/E') simulator.load_dynamic_data(self.dyr_file, 'PSS/E') simulator.solve_powerflow('PQ') buses = simulator.get_all_buses() for bus in buses: AREA = simulator.get_bus_data(bus, 'I', 'AREA') if AREA == 37: simulator.prepare_bus_meter(bus, 'FREQUENCY IN HZ') simulator.set_dynamic_simulation_time_step(0.002) simulator.set_dynamic_simulator_output_file( '.\\simulation\\sample_{}'.format(sample_num)) simulator.start_dynamic_simulation() simulator.run_dynamic_simulation_to_time(0.5) for hvdc in self.hvdc_block: simulator.manually_block_hvdc(hvdc) simulator.trip_fixed_shunt((hvdc[1], '1')) simulator.run_dynamic_simulation_to_time(0.6) for i in range(len(self.loads_shedding)): simulator.scale_load(self.loads_shedding[i], -1 * shedding_percent[i]) simulator.run_dynamic_simulation_to_time(5.0) simulator.stop_dynamic_simulation() min_frequency = self.get_min_frequency( '.\\simulation\\sample_{}.csv'.format(sample_num)) if min_frequency > self.min_frequency: return [sample_num, min_frequency, 1] else: return [sample_num, min_frequency, 0]
from stepspy import STEPS # import modules from stepspy import POUCH_CSV # import modules import matplotlib.pyplot as plt simulator = STEPS( is_default=True, log_file="ieee9.log" ) # create simulator, use default simulator, and redirect logs to file ieee9.log simulator.set_allowed_maximum_bus_number( 10000 ) # set allowed maximum bus number, no bus with bus number greater than this number is allowed simulator.load_powerflow_data('../IEEE9.raw', 'PSS/E') # load powerflow data simulator.solve_powerflow('NR') # solve with Newton-Raphson method simulator.show_powerflow_result() # show powerflow result simulator.set_dynamic_model_database_capacity( 1000000) # set dynamic model database capacity, in bytes simulator.load_dynamic_data('../IEEE9_detail.dyr', 'PSS/E') # load dynamic data buses = simulator.get_all_buses() # get all buses gens = simulator.get_all_generators() # get all generators for bus in buses: # prepare bus voltage meter for all buses simulator.prepare_bus_meter(bus, "voltage in pu") for bus in buses: # prepare bus frequency meter for all buses simulator.prepare_bus_meter(bus, "frequency in Hz") for gen in gens: # prepare rotor angle meter for all generators simulator.prepare_generator_meter(gen, "rotor angle in deg") for gen in gens: # prepare rotor speed deviation meter for all generators simulator.prepare_generator_meter(gen, "rotor speed deviation in pu")
class ADELSMTL(): # 代理辅助模型驱动的差分进化切负荷模型 def __init__(self, size=50, iter_num=200, F=0.8, CR=0.4): self.__size = size self.__iter_num = iter_num self.__F = F self.__CR = CR # 以下为加载代理辅助模型,目前只有频率模型 def load_frequency_classification_prediction_model(self, file): K.clear_session() self.frequency_classification_model = load_model(file) # 以下为加载运行场景 def load_scenario_data(self, raw_file, dyr_file): from stepspy import STEPS self.simulator = STEPS(is_default=False, log_file='.\simulation\log.txt') self.simulator.load_powerflow_data(raw_file, 'PSS/E') self.simulator.load_dynamic_data(dyr_file, 'PSS/E') self.simulator.solve_powerflow('PQ') self.__dim = len(self.loads_shedding) # 个体特征维数 self.__loads_p = np.zeros(len(self.loads_shedding)) # 该方式下的负荷量 for i in range(len(self.loads_shedding)): self.__loads_p[i] = self.simulator.get_load_data( self.loads_shedding[i], 'F', 'PP0_MW') def set_load_shedding_location(self, path_name): data = pd.read_csv(path_name, header=0, engine='python') loads_shedding = data['负荷'].values.tolist() for i in range(len(loads_shedding)): loads_shedding[i] = eval(loads_shedding[i]) self.max_percent = data['最大切除比例'].values.tolist() self.loads_shedding = loads_shedding self.__dim = len(self.loads_shedding) # 个体特征维数 self.x_min = np.zeros(self.__dim) self.x_max = np.array(self.max_percent) #以下为种群初始化 def initialize_population(self): self.population = np.zeros((self.__size, self.__dim)) for i in range(self.__dim): for j in range(self.__size): # 初始种群在限度范围内随机初始化 self.population[j, i] = random.uniform(self.x_min[i], self.x_max[i]) self.population_fitness = np.zeros(self.__size) for i in range(self.__size): self.population_fitness[i] = self.get_individual_fitness( self.population[i, :]) def correct_F(self, current): lanba = math.exp(1 - self.__iter_num / (self.__iter_num + 1 - current)) F = 1.0 * 2**lanba return F def correct_CR(self): CR = 0.5 * (1 + random.random()) return CR # 以下为进化过程 def operate_evolution(self): '''实施进化计算''' k = 0 while True: F = self.correct_F(k) mutation_population = self.operate_population_mutation(F) process_population = self.operate_population_crossover( mutation_population) self.operate_selection(process_population) for j in range(self.__size): self.population_fitness[j] = self.get_individual_fitness( self.population[j, :]) mean_fitness = np.mean(self.population_fitness) max_fitness = np.max(self.population_fitness) min_fitness = np.min(self.population_fitness) min_fit_index = np.argmin(self.population_fitness) best_ind = self.population[min_fit_index, :] k = k + 1 if k > self.__iter_num: break for i in range(self.__size): self.population_fitness[i] = self.get_individual_fitness( self.population[i, :]) min_index = np.argmin(self.population_fitness) self.best_individual = self.population[min_index, :] return def operate_population_mutation(self, F): '''对种群实施变异''' self.__F = F mutation_population = np.zeros((self.__size, self.__dim)) for i in range(self.__size): list_num = list(range(0, self.__size, 1)) list_num.remove(i) res = random.sample(list_num, 3) mutation_individual = self.population[res[0], :] + self.__F * ( self.population[res[1], :] - self.population[res[2], :] ) # 变异操作,产生新个体 for j in range(self.__dim): # 特征越限处理 if mutation_individual[j] < self.x_min[ j] or mutation_individual[j] > self.x_max[j]: mutation_individual = self.x_min + random.random() * ( self.x_max - self.x_min) break mutation_population[i, :] = mutation_individual return mutation_population def operate_population_crossover(self, mutation_population): '''进行交叉操作''' self.__CR = self.correct_CR() process_population = np.zeros((self.__size, self.__dim)) for i in range(self.__size): randn = random.randint(0, self.__dim) for j in range(self.__dim): rand_float = random.random() if rand_float <= self.__CR or randn == j: process_population[i, j] = mutation_population[i, j] else: process_population[i, j] = self.population[i, j] return process_population def operate_selection(self, process_population): '''对个体进行选择和更新''' for i in range(self.__size): ind_1 = self.population[i, :] ind_2 = process_population[i, :] better_ind = self.select_individual_cla(ind_1, ind_2) self.population[i, :] = better_ind return def select_individual_cla(self, ind_1, ind_2): ind_1_cla = self.frequency_classification_model.predict_classes( 5 * ind_1.reshape((1, -1))) ind_1_cla = ind_1_cla[0, 0] ind_2_cla = self.frequency_classification_model.predict_classes( 5 * ind_2.reshape((1, -1))) ind_2_cla = ind_2_cla[0, 0] if ind_1_cla == 1 and ind_2_cla == 1: fit_1 = self.get_individual_fitness(ind_1) fit_2 = self.get_individual_fitness(ind_2) if fit_1 > fit_2: better_ind = ind_2 else: better_ind = ind_1 elif ind_1_cla == 0 and ind_2_cla == 1: better_ind = ind_2 elif ind_1_cla == 0 and ind_2_cla == 0: better_ind = np.zeros(self.__dim) for i in range(self.__dim): better_ind[i] = random.uniform(self.x_min[i], self.x_max[i]) else: better_ind = ind_1 return better_ind # 以下为个体适应度计算函数 def get_individual_fitness(self, individual): # individual应该是个一维数组 value = np.sum(individual * self.__loads_p) # 切负荷总量 return value def get_best_individual(self): min_shedding_power = self.get_individual_fitness(self.best_individual) return self.best_individual, min_shedding_power
class ADELSM(): # 代理辅助模型驱动的差分进化切负荷模型 def __init__(self, size=100, iter_num=200): self.__size = size self.__iter_num = iter_num self.__F = 0.8 self.__CR = 0.4 self.__process = [] def set_load_shedding_location(self, path_name): data = pd.read_csv(path_name, header=0, engine='python') loads_shedding = data['负荷'].values.tolist() for i in range(len(loads_shedding)): loads_shedding[i] = eval(loads_shedding[i]) self.max_percent = data['最大切除比例'].values.tolist() self.loads_shedding = loads_shedding self.__dim = len(self.loads_shedding) # 个体特征维数 self.x_min = np.zeros(self.__dim) self.x_max = np.array(self.max_percent) def set_blocking_hvdc_location(self, path_name): data = pd.read_csv(path_name, header=0, engine='python') data = data['直流'].values.tolist() for i in range(len(data)): data[i] = eval(data[i]) self.hvdc_block = data # 以下为加载代理辅助模型,目前只有频率模型 def load_frequency_classification_prediction_model(self, file): K.clear_session() self.frequency_classification_model = load_model(file) # 以下为加载运行场景 def load_scenario_data(self, raw_file, dyr_file): from stepspy import STEPS self.simulator = STEPS(is_default=False, log_file='.\\simulation\\log_op.txt') self.simulator.load_powerflow_data(raw_file, 'PSS/E') self.simulator.load_dynamic_data(dyr_file, 'PSS/E') self.simulator.solve_powerflow('PQ') self.__loads_p = np.zeros(len(self.loads_shedding)) # 该方式下的负荷量 for i in range(len(self.loads_shedding)): self.__loads_p[i] = self.simulator.get_load_data( self.loads_shedding[i], 'F', 'PP0_MW') return # 以下为设置差分进化算法的参数 def set_evolution_parameter(self, par_name, value): if par_name == '交叉因子': self.__CR = value elif par_name == '变异因子': self.__F = value else: pass #以下为种群初始化 def initialize_population(self): self.population = np.zeros((self.__size, self.__dim)) for i in range(self.__dim): for j in range(self.__size): # 初始种群在限度范围内随机初始化 self.population[j, i] = random.uniform(self.x_min[i], self.x_max[i]) self.population_fitness = np.zeros(self.__size) for i in range(self.__size): self.population_fitness[i] = self.get_individual_fitness( self.population[i, :]) # 以下为进化过程 def operate_evolution(self): '''实施进化计算''' k = 0 while True: mutation_population = self.operate_population_mutation() process_population = self.operate_population_crossover( mutation_population) self.operate_selection(process_population) for j in range(self.__size): self.population_fitness[j] = self.get_individual_fitness( self.population[j, :]) mean_fitness = np.mean(self.population_fitness) max_fitness = np.max(self.population_fitness) min_fitness = np.min(self.population_fitness) self.process_output.append('第{}代-平均值{}-最大值{}-最小值{}'.format( k, int(mean_fitness), int(max_fitness), int(min_fitness))) self.process_output.verticalScrollBar().setValue( self.process_output.verticalScrollBar().maximum()) QApplication.processEvents() k = k + 1 if k > self.__iter_num: break for i in range(self.__size): self.population_fitness[i] = self.get_individual_fitness( self.population[i, :]) return def operate_evolution_one_enpouch(self): mutation_population = self.operate_population_mutation() process_population = self.operate_population_crossover( mutation_population) self.operate_selection(process_population) for j in range(self.__size): self.population_fitness[j] = self.get_individual_fitness( self.population[j, :]) mean_fitness = np.mean(self.population_fitness) max_fitness = np.max(self.population_fitness) min_fitness = np.min(self.population_fitness) return int(mean_fitness), int(max_fitness), int(min_fitness) def operate_population_mutation(self): '''对种群实施变异''' mutation_population = np.zeros((self.__size, self.__dim)) for i in range(self.__size): list_num = list(range(0, self.__size, 1)) list_num.remove(i) res = random.sample(list_num, 3) mutation_individual = self.population[res[0], :] + self.__F * ( self.population[res[1], :] - self.population[res[2], :] ) # 变异操作,产生新个体 for j in range(self.__dim): # 特征越限处理 if mutation_individual[j] < self.x_min[ j] or mutation_individual[j] > self.x_max[j]: mutation_individual = self.x_min + random.random() * ( self.x_max - self.x_min) break mutation_population[i, :] = mutation_individual return mutation_population def operate_population_crossover(self, mutation_population): '''进行交叉操作''' process_population = np.zeros((self.__size, self.__dim)) for i in range(self.__size): randn = random.randint(0, self.__dim) for j in range(self.__dim): rand_float = random.random() if rand_float <= self.__CR or randn == j: process_population[i, j] = mutation_population[i, j] else: process_population[i, j] = self.population[i, j] return process_population def operate_selection(self, process_population): '''对个体进行选择和更新''' for i in range(self.__size): ind_1 = self.population[i, :] ind_2 = process_population[i, :] better_ind = self.select_individual_cla(ind_1, ind_2) self.population[i, :] = better_ind return def select_individual_cla(self, ind_1, ind_2): ind_1_cla = self.frequency_classification_model.predict_classes( 5 * ind_1.reshape((1, -1))) ind_1_cla = ind_1_cla[0, 0] ind_2_cla = self.frequency_classification_model.predict_classes( 5 * ind_2.reshape((1, -1))) ind_2_cla = ind_2_cla[0, 0] if ind_1_cla == 1 and ind_2_cla == 1: fit_1 = self.get_individual_fitness(ind_1) fit_2 = self.get_individual_fitness(ind_2) if fit_1 > fit_2: better_ind = ind_2 else: better_ind = ind_1 elif ind_1_cla == 0 and ind_2_cla == 1: better_ind = ind_2 elif ind_1_cla == 0 and ind_2_cla == 0: better_ind = np.zeros(self.__dim) for i in range(self.__dim): better_ind[i] = random.uniform(self.x_min[i], self.x_max[i]) else: better_ind = ind_1 return better_ind # 以下为个体适应度计算函数 def get_individual_fitness(self, individual): # individual应该是个一维数组 value = np.sum(individual * self.__loads_p) # 切负荷总量 return value def save_best_individual(self, file): min_index = np.argmin(self.population_fitness) best_individual = self.population[min_index, :] with open(file, 'w', newline='') as f: csv_write = csv.writer(f) csv_write.writerow(self.loads_shedding) csv_write.writerow(best_individual) loads_name = [] for load in self.loads_shedding: NAME = self.simulator.get_bus_data(load[0], 'S', 'NAME') loads_name.append(NAME) return best_individual, self.__loads_p, self.loads_shedding, loads_name def check_evolution_result(self, best_individual): buses = self.simulator.get_all_buses() for bus in buses: AREA = self.simulator.get_bus_data(bus, 'I', 'AREA') if AREA == 37: self.simulator.prepare_bus_meter(bus, 'FREQUENCY IN HZ') self.simulator.set_dynamic_simulation_time_step(0.002) self.simulator.set_dynamic_simulator_output_file( '.\\simulation\\代理辅助模型校验结果') self.simulator.start_dynamic_simulation() self.simulator.run_dynamic_simulation_to_time(0.5) for hvdc in self.hvdc_block: self.simulator.manually_block_hvdc(hvdc) self.simulator.trip_fixed_shunt((hvdc[1], '1')) self.simulator.run_dynamic_simulation_to_time(0.6) for i in range(len(self.loads_shedding)): self.simulator.scale_load(self.loads_shedding[i], -1 * best_individual[i]) self.simulator.run_dynamic_simulation_to_time(5.0) self.simulator.stop_dynamic_simulation() sample_data = pd.read_csv('.\\simulation\\代理辅助模型校验结果.csv', header=0, engine='python') columns = list(sample_data) frequency_column = [] for column in columns: if 'FREQUENCY' in column: frequency_column.append(column) else: pass frequency_data = sample_data.loc[:, frequency_column] min_frequency = np.min(frequency_data.values) return min_frequency