├── README.md ├── config.data ├── minganxing.py ├── shiyan1.py ├── shiyan2~4.py └── social3.py /README.md: -------------------------------------------------------------------------------- 1 | # A-Social-Relationship-Awareness-Based-Dependent-Task-Offloading-Algorithm-for-Mobile-Edge-Computing 2 | This study proposes a novel task offloading algorithm that comprehensively considers various 3 | factors including a symmetric social relationships among users, task dependencies, 4 | energy consumption, and latency. Specifically, this paper introduces the social affinity 5 | between devices and task categories as a supplement to the traditional objective functions 6 | (focused on energy consumption and latency) to optimize the task offloading process. 7 | The article extensively discusses task offloading decisions under four modes (local execution, 8 | Device-to-Device (D2D) execution, edge execution, and D2D-edge mixed execution), 9 | providing comprehensive analysis and modeling in terms of energy consumption, 10 | latency, social affinity, and task dependencies for each mode. The Hungarian algorithm 11 | is utilized for global optimization to enhance the overall performance of the system. The 12 | effectiveness of the proposed algorithm is validated through experiments, and the specific 13 | impact of task data size on offloading strategies in different scenarios is analyzed, 14 | including personal mobile devices, Internet of Things (IoT) environments, data centers, 15 | and intelligent vehicles. 16 | -------------------------------------------------------------------------------- /config.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charyco/A-Social-Relationship-Awareness-Based-Dependent-Task-Offloading-Algorithm-for-Mobile-Edge-Computing/b6e9ba9066278a82f6be0d1a0220c4e517875425/config.data -------------------------------------------------------------------------------- /minganxing.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import matplotlib.pyplot as plt 3 | from scipy.optimize import linear_sum_assignment 4 | 5 | 6 | class Task: 7 | def __init__(self, task_id, computation_cost, data_size, social_group, dependencies=[], result_size=0): 8 | self.task_id = task_id 9 | self.computation_cost = computation_cost 10 | self.data_size = data_size 11 | self.social_group = social_group 12 | self.dependencies = dependencies 13 | self.result_size = result_size 14 | self.is_completed = False 15 | self.device_id = None 16 | 17 | class Device: 18 | def __init__(self, device_id, capacity, transmission_power, social_group, 19 | d2d_transmit_power, d2d_receive_power, cellular_transmit_power, 20 | cellular_receive_power, upload_bandwidth, download_bandwidth, d2d_bandwidth): 21 | self.device_id = device_id 22 | self.capacity = capacity 23 | self.transmission_power = transmission_power 24 | self.social_group = social_group 25 | self.d2d_transmit_power = d2d_transmit_power 26 | self.d2d_receive_power = d2d_receive_power 27 | self.cellular_transmit_power = cellular_transmit_power 28 | self.cellular_receive_power = cellular_receive_power 29 | self.upload_bandwidth = upload_bandwidth 30 | self.download_bandwidth = download_bandwidth 31 | self.d2d_bandwidth = d2d_bandwidth 32 | 33 | 34 | class SocialGraph: 35 | def __init__(self): 36 | self.relationships = {} # This now represents device-task type relationships 37 | 38 | def add_relationship(self, device_id, task_type, strength): 39 | self.relationships[(device_id, task_type)] = strength 40 | 41 | def get_strength(self, device_id, task_type): 42 | return self.relationships.get((device_id, task_type), 0) 43 | 44 | 45 | 46 | class TaskDependencyGraph: 47 | def __init__(self): 48 | self.graph = nx.DiGraph() 49 | 50 | def add_task(self, task): 51 | self.graph.add_node(task.task_id, task=task) 52 | 53 | def add_dependency(self, task_id, dependent_task_id): 54 | self.graph.add_edge(dependent_task_id, task_id) 55 | 56 | def display_graph(self): 57 | pos = nx.spring_layout(self.graph) 58 | labels = {node: f'Task {node}' for node in self.graph.nodes()} 59 | nx.draw(self.graph, pos, labels=labels, with_labels=True, node_color='skyblue') 60 | plt.show() 61 | 62 | def get_dependencies(self, task_id): 63 | return list(self.graph.predecessors(task_id)) 64 | 65 | def is_executable(self, task_id): 66 | if not self.get_dependencies(task_id): # 如果没有依赖项,立即可执行 67 | return True 68 | return all(self.graph.nodes[dep]['task'].is_completed for dep in self.get_dependencies(task_id)) 69 | 70 | 71 | class TaskScheduler: 72 | def __init__(self, tasks, devices, social_graph): 73 | self.tasks = tasks 74 | self.devices = devices 75 | self.social_graph = social_graph 76 | self.dependency_graph = TaskDependencyGraph() 77 | for task in self.tasks: 78 | self.dependency_graph.add_task(task) 79 | for dep in task.dependencies: 80 | self.dependency_graph.add_dependency(task.task_id, dep) 81 | self.cost_data = {'local': [], 'D2D': [], 'edge': [], 'D2D-edge': []} # 初始化存储成本数据的字典 82 | 83 | 84 | def get_device_by_id(self, device_id): 85 | """通过设备ID获取设备对象""" 86 | return next((device for device in self.devices if device.device_id == device_id), None) 87 | 88 | def is_task_executable(self, task_id): 89 | task = self.get_task_by_id(task_id) 90 | if not task.dependencies: 91 | return True # If there are no dependencies, the task can be executed immediately 92 | return all(self.get_task_by_id(dep).is_completed for dep in task.dependencies) 93 | 94 | def get_task_by_id(self, task_id): 95 | """通过任务ID获取任务对象""" 96 | return next((task for task in self.tasks if task.task_id == task_id), None) 97 | 98 | def calculate_overhead_U_matrix(self): 99 | U_matrix = {} 100 | for task in self.tasks: 101 | if self.is_task_executable(task.task_id): 102 | U_matrix[task.task_id] = {} 103 | for device in self.devices: 104 | _, U_value = self.calculate_overhead_U(task, device) 105 | U_matrix[task.task_id][device.device_id] = U_value 106 | return U_matrix 107 | 108 | def calculate_overhead_U(self, task, device): 109 | if task.data_size > device.capacity: 110 | print( 111 | f"Task {task.task_id} with data size {task.data_size} exceeds Device {device.device_id} capacity {device.capacity}. Returning inf.") 112 | return None, float('inf') # 如果任务数据大小超过设备容量,则返回无穷大 113 | 114 | overheads = {} 115 | mu = 0.1 # 时间和能耗的权重因子 116 | for offloading_type in ['local', 'D2D', 'edge', 'D2D-edge']: 117 | energy = self.calculate_energy_consumption(task, device, offloading_type) 118 | time = self.calculate_time_delay(task, device, offloading_type) 119 | social_factor = self.calculate_social_factor(task, device) if offloading_type in ['D2D', 'D2D-edge'] else 1 120 | U = mu * time + (1 - mu) * energy * social_factor 121 | overheads[offloading_type] = U 122 | print(f"Offloading {offloading_type}: Energy={energy}, Time={time}, Social={social_factor}, U={U}") 123 | 124 | best_type = min(overheads, key=overheads.get) 125 | best_cost = overheads[best_type] 126 | print(f"Best offloading option: {best_type} with cost {best_cost}") 127 | return best_type, best_cost 128 | 129 | def calculate_energy_consumption(self, task, device, offloading_type): 130 | if offloading_type == 'local': 131 | return device.transmission_power * task.computation_cost 132 | elif offloading_type == 'D2D': 133 | return ( 134 | device.d2d_transmit_power + device.d2d_receive_power) * task.data_size / device.d2d_bandwidth + device.transmission_power * task.computation_cost 135 | elif offloading_type == 'edge': 136 | return device.cellular_transmit_power * task.data_size / device.upload_bandwidth + device.cellular_receive_power * task.result_size / device.download_bandwidth 137 | elif offloading_type == 'D2D-edge': 138 | return ( 139 | device.d2d_transmit_power + device.cellular_receive_power) * task.data_size / device.d2d_bandwidth + device.cellular_transmit_power * task.data_size / device.upload_bandwidth + device.cellular_receive_power * task.result_size / device.download_bandwidth 140 | else: 141 | raise ValueError("Unsupported offloading type") 142 | 143 | def calculate_time_delay(self, task, device, offloading_type): 144 | edge_processing_time = 0.5 # 假设的云处理时间 145 | if offloading_type == 'local': 146 | return task.data_size / device.capacity 147 | elif offloading_type == 'D2D': 148 | return task.data_size / device.d2d_bandwidth + task.data_size / device.capacity 149 | elif offloading_type == 'edge': 150 | return task.data_size / device.upload_bandwidth + edge_processing_time 151 | elif offloading_type == 'D2D-edge': 152 | return task.data_size / device.d2d_bandwidth + task.data_size / device.upload_bandwidth + edge_processing_time 153 | else: 154 | raise ValueError("Unsupported offloading type") 155 | 156 | def calculate_social_factor(self, task, device): 157 | # 计算社会因素对能耗和时间的加权影响 158 | task_type = task.social_group # 从任务对象中获取任务类型 159 | device_id = device.device_id # 从设备对象中获取设备ID 160 | w_ij = self.social_graph.get_strength(device_id, task_type) 161 | alpha = 0.5 # 示例: 调节因子 162 | social_cost = 1 / (1 + alpha * w_ij) 163 | return social_cost 164 | 165 | def global_optimization(self, U_matrix): 166 | task_ids = list(U_matrix.keys()) 167 | device_ids = [device.device_id for device in self.devices] 168 | cost_matrix = [[U_matrix[task_id][device_id] for device_id in device_ids] for task_id in task_ids] 169 | row_indices, col_indices = linear_sum_assignment(cost_matrix) 170 | return [(task_ids[row], device_ids[col]) for row, col in zip(row_indices, col_indices)] 171 | 172 | def optimize_task_offloading(self): 173 | changes = True 174 | while changes: 175 | changes = False 176 | U_matrix = self.calculate_overhead_U_matrix() 177 | if not U_matrix: 178 | break # 如果没有可执行的任务,则中断循环 179 | 180 | assignments = self.global_optimization(U_matrix) 181 | for task_id, device_id in assignments: 182 | task = self.get_task_by_id(task_id) 183 | device = self.get_device_by_id(device_id) 184 | if not task.is_completed: 185 | task.is_completed = True 186 | task.device_id = device_id # 确保分配了设备ID 187 | changes = True 188 | _, _ = self.calculate_overhead_U(task, device) 189 | 190 | def sensitivity_analysis_data_size(self, task_id, data_sizes): 191 | original_data_size = self.get_task_by_id(task_id).data_size 192 | for size in data_sizes: 193 | self.get_task_by_id(task_id).data_size = size 194 | self.optimize_task_offloading() 195 | task = self.get_task_by_id(task_id) 196 | if task.device_id is not None: 197 | device = self.get_device_by_id(task.device_id) 198 | offloading_type, cost = self.calculate_overhead_U(task, device) 199 | self.cost_data[offloading_type].append((size, cost)) 200 | print(f"Data size {size} results in {offloading_type} with cost {cost}") 201 | else: 202 | # 如果没有设备可以处理任务,确保记录这一信息 203 | for key in self.cost_data.keys(): 204 | self.cost_data[key].append((size, float('inf'))) 205 | print(f"No feasible offloading found for data size {size}") 206 | self.get_task_by_id(task_id).data_size = original_data_size 207 | 208 | 209 | def initialize_system(): 210 | tasks = [ 211 | Task(1, 100, 500, 'A'), 212 | Task(2, 150, 600, 'B', [1]), 213 | Task(3, 200, 400, 'C'), 214 | Task(4, 175, 450, 'A', [1, 3]) 215 | ] 216 | tasks[0].is_completed = True # 假设任务 1 已完成 217 | 218 | devices = [ 219 | Device(1, 5000, 0.1, 'A', 0.05, 0.05, 0.2, 0.1, 1000, 1000, 20), 220 | Device(2, 10000, 0.2, 'B', 0.05, 0.05, 0.2, 0.1, 1000, 1000, 20), 221 | Device(3, 7500, 0.15, 'C', 0.04, 0.04, 0.15, 0.12, 800, 800, 30), 222 | Device(4, 10000, 0.1, 'A', 0.05, 0.05, 0.2, 0.1, 2000, 2000, 50) # 增加一个高容量设备 223 | ] 224 | social_graph = SocialGraph() 225 | # Assuming 'A', 'B', 'C' are the identifiers for task types directly 226 | social_graph.add_relationship(1, 'A', 0.9) 227 | social_graph.add_relationship(2, 'B', 0.9) 228 | social_graph.add_relationship(3, 'C', 0.9) 229 | social_graph.add_relationship(4, 'A', 0.8) 230 | return tasks, devices, social_graph 231 | 232 | 233 | 234 | 235 | 236 | if __name__ == '__main__': 237 | tasks, devices, social_graph = initialize_system() 238 | scheduler = TaskScheduler(tasks, devices, social_graph) 239 | data_sizes = range(500, 2500, 200) # 定义数据大小范围 240 | scheduler.sensitivity_analysis_data_size(1, data_sizes) # 进行敏感性分析 241 | 242 | print("Cost data collected:", scheduler.cost_data) 243 | 244 | plt.figure(figsize=(10, 6)) 245 | for offload_type, data in scheduler.cost_data.items(): 246 | if data: 247 | sizes, costs = zip(*data) 248 | plt.plot(sizes, costs, marker='o', label=offload_type) 249 | plt.title('Cost vs Data Size for Different Offloading Types') 250 | plt.xlabel('Data Size (MB)') 251 | plt.ylabel('Cost') 252 | plt.legend() 253 | plt.grid(True) 254 | plt.show() 255 | 256 | -------------------------------------------------------------------------------- /shiyan1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | # 定义参数 5 | P_trans = 0.1 6 | P_d = 500 7 | B_d2d = 20 8 | B_up = 10 9 | B_down = 10 10 | T_d2d_trans = 0.05 11 | T_d2d_recv = 0.05 12 | T_cell_trans = 0.2 13 | T_cell_recv = 0.1 14 | T_edge_proc = 0.5 15 | C_t = 100 16 | R_t = 500 17 | mu_values = [0.1, 0.5, 0.9] # 不同的mu值 18 | 19 | # 数据大小范围 20 | data_sizes = np.linspace(200, 2000, 10) 21 | 22 | # 创建一个图形框,在其中可以放置多个轴 23 | fig, axs = plt.subplots(1, 3, figsize=(15, 5), sharey=True) 24 | 25 | for idx, mu in enumerate(mu_values): 26 | costs = {'Local': [], 'D2D': [], 'Edge': [], 'D2D-Edge': []} 27 | 28 | for D_t in data_sizes: 29 | # 本地执行成本 30 | E_local = P_trans * C_t 31 | T_local = D_t / P_d 32 | costs['Local'].append(mu * T_local + (1 - mu) * E_local) 33 | 34 | # D2D执行成本 35 | E_D2D = (T_d2d_trans + T_d2d_recv) * (D_t / B_d2d) + P_trans * C_t 36 | T_D2D = (D_t / B_d2d) + (D_t / P_d) 37 | costs['D2D'].append(mu * T_D2D + (1 - mu) * E_D2D) 38 | 39 | # 边缘执行成本 40 | E_edge = T_cell_trans * (D_t / B_up) + T_cell_recv * (R_t / B_down) 41 | T_edge = (D_t / B_up) + T_edge_proc 42 | costs['Edge'].append(mu * T_edge + (1 - mu) * E_edge) 43 | 44 | # D2D-边缘混合执行成本 45 | E_D2D_edge = (T_d2d_trans + T_cell_recv) * (D_t / B_d2d) + T_cell_trans * (D_t / B_up) + T_cell_recv * ( 46 | R_t / B_down) 47 | T_D2D_edge = (D_t / B_d2d) + (D_t / B_up) + T_edge_proc 48 | costs['D2D-Edge'].append(mu * T_D2D_edge + (1 - mu) * E_D2D_edge) 49 | 50 | # 绘制每个mu值的成本 51 | ax = axs[idx] 52 | for offloading_type, cost in costs.items(): 53 | ax.plot(data_sizes, cost, label=f'{offloading_type} Cost') 54 | 55 | ax.set_title(f'Impact of Data Size on Offloading Cost (mu={mu})') 56 | ax.set_xlabel('Data Size (MB)') 57 | if idx == 0: 58 | ax.set_ylabel('Total Cost (Weighted Sum of Energy and Time)') 59 | ax.legend() 60 | ax.grid(True) 61 | 62 | # 显示整个图表 63 | plt.tight_layout() 64 | plt.show() 65 | -------------------------------------------------------------------------------- /shiyan2~4.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | ''' 5 | # 场景 2: 物联网设备(如传感器网络) 6 | P_trans = 0.01 7 | P_d = 50 8 | B_d2d = 1 9 | B_up = 2 10 | B_down = 2 11 | T_d2d_trans = 0.02 12 | T_d2d_recv = 0.02 13 | T_cell_trans = 0.1 14 | T_cell_recv = 0.05 15 | T_edge_proc = 0.1 16 | C_t = 10 17 | R_t = 50 18 | mu = 0.2 # 能耗是关键考虑因素 19 | 20 | 21 | # 场景 3: 数据中心或服务器 22 | P_trans = 0.5 23 | P_d = 1000 24 | B_d2d = 100 25 | B_up = 100 26 | B_down = 100 27 | T_d2d_trans = 0.5 28 | T_d2d_recv = 0.5 29 | T_cell_trans = 0.5 30 | T_cell_recv = 0.5 31 | T_edge_proc = 0.05 32 | C_t = 1000 33 | R_t = 5000 34 | mu = 0.9 # 时延是主要关注点 35 | ''' 36 | 37 | # 场景 4: 智能车辆 38 | P_trans = 0.3 39 | P_d = 800 40 | B_d2d = 50 41 | B_up = 50 42 | B_down = 50 43 | T_d2d_trans = 0.1 44 | T_d2d_recv = 0.1 45 | T_cell_trans = 0.3 46 | T_cell_recv = 0.2 47 | T_edge_proc = 0.2 48 | C_t = 500 49 | R_t = 2500 50 | mu = 0.7 # 响应时间和能耗都很重要 51 | 52 | # 数据大小范围 53 | data_sizes = np.linspace(200, 2000, 10) 54 | 55 | # 计算各种卸载策略的成本 56 | costs = {'Local': [], 'D2D': [], 'Edge': [], 'D2D-Edge': []} 57 | 58 | for D_t in data_sizes: 59 | # 本地执行成本 60 | E_local = P_trans * C_t 61 | T_local = D_t / P_d 62 | costs['Local'].append(mu * T_local + (1 - mu) * E_local) 63 | 64 | # D2D执行成本 65 | E_D2D = (T_d2d_trans + T_d2d_recv) * (D_t / B_d2d) + P_trans * C_t 66 | T_D2D = (D_t / B_d2d) + (D_t / P_d) 67 | costs['D2D'].append(mu * T_D2D + (1 - mu) * E_D2D) 68 | 69 | # 边缘执行成本 70 | E_edge = T_cell_trans * (D_t / B_up) + T_cell_recv * (R_t / B_down) 71 | T_edge = (D_t / B_up) + T_edge_proc 72 | costs['Edge'].append(mu * T_edge + (1 - mu) * E_edge) 73 | 74 | # D2D-边缘混合执行成本 75 | E_D2D_edge = (T_d2d_trans + T_cell_recv) * (D_t / B_d2d) + T_cell_trans * (D_t / B_up) + T_cell_recv * ( 76 | R_t / B_down) 77 | T_D2D_edge = (D_t / B_d2d) + (D_t / B_up) + T_edge_proc 78 | costs['D2D-Edge'].append(mu * T_D2D_edge + (1 - mu) * E_D2D_edge) 79 | 80 | # 绘图 81 | plt.figure(figsize=(10, 6)) 82 | for offloading_type, cost in costs.items(): 83 | plt.plot(data_sizes, cost, label=f'{offloading_type} Cost') 84 | 85 | plt.title('Impact of Data Size on Offloading Cost') 86 | plt.xlabel('Data Size (MB)') 87 | plt.ylabel('Total Cost (Weighted Sum of Energy and Time)') 88 | plt.legend() 89 | plt.grid(True) 90 | plt.show() 91 | -------------------------------------------------------------------------------- /social3.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import matplotlib.pyplot as plt 3 | from scipy.optimize import linear_sum_assignment 4 | 5 | 6 | class Task: 7 | def __init__(self, task_id, computation_cost, data_size, social_group, dependencies=[], result_size=0): 8 | self.task_id = task_id 9 | self.computation_cost = computation_cost 10 | self.data_size = data_size 11 | self.social_group = social_group 12 | self.dependencies = dependencies 13 | self.result_size = result_size 14 | self.is_completed = False # 默认任务未完成 15 | 16 | 17 | class Device: 18 | def __init__(self, device_id, capacity, transmission_power, social_group, 19 | d2d_transmit_power, d2d_receive_power, cellular_transmit_power, 20 | cellular_receive_power, upload_bandwidth, download_bandwidth, d2d_bandwidth): 21 | self.device_id = device_id 22 | self.capacity = capacity 23 | self.transmission_power = transmission_power 24 | self.social_group = social_group 25 | self.d2d_transmit_power = d2d_transmit_power 26 | self.d2d_receive_power = d2d_receive_power 27 | self.cellular_transmit_power = cellular_transmit_power 28 | self.cellular_receive_power = cellular_receive_power 29 | self.upload_bandwidth = upload_bandwidth 30 | self.download_bandwidth = download_bandwidth 31 | self.d2d_bandwidth = d2d_bandwidth 32 | 33 | 34 | class SocialGraph: 35 | def __init__(self): 36 | self.relationships = {} # This now represents device-task type relationships 37 | 38 | def add_relationship(self, device_id, task_type, strength): 39 | self.relationships[(device_id, task_type)] = strength 40 | 41 | def get_strength(self, device_id, task_type): 42 | return self.relationships.get((device_id, task_type), 0) 43 | 44 | 45 | 46 | class TaskDependencyGraph: 47 | def __init__(self): 48 | self.graph = nx.DiGraph() 49 | 50 | def add_task(self, task): 51 | self.graph.add_node(task.task_id, task=task) 52 | 53 | def add_dependency(self, task_id, dependent_task_id): 54 | self.graph.add_edge(dependent_task_id, task_id) 55 | 56 | def display_graph(self): 57 | pos = nx.spring_layout(self.graph) 58 | labels = {node: f'Task {node}' for node in self.graph.nodes()} 59 | nx.draw(self.graph, pos, labels=labels, with_labels=True, node_color='skyblue') 60 | plt.show() 61 | 62 | def get_dependencies(self, task_id): 63 | return list(self.graph.predecessors(task_id)) 64 | 65 | def is_executable(self, task_id): 66 | if not self.get_dependencies(task_id): # 如果没有依赖项,立即可执行 67 | return True 68 | return all(self.graph.nodes[dep]['task'].is_completed for dep in self.get_dependencies(task_id)) 69 | 70 | 71 | class TaskScheduler: 72 | def __init__(self, tasks, devices, social_graph): 73 | self.tasks = tasks 74 | self.devices = devices 75 | self.social_graph = social_graph 76 | self.dependency_graph = TaskDependencyGraph() 77 | for task in self.tasks: 78 | self.dependency_graph.add_task(task) 79 | for dep in task.dependencies: 80 | self.dependency_graph.add_dependency(task.task_id, dep) 81 | 82 | def get_device_by_id(self, device_id): 83 | """通过设备ID获取设备对象""" 84 | return next((device for device in self.devices if device.device_id == device_id), None) 85 | 86 | def is_task_executable(self, task_id): 87 | """检查任务是否可以执行,即所有依赖任务都已完成""" 88 | task = self.get_task_by_id(task_id) 89 | if not task.dependencies: 90 | return True # 如果没有依赖,任务可以立即执行 91 | return all(self.get_task_by_id(dep).is_completed for dep in task.dependencies) 92 | 93 | def get_task_by_id(self, task_id): 94 | """通过任务ID获取任务对象""" 95 | return next((task for task in self.tasks if task.task_id == task_id), None) 96 | 97 | def calculate_overhead_U_matrix(self): 98 | U_matrix = {} 99 | for task in self.tasks: 100 | if self.is_task_executable(task.task_id): 101 | U_matrix[task.task_id] = {} 102 | for device in self.devices: 103 | _, U_value = self.calculate_overhead_U(task, device) 104 | U_matrix[task.task_id][device.device_id] = U_value 105 | return U_matrix 106 | 107 | def calculate_overhead_U(self, task, device): 108 | overheads = {} 109 | mu = 0.5 # 假设时间和能耗的权重为0.5,可根据需求调整 110 | for offloading_type in ['local', 'D2D', 'edge', 'D2D-edge']: 111 | energy = self.calculate_energy_consumption(task, device, offloading_type) 112 | time = self.calculate_time_delay(task, device, offloading_type) 113 | if offloading_type in ['D2D', 'D2D-edge']: 114 | social_factor = self.calculate_social_factor(task, device) 115 | else: 116 | social_factor = 1 # 对于 'local' 和 'edge' 不考虑社会因素 117 | U = mu * time + (1 - mu) * energy * social_factor 118 | overheads[offloading_type] = U 119 | best_type = min(overheads, key=overheads.get) 120 | return best_type, overheads[best_type] 121 | 122 | def calculate_energy_consumption(self, task, device, offloading_type): 123 | if offloading_type == 'local': 124 | return device.transmission_power * task.computation_cost 125 | elif offloading_type == 'D2D': 126 | return ( 127 | device.d2d_transmit_power + device.d2d_receive_power) * task.data_size / device.d2d_bandwidth + device.transmission_power * task.computation_cost 128 | elif offloading_type == 'edge': 129 | return device.cellular_transmit_power * task.data_size / device.upload_bandwidth + device.cellular_receive_power * task.result_size / device.download_bandwidth 130 | elif offloading_type == 'D2D-edge': 131 | return ( 132 | device.d2d_transmit_power + device.cellular_receive_power) * task.data_size / device.d2d_bandwidth + device.cellular_transmit_power * task.data_size / device.upload_bandwidth + device.cellular_receive_power * task.result_size / device.download_bandwidth 133 | else: 134 | raise ValueError("Unsupported offloading type") 135 | 136 | def calculate_time_delay(self, task, device, offloading_type): 137 | edge_processing_time = 0.5 # 假设的云处理时间 138 | if offloading_type == 'local': 139 | return task.data_size / device.capacity 140 | elif offloading_type == 'D2D': 141 | return task.data_size / device.d2d_bandwidth + task.data_size / device.capacity 142 | elif offloading_type == 'edge': 143 | return task.data_size / device.upload_bandwidth + edge_processing_time 144 | elif offloading_type == 'D2D-edge': 145 | return task.data_size / device.d2d_bandwidth + task.data_size / device.upload_bandwidth + edge_processing_time 146 | else: 147 | raise ValueError("Unsupported offloading type") 148 | 149 | def calculate_social_factor(self, task, device): 150 | # 计算社会因素对能耗和时间的加权影响 151 | task_type = task.social_group # 从任务对象中获取任务类型 152 | device_id = device.device_id # 从设备对象中获取设备ID 153 | w_ij = self.social_graph.get_strength(device_id, task_type) 154 | alpha = 0.5 # 示例: 调节因子 155 | social_cost = 1 / (1 + alpha * w_ij) 156 | return social_cost 157 | 158 | def global_optimization(self, U_matrix): 159 | task_ids = list(U_matrix.keys()) 160 | device_ids = [device.device_id for device in self.devices] 161 | cost_matrix = [[U_matrix[task_id][device_id] for device_id in device_ids] for task_id in task_ids] 162 | row_indices, col_indices = linear_sum_assignment(cost_matrix) 163 | return [(task_ids[row], device_ids[col]) for row, col in zip(row_indices, col_indices)] 164 | 165 | def optimize_task_offloading(self): 166 | """优化任务卸载,直到没有更多任务可以执行为止""" 167 | changes = True 168 | while changes: 169 | changes = False 170 | U_matrix = self.calculate_overhead_U_matrix() 171 | if not U_matrix: 172 | break # 如果没有任务可以执行,退出循环 173 | 174 | assignments = self.global_optimization(U_matrix) 175 | for task_id, device_id in assignments: 176 | task = self.get_task_by_id(task_id) 177 | device = self.get_device_by_id(device_id) 178 | if not task.is_completed: # 确保任务尚未完成 179 | task.is_completed = True # 标记任务为完成 180 | changes = True # 标记有任务完成,可能触发新的任务可以执行 181 | offloading_type, _ = self.calculate_overhead_U(task, device) 182 | self.visualize_assignments(assignments) 183 | 184 | def visualize_assignments(self, assignments): 185 | G = nx.DiGraph() 186 | pos = {} 187 | labels = {} 188 | 189 | for task_id, device_id in assignments: 190 | G.add_node(task_id, label=f'Task {task_id}', color='lightblue') 191 | G.add_node(device_id, label=f'Device {device_id}', color='lightgreen') 192 | G.add_edge(task_id, device_id) 193 | pos[task_id] = (1, -int(task_id)) 194 | pos[device_id] = (2, -int(device_id)) 195 | labels[task_id] = f'Task {task_id}' 196 | labels[device_id] = f'Device {device_id}' 197 | 198 | colors = [G.nodes[n]['color'] for n in G.nodes()] 199 | 200 | nx.draw(G, pos, labels=labels, node_color=colors, with_labels=True, edge_color='black', width=2) 201 | plt.title('Task to Device Assignments') 202 | plt.show() 203 | 204 | 205 | def initialize_system(): 206 | tasks = [ 207 | Task(1, 100, 1000, 'A', [], 500), 208 | Task(2, 150, 1200, 'B', [1], 600), 209 | Task(3, 200, 800, 'C', [2], 400), 210 | Task(4, 175, 950, 'A', [1, 3], 475), 211 | Task(5, 120, 700, 'B', [1, 2, 4], 350), 212 | Task(6, 130, 1100, 'C', [5], 300), 213 | Task(7, 160, 500, 'A', [6], 550), 214 | Task(8, 140, 1200, 'B', [6, 7], 600), 215 | Task(9, 180, 1000, 'C', [1, 5, 8], 500) 216 | ] 217 | tasks[0].is_completed = True 218 | tasks[1].is_completed = True 219 | tasks[8].is_completed = True 220 | devices = [ 221 | Device(1, 500, 0.1, 'A', 0.05, 0.05, 0.2, 0.1, 500, 500, 10), 222 | Device(2, 1000, 0.2, 'B', 0.05, 0.05, 0.2, 0.1, 500, 500, 20), 223 | Device(3, 750, 0.15, 'C', 0.04, 0.04, 0.15, 0.12, 400, 400, 15), 224 | Device(4, 800, 0.12, 'A', 0.03, 0.03, 0.18, 0.11, 450, 450, 18), 225 | Device(5, 900, 0.13, 'B', 0.06, 0.06, 0.22, 0.12, 550, 550, 25) 226 | ] 227 | social_graph = SocialGraph() 228 | # Assuming 'A', 'B', 'C' are the identifiers for task types directly 229 | social_graph.add_relationship(1, 'A', 0.9) # Device 1 has high affinity for Task type 'A' 230 | social_graph.add_relationship(2, 'B', 0.9) # Device 2 for Task type 'B' 231 | social_graph.add_relationship(3, 'C', 0.9) # Device 3 for Task type 'C' 232 | social_graph.add_relationship(4, 'A', 0.8) # Device 4 also supports Task type 'A' well 233 | social_graph.add_relationship(5, 'B', 0.8) # Device 5 supports Task type 'B' 234 | return tasks, devices, social_graph 235 | 236 | 237 | 238 | if __name__ == '__main__': 239 | tasks, devices, social_graph = initialize_system() 240 | scheduler = TaskScheduler(tasks, devices, social_graph) 241 | scheduler.optimize_task_offloading() 242 | --------------------------------------------------------------------------------