Source code for ddmtolab.Problems.RWO.pepvm

import numpy as np
from ddmtolab.Methods.mtop import MTOP


[docs] class PEPVM: """ Parameter Extraction of Photovoltaic Models (PEPVM) benchmark problem. This problem consists of three single-objective optimization tasks for parameter extraction of different photovoltaic cell models using experimental I-V data. - Task 1: Single Diode Model (5 parameters) - Task 2: Double Diode Model (7 parameters) - Task 3: PV Module Model (5 parameters) The tasks share similar parameter extraction objectives but differ in model complexity and experimental conditions. References ---------- [1] Li, S., Gu, Q., Gong, W., & Ning, B. (2020). An Enhanced Adaptive Differential Evolution Algorithm for Parameter Extraction of Photovoltaic Models. Energy Conversion and Management, 205, 112443. [2] Li, Y., Gong, W., & Li, S. (2022). Multitasking Optimization via an Adaptive Solver Multitasking Evolutionary Framework. Information Sciences. [3] Li, Y., Gong, W., & Li, S. (2023). Evolutionary Competitive Multitasking Optimization via Improved Adaptive Differential Evolution. Expert Systems with Applications, 119550. Attributes ---------- None required for this benchmark. """ problem_information = { 'n_cases': 1, 'n_tasks': '3', 'n_dims': '[5, 7]', 'n_objs': '1', 'n_cons': '0', 'type': 'real_world', } def __init__(self): pass
[docs] def P1(self) -> MTOP: """ Generates PEPVM Problem: Three photovoltaic parameter extraction tasks. - Task 1: Single Diode Model (5-D, experimental data at 33°C) - Task 2: Double Diode Model (7-D, experimental data at 33°C) - Task 3: PV Module Model (5-D, experimental data at 45°C) All tasks minimize RMSE between measured and modeled I-V characteristics. Returns ------- MTOP A Multi-Task Optimization Problem instance with 3 tasks. """ # Physical constants q = 1.60217646e-19 # Elementary charge (C) k = 1.3806503e-23 # Boltzmann constant (J/K) # Task 1: Single Diode Model def T1(x): """ Single Diode Model at T=33°C Parameters: [I_ph, I_sd, R_s, R_sh, a] Returns: RMSE (shape: (N, 1)) """ x = np.atleast_2d(x) n = x.shape[0] T = 273.15 + 33.0 V_t = k * T / q I_ph = x[:, 0:1] I_sd = x[:, 1:2] R_s = x[:, 2:3] R_sh = x[:, 3:4] a = x[:, 4:5] # 防止除零和过小值 a = np.maximum(a, 1e-10) R_sh = np.maximum(R_sh, 1e-10) I_sd = np.maximum(I_sd, 1e-50) # Experimental I-V data V_L = np.array([-0.2057, -0.1291, -0.0588, 0.0057, 0.0646, 0.1185, 0.1678, 0.2132, 0.2545, 0.2924, 0.3269, 0.3585, 0.3873, 0.4137, 0.4373, 0.4590, 0.4784, 0.4960, 0.5119, 0.5265, 0.5398, 0.5521, 0.5633, 0.5736, 0.5833, 0.5900]) I_L = np.array([0.7640, 0.7620, 0.7605, 0.7605, 0.7600, 0.7590, 0.7570, 0.7570, 0.7555, 0.7540, 0.7505, 0.7465, 0.7385, 0.7280, 0.7065, 0.6755, 0.6320, 0.5730, 0.4990, 0.4130, 0.3165, 0.2120, 0.1035, -0.0100, -0.1230, -0.2100]) # Calculate RMSE for each solution summ = np.zeros((n, 1)) for i in range(len(V_L)): exp_arg = (V_L[i] + I_L[i] * R_s) / (a * V_t) exp_arg = np.clip(exp_arg, -700, 700) exp_term = np.exp(exp_arg) - 1 # 限制exp_term避免后续计算溢出 exp_term = np.clip(exp_term, -1e10, 1e10) y1 = (I_ph - I_sd * exp_term - (V_L[i] + I_L[i] * R_s) / R_sh - I_L[i]) # 限制y1的范围避免平方时溢出 y1 = np.clip(y1, -1e10, 1e10) summ += y1 ** 2 obj = np.sqrt(summ / len(V_L)) return obj # Task 2: Double Diode Model def T2(x): """ Double Diode Model at T=33°C Parameters: [I_ph, I_sd1, R_s, R_sh, a1, I_sd2, a2] Returns: RMSE (shape: (N, 1)) """ x = np.atleast_2d(x) n = x.shape[0] T = 273.15 + 33.0 V_t = k * T / q I_ph = x[:, 0:1] I_sd1 = x[:, 1:2] R_s = x[:, 2:3] R_sh = x[:, 3:4] a1 = x[:, 4:5] I_sd2 = x[:, 5:6] a2 = x[:, 6:7] # 防止除零和过小值 a1 = np.maximum(a1, 1e-10) a2 = np.maximum(a2, 1e-10) R_sh = np.maximum(R_sh, 1e-10) I_sd1 = np.maximum(I_sd1, 1e-50) I_sd2 = np.maximum(I_sd2, 1e-50) # Experimental I-V data V_L = np.array([-0.2057, -0.1291, -0.0588, 0.0057, 0.0646, 0.1185, 0.1678, 0.2132, 0.2545, 0.2924, 0.3269, 0.3585, 0.3873, 0.4137, 0.4373, 0.4590, 0.4784, 0.4960, 0.5119, 0.5265, 0.5398, 0.5521, 0.5633, 0.5736, 0.5833, 0.5900]) I_L = np.array([0.7640, 0.7620, 0.7605, 0.7605, 0.7600, 0.7590, 0.7570, 0.7570, 0.7555, 0.7540, 0.7505, 0.7465, 0.7385, 0.7280, 0.7065, 0.6755, 0.6320, 0.5730, 0.4990, 0.4130, 0.3165, 0.2120, 0.1035, -0.0100, -0.1230, -0.2100]) # Calculate RMSE for each solution summ = np.zeros((n, 1)) for i in range(len(V_L)): exp_arg1 = (V_L[i] + I_L[i] * R_s) / (a1 * V_t) exp_arg2 = (V_L[i] + I_L[i] * R_s) / (a2 * V_t) exp_arg1 = np.clip(exp_arg1, -700, 700) exp_arg2 = np.clip(exp_arg2, -700, 700) exp_term1 = np.exp(exp_arg1) - 1 exp_term2 = np.exp(exp_arg2) - 1 # 限制exp_term避免后续计算溢出 exp_term1 = np.clip(exp_term1, -1e10, 1e10) exp_term2 = np.clip(exp_term2, -1e10, 1e10) y1 = (I_ph - I_sd1 * exp_term1 - I_sd2 * exp_term2 - (V_L[i] + I_L[i] * R_s) / R_sh - I_L[i]) # 限制y1的范围避免平方时溢出 y1 = np.clip(y1, -1e10, 1e10) summ += y1 ** 2 obj = np.sqrt(summ / len(V_L)) return obj # Task 3: PV Module Model def T3(x): """ PV Module Model at T=45°C Parameters: [I_ph, I_sd, R_s, R_sh, a] Returns: RMSE (shape: (N, 1)) """ x = np.atleast_2d(x) n = x.shape[0] T = 273.15 + 45.0 V_t = k * T / q I_ph = x[:, 0:1] I_sd = x[:, 1:2] R_s = x[:, 2:3] R_sh = x[:, 3:4] a = x[:, 4:5] Ns = 1 # 防止除零和过小值 a = np.maximum(a, 1e-10) R_sh = np.maximum(R_sh, 1e-10) I_sd = np.maximum(I_sd, 1e-50) # Experimental I-V data V_L = np.array([0.1248, 1.8093, 3.3511, 4.7622, 6.0538, 7.2364, 8.3189, 9.3097, 10.2163, 11.0449, 11.8018, 12.4929, 13.1231, 13.6983, 14.2221, 14.6995, 15.1346, 15.5311, 15.8929, 16.2229, 16.5241, 16.7987, 17.0499, 17.2793, 17.4885]) I_L = np.array([1.0315, 1.0300, 1.0260, 1.0220, 1.0180, 1.0155, 1.0140, 1.0100, 1.0035, 0.9880, 0.9630, 0.9255, 0.8725, 0.8075, 0.7265, 0.6345, 0.5345, 0.4275, 0.3185, 0.2085, 0.1010, -0.0080, -0.1110, -0.2090, -0.3030]) # Calculate RMSE for each solution summ = np.zeros((n, 1)) for i in range(len(V_L)): exp_arg = (V_L[i] + I_L[i] * R_s) / (a * Ns * V_t) exp_arg = np.clip(exp_arg, -700, 700) exp_term = np.exp(exp_arg) - 1 # 限制exp_term避免后续计算溢出 exp_term = np.clip(exp_term, -1e10, 1e10) y1 = (I_ph - I_sd * exp_term - (V_L[i] + I_L[i] * R_s) / R_sh - I_L[i]) # 限制y1的范围避免平方时溢出 y1 = np.clip(y1, -1e10, 1e10) summ += y1 ** 2 obj = np.sqrt(summ / len(V_L)) return obj # Define bounds for each task # Task 1: [I_ph, I_sd, R_s, R_sh, a] lb1 = np.array([0.0, 0.0, 0.0, 0.0, 1.0]) ub1 = np.array([1.0, 1e-6, 0.5, 100.0, 2.0]) # Task 2: [I_ph, I_sd1, R_s, R_sh, a1, I_sd2, a2] lb2 = np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0]) ub2 = np.array([1.0, 1e-6, 0.5, 100.0, 2.0, 1e-6, 2.0]) # Task 3: [I_ph, I_sd, R_s, R_sh, a] lb3 = np.array([0.0, 0.0, 0.0, 0.0, 1.0]) ub3 = np.array([2.0, 5e-5, 2.0, 2000.0, 50.0]) # Create MTOP instance problem = MTOP() problem.add_task(T1, dim=5, lower_bound=lb1, upper_bound=ub1) problem.add_task(T2, dim=7, lower_bound=lb2, upper_bound=ub2) problem.add_task(T3, dim=5, lower_bound=lb3, upper_bound=ub3) return problem