Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,184 +1,184 @@
|
|
| 1 |
-
import gradio as gr
|
| 2 |
-
import joblib
|
| 3 |
-
import numpy as np
|
| 4 |
-
import networkx as nx
|
| 5 |
-
import matplotlib.pyplot as plt
|
| 6 |
-
import io
|
| 7 |
-
from PIL import Image
|
| 8 |
-
import ast
|
| 9 |
-
import pandas as pd
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
def create_node_inputs(num_nodes):
|
| 13 |
-
"""Dynamically create input fields for each node's parameters, returning sliders only."""
|
| 14 |
-
inputs = []
|
| 15 |
-
for i in range(num_nodes):
|
| 16 |
-
inputs.append(gr.HTML(value=f"<h3>Node {i} Parameters</h3>")) # Display-only
|
| 17 |
-
inputs.append(gr.Slider(0.1, 0.5, value=0.3, label=f"Node {i} Active Time (s)"))
|
| 18 |
-
inputs.append(gr.Slider(0.5, 2.0, value=1.0, label=f"Node {i} Sleep Time (s)"))
|
| 19 |
-
inputs.append(gr.Slider(0.1, 1.0, value=0.5, label=f"Node {i} Energy Level"))
|
| 20 |
-
inputs.append(gr.Slider(0.1, 1.0, value=0.5, label=f"Node {i} Retransmission Interval (s)"))
|
| 21 |
-
inputs.append(gr.Slider(0.01, 0.3, value=0.1, label=f"Node {i} Packet Loss Rate"))
|
| 22 |
-
inputs.append(gr.Slider(10, 100, value=50, label=f"Node {i} Distance to Next Node (m)"))
|
| 23 |
-
return inputs
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
def simulate_network(num_nodes, edges_input, source_node, dest_node, *node_params):
|
| 27 |
-
# Load the trained model
|
| 28 |
-
model = joblib.load('energy_efficiency_model.pkl')
|
| 29 |
-
|
| 30 |
-
# Parse edges input (e.g., "0->1,1->2" or "[(0,1),(1,2)]")
|
| 31 |
-
try:
|
| 32 |
-
if edges_input.startswith('['):
|
| 33 |
-
edges = ast.literal_eval(edges_input)
|
| 34 |
-
if not all(isinstance(e, tuple) and len(e) == 2 for e in edges):
|
| 35 |
-
raise ValueError("Edges must be a list of tuples, e.g., [(0,1),(1,2)]")
|
| 36 |
-
else:
|
| 37 |
-
edges = [tuple(map(int, e.split('->'))) for e in edges_input.split(',')]
|
| 38 |
-
if not all(len(e) == 2 for e in edges):
|
| 39 |
-
raise ValueError("Edges must be in format '0->1,1->2' or [(0,1),(1,2)]")
|
| 40 |
-
except Exception as e:
|
| 41 |
-
return None, f"Error parsing edges: {str(e)}. Use format '0->1,1->2' or [(0,1),(1,2)]"
|
| 42 |
-
|
| 43 |
-
# Validate edges and source/destination nodes
|
| 44 |
-
try:
|
| 45 |
-
source_node = int(source_node)
|
| 46 |
-
dest_node = int(dest_node)
|
| 47 |
-
if not (0 <= source_node < num_nodes and 0 <= dest_node < num_nodes):
|
| 48 |
-
return None, f"Error: Source and destination nodes must be between 0 and {num_nodes - 1}"
|
| 49 |
-
if not all(0 <= u < num_nodes and 0 <= v < num_nodes for u, v in edges):
|
| 50 |
-
return None, f"Error: All node indices in edges must be between 0 and {num_nodes - 1}"
|
| 51 |
-
except ValueError:
|
| 52 |
-
return None, "Error: Source and destination nodes must be integers"
|
| 53 |
-
|
| 54 |
-
# Create directed graph
|
| 55 |
-
G = nx.DiGraph()
|
| 56 |
-
G.add_nodes_from(range(num_nodes))
|
| 57 |
-
G.add_edges_from(edges)
|
| 58 |
-
|
| 59 |
-
# Group node parameters, excluding HTML components
|
| 60 |
-
params_per_node = 6 # Number of numerical parameters per node
|
| 61 |
-
node_data = []
|
| 62 |
-
for i in range(num_nodes):
|
| 63 |
-
start_idx = i * (params_per_node + 1) + 1 # Skip HTML component
|
| 64 |
-
node_data.append({
|
| 65 |
-
'active_time': node_params[start_idx],
|
| 66 |
-
'sleep_time': node_params[start_idx + 1],
|
| 67 |
-
'energy_level': node_params[start_idx + 2],
|
| 68 |
-
'retransmission_interval': node_params[start_idx + 3],
|
| 69 |
-
'packet_loss_rate': node_params[start_idx + 4],
|
| 70 |
-
'distance_to_next_node': node_params[start_idx + 5]
|
| 71 |
-
})
|
| 72 |
-
|
| 73 |
-
# Calculate energy consumption for each edge
|
| 74 |
-
feature_names = ['active_time', 'sleep_time', 'energy_level',
|
| 75 |
-
'retransmission_interval', 'packet_loss_rate', 'distance_to_next_node']
|
| 76 |
-
for u, v in G.edges():
|
| 77 |
-
# Use source node's parameters for edge (u,v)
|
| 78 |
-
params = node_data[u]
|
| 79 |
-
input_features = pd.DataFrame([[
|
| 80 |
-
params['active_time'],
|
| 81 |
-
params['sleep_time'],
|
| 82 |
-
params['energy_level'],
|
| 83 |
-
params['retransmission_interval'],
|
| 84 |
-
params['packet_loss_rate'],
|
| 85 |
-
params['distance_to_next_node']
|
| 86 |
-
]], columns=feature_names)
|
| 87 |
-
energy_consumption = model.predict(input_features)[0]
|
| 88 |
-
G.edges[u, v]['energy'] = energy_consumption
|
| 89 |
-
|
| 90 |
-
# Find the most energy-efficient path
|
| 91 |
-
path = None
|
| 92 |
-
total_energy = None
|
| 93 |
-
try:
|
| 94 |
-
path = nx.shortest_path(G, source=source_node, target=dest_node, weight='energy')
|
| 95 |
-
total_energy = sum(G.edges[u, v]['energy'] for u, v in zip(path[:-1], path[1:]))
|
| 96 |
-
except nx.NetworkXNoPath:
|
| 97 |
-
# Find all possible paths and select the most energy-efficient one
|
| 98 |
-
all_paths = list(nx.all_simple_paths(G, source=source_node, target=dest_node))
|
| 99 |
-
if not all_paths:
|
| 100 |
-
return None, f"No path exists from node {source_node} to node {dest_node}"
|
| 101 |
-
# Calculate total energy for each path
|
| 102 |
-
min_energy = float('inf')
|
| 103 |
-
best_path = None
|
| 104 |
-
for p in all_paths:
|
| 105 |
-
energy = sum(G.edges[u, v]['energy'] for u, v in zip(p[:-1], p[1:]))
|
| 106 |
-
if energy < min_energy:
|
| 107 |
-
min_energy = energy
|
| 108 |
-
best_path = p
|
| 109 |
-
path = best_path
|
| 110 |
-
total_energy = min_energy
|
| 111 |
-
|
| 112 |
-
# Visualize the network
|
| 113 |
-
plt.figure(figsize=(12, 8))
|
| 114 |
-
pos = nx.spring_layout(G)
|
| 115 |
-
|
| 116 |
-
# Draw nodes and edges
|
| 117 |
-
nx.draw(G, pos, with_labels=True, node_color='lightblue',
|
| 118 |
-
node_size=500, font_size=12, font_weight='bold')
|
| 119 |
-
|
| 120 |
-
# Draw edge labels (energy consumption)
|
| 121 |
-
edge_labels = nx.get_edge_attributes(G, 'energy')
|
| 122 |
-
edge_labels = {k: f"{v:.3f}" for k, v in edge_labels.items()}
|
| 123 |
-
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
|
| 124 |
-
|
| 125 |
-
# Highlight the optimal path
|
| 126 |
-
path_edges = list(zip(path[:-1], path[1:]))
|
| 127 |
-
nx.draw_networkx_edges(G, pos, edgelist=path_edges, edge_color='r', width=2)
|
| 128 |
-
|
| 129 |
-
# Save plot to buffer
|
| 130 |
-
buf = io.BytesIO()
|
| 131 |
-
plt.savefig(buf, format='png')
|
| 132 |
-
buf.seek(0)
|
| 133 |
-
img = Image.open(buf)
|
| 134 |
-
plt.close()
|
| 135 |
-
|
| 136 |
-
# Prepare output
|
| 137 |
-
result = f"""
|
| 138 |
-
Network Simulation Results:
|
| 139 |
-
- Number of nodes: {num_nodes}
|
| 140 |
-
- Edges: {edges}
|
| 141 |
-
- Optimal path from node {source_node} to node {dest_node}: {path}
|
| 142 |
-
- Total energy consumption: {total_energy:.3f} units
|
| 143 |
-
- Node Parameters:
|
| 144 |
-
"""
|
| 145 |
-
for i, params in enumerate(node_data):
|
| 146 |
-
result += f"""
|
| 147 |
-
Node {i}:
|
| 148 |
-
* Active Time: {params['active_time']:.2f} s
|
| 149 |
-
* Sleep Time: {params['sleep_time']:.2f} s
|
| 150 |
-
* Energy Level: {params['energy_level']:.2f}
|
| 151 |
-
* Retransmission Interval: {params['retransmission_interval']:.2f} s
|
| 152 |
-
* Packet Loss Rate: {params['packet_loss_rate']:.2f}
|
| 153 |
-
* Distance to Next Node: {params['distance_to_next_node']:.2f} m
|
| 154 |
-
"""
|
| 155 |
-
|
| 156 |
-
return img, result
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
# Create Gradio interface
|
| 160 |
-
def create_dynamic_interface(num_nodes=5):
|
| 161 |
-
inputs = [
|
| 162 |
-
gr.Slider(3,
|
| 163 |
-
gr.Textbox(label="Edges (e.g., '0->1,1->2' or '[(0,1),(1,2)]')",
|
| 164 |
-
value="0->1,1->2,2->3,3->4" if num_nodes == 5 else ""),
|
| 165 |
-
gr.Number(value=0, label="Source Node", precision=0),
|
| 166 |
-
gr.Number(value=num_nodes - 1, label="Destination Node", precision=0),
|
| 167 |
-
]
|
| 168 |
-
inputs.extend(create_node_inputs(num_nodes))
|
| 169 |
-
return inputs
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
# Initial interface with default number of nodes
|
| 173 |
-
initial_inputs = create_dynamic_interface()
|
| 174 |
-
|
| 175 |
-
iface = gr.Interface(
|
| 176 |
-
fn=simulate_network,
|
| 177 |
-
inputs=initial_inputs,
|
| 178 |
-
outputs=[gr.Image(label="Network Visualization"), gr.Textbox(label="Simulation Results")],
|
| 179 |
-
title="Energy-Efficient Network Path Simulation",
|
| 180 |
-
description="Simulate energy-efficient path selection with custom node parameters and network topology. Specify edges as '0->1,1->2' or [(0,1),(1,2)]."
|
| 181 |
-
)
|
| 182 |
-
|
| 183 |
-
if __name__ == "__main__":
|
| 184 |
iface.launch()
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import joblib
|
| 3 |
+
import numpy as np
|
| 4 |
+
import networkx as nx
|
| 5 |
+
import matplotlib.pyplot as plt
|
| 6 |
+
import io
|
| 7 |
+
from PIL import Image
|
| 8 |
+
import ast
|
| 9 |
+
import pandas as pd
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def create_node_inputs(num_nodes):
|
| 13 |
+
"""Dynamically create input fields for each node's parameters, returning sliders only."""
|
| 14 |
+
inputs = []
|
| 15 |
+
for i in range(num_nodes):
|
| 16 |
+
inputs.append(gr.HTML(value=f"<h3>Node {i} Parameters</h3>")) # Display-only
|
| 17 |
+
inputs.append(gr.Slider(0.1, 0.5, value=0.3, label=f"Node {i} Active Time (s)"))
|
| 18 |
+
inputs.append(gr.Slider(0.5, 2.0, value=1.0, label=f"Node {i} Sleep Time (s)"))
|
| 19 |
+
inputs.append(gr.Slider(0.1, 1.0, value=0.5, label=f"Node {i} Energy Level"))
|
| 20 |
+
inputs.append(gr.Slider(0.1, 1.0, value=0.5, label=f"Node {i} Retransmission Interval (s)"))
|
| 21 |
+
inputs.append(gr.Slider(0.01, 0.3, value=0.1, label=f"Node {i} Packet Loss Rate"))
|
| 22 |
+
inputs.append(gr.Slider(10, 100, value=50, label=f"Node {i} Distance to Next Node (m)"))
|
| 23 |
+
return inputs
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def simulate_network(num_nodes, edges_input, source_node, dest_node, *node_params):
|
| 27 |
+
# Load the trained model
|
| 28 |
+
model = joblib.load('energy_efficiency_model.pkl')
|
| 29 |
+
|
| 30 |
+
# Parse edges input (e.g., "0->1,1->2" or "[(0,1),(1,2)]")
|
| 31 |
+
try:
|
| 32 |
+
if edges_input.startswith('['):
|
| 33 |
+
edges = ast.literal_eval(edges_input)
|
| 34 |
+
if not all(isinstance(e, tuple) and len(e) == 2 for e in edges):
|
| 35 |
+
raise ValueError("Edges must be a list of tuples, e.g., [(0,1),(1,2)]")
|
| 36 |
+
else:
|
| 37 |
+
edges = [tuple(map(int, e.split('->'))) for e in edges_input.split(',')]
|
| 38 |
+
if not all(len(e) == 2 for e in edges):
|
| 39 |
+
raise ValueError("Edges must be in format '0->1,1->2' or [(0,1),(1,2)]")
|
| 40 |
+
except Exception as e:
|
| 41 |
+
return None, f"Error parsing edges: {str(e)}. Use format '0->1,1->2' or [(0,1),(1,2)]"
|
| 42 |
+
|
| 43 |
+
# Validate edges and source/destination nodes
|
| 44 |
+
try:
|
| 45 |
+
source_node = int(source_node)
|
| 46 |
+
dest_node = int(dest_node)
|
| 47 |
+
if not (0 <= source_node < num_nodes and 0 <= dest_node < num_nodes):
|
| 48 |
+
return None, f"Error: Source and destination nodes must be between 0 and {num_nodes - 1}"
|
| 49 |
+
if not all(0 <= u < num_nodes and 0 <= v < num_nodes for u, v in edges):
|
| 50 |
+
return None, f"Error: All node indices in edges must be between 0 and {num_nodes - 1}"
|
| 51 |
+
except ValueError:
|
| 52 |
+
return None, "Error: Source and destination nodes must be integers"
|
| 53 |
+
|
| 54 |
+
# Create directed graph
|
| 55 |
+
G = nx.DiGraph()
|
| 56 |
+
G.add_nodes_from(range(num_nodes))
|
| 57 |
+
G.add_edges_from(edges)
|
| 58 |
+
|
| 59 |
+
# Group node parameters, excluding HTML components
|
| 60 |
+
params_per_node = 6 # Number of numerical parameters per node
|
| 61 |
+
node_data = []
|
| 62 |
+
for i in range(num_nodes):
|
| 63 |
+
start_idx = i * (params_per_node + 1) + 1 # Skip HTML component
|
| 64 |
+
node_data.append({
|
| 65 |
+
'active_time': node_params[start_idx],
|
| 66 |
+
'sleep_time': node_params[start_idx + 1],
|
| 67 |
+
'energy_level': node_params[start_idx + 2],
|
| 68 |
+
'retransmission_interval': node_params[start_idx + 3],
|
| 69 |
+
'packet_loss_rate': node_params[start_idx + 4],
|
| 70 |
+
'distance_to_next_node': node_params[start_idx + 5]
|
| 71 |
+
})
|
| 72 |
+
|
| 73 |
+
# Calculate energy consumption for each edge
|
| 74 |
+
feature_names = ['active_time', 'sleep_time', 'energy_level',
|
| 75 |
+
'retransmission_interval', 'packet_loss_rate', 'distance_to_next_node']
|
| 76 |
+
for u, v in G.edges():
|
| 77 |
+
# Use source node's parameters for edge (u,v)
|
| 78 |
+
params = node_data[u]
|
| 79 |
+
input_features = pd.DataFrame([[
|
| 80 |
+
params['active_time'],
|
| 81 |
+
params['sleep_time'],
|
| 82 |
+
params['energy_level'],
|
| 83 |
+
params['retransmission_interval'],
|
| 84 |
+
params['packet_loss_rate'],
|
| 85 |
+
params['distance_to_next_node']
|
| 86 |
+
]], columns=feature_names)
|
| 87 |
+
energy_consumption = model.predict(input_features)[0]
|
| 88 |
+
G.edges[u, v]['energy'] = energy_consumption
|
| 89 |
+
|
| 90 |
+
# Find the most energy-efficient path
|
| 91 |
+
path = None
|
| 92 |
+
total_energy = None
|
| 93 |
+
try:
|
| 94 |
+
path = nx.shortest_path(G, source=source_node, target=dest_node, weight='energy')
|
| 95 |
+
total_energy = sum(G.edges[u, v]['energy'] for u, v in zip(path[:-1], path[1:]))
|
| 96 |
+
except nx.NetworkXNoPath:
|
| 97 |
+
# Find all possible paths and select the most energy-efficient one
|
| 98 |
+
all_paths = list(nx.all_simple_paths(G, source=source_node, target=dest_node))
|
| 99 |
+
if not all_paths:
|
| 100 |
+
return None, f"No path exists from node {source_node} to node {dest_node}"
|
| 101 |
+
# Calculate total energy for each path
|
| 102 |
+
min_energy = float('inf')
|
| 103 |
+
best_path = None
|
| 104 |
+
for p in all_paths:
|
| 105 |
+
energy = sum(G.edges[u, v]['energy'] for u, v in zip(p[:-1], p[1:]))
|
| 106 |
+
if energy < min_energy:
|
| 107 |
+
min_energy = energy
|
| 108 |
+
best_path = p
|
| 109 |
+
path = best_path
|
| 110 |
+
total_energy = min_energy
|
| 111 |
+
|
| 112 |
+
# Visualize the network
|
| 113 |
+
plt.figure(figsize=(12, 8))
|
| 114 |
+
pos = nx.spring_layout(G)
|
| 115 |
+
|
| 116 |
+
# Draw nodes and edges
|
| 117 |
+
nx.draw(G, pos, with_labels=True, node_color='lightblue',
|
| 118 |
+
node_size=500, font_size=12, font_weight='bold')
|
| 119 |
+
|
| 120 |
+
# Draw edge labels (energy consumption)
|
| 121 |
+
edge_labels = nx.get_edge_attributes(G, 'energy')
|
| 122 |
+
edge_labels = {k: f"{v:.3f}" for k, v in edge_labels.items()}
|
| 123 |
+
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
|
| 124 |
+
|
| 125 |
+
# Highlight the optimal path
|
| 126 |
+
path_edges = list(zip(path[:-1], path[1:]))
|
| 127 |
+
nx.draw_networkx_edges(G, pos, edgelist=path_edges, edge_color='r', width=2)
|
| 128 |
+
|
| 129 |
+
# Save plot to buffer
|
| 130 |
+
buf = io.BytesIO()
|
| 131 |
+
plt.savefig(buf, format='png')
|
| 132 |
+
buf.seek(0)
|
| 133 |
+
img = Image.open(buf)
|
| 134 |
+
plt.close()
|
| 135 |
+
|
| 136 |
+
# Prepare output
|
| 137 |
+
result = f"""
|
| 138 |
+
Network Simulation Results:
|
| 139 |
+
- Number of nodes: {num_nodes}
|
| 140 |
+
- Edges: {edges}
|
| 141 |
+
- Optimal path from node {source_node} to node {dest_node}: {path}
|
| 142 |
+
- Total energy consumption: {total_energy:.3f} units
|
| 143 |
+
- Node Parameters:
|
| 144 |
+
"""
|
| 145 |
+
for i, params in enumerate(node_data):
|
| 146 |
+
result += f"""
|
| 147 |
+
Node {i}:
|
| 148 |
+
* Active Time: {params['active_time']:.2f} s
|
| 149 |
+
* Sleep Time: {params['sleep_time']:.2f} s
|
| 150 |
+
* Energy Level: {params['energy_level']:.2f}
|
| 151 |
+
* Retransmission Interval: {params['retransmission_interval']:.2f} s
|
| 152 |
+
* Packet Loss Rate: {params['packet_loss_rate']:.2f}
|
| 153 |
+
* Distance to Next Node: {params['distance_to_next_node']:.2f} m
|
| 154 |
+
"""
|
| 155 |
+
|
| 156 |
+
return img, result
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
# Create Gradio interface
|
| 160 |
+
def create_dynamic_interface(num_nodes=5):
|
| 161 |
+
inputs = [
|
| 162 |
+
gr.Slider(3, 4, value=num_nodes, step=1, label="Number of Nodes"),
|
| 163 |
+
gr.Textbox(label="Edges (e.g., '0->1,1->2' or '[(0,1),(1,2)]')",
|
| 164 |
+
value="0->1,1->2,2->3,3->4" if num_nodes == 5 else ""),
|
| 165 |
+
gr.Number(value=0, label="Source Node", precision=0),
|
| 166 |
+
gr.Number(value=num_nodes - 1, label="Destination Node", precision=0),
|
| 167 |
+
]
|
| 168 |
+
inputs.extend(create_node_inputs(num_nodes))
|
| 169 |
+
return inputs
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
# Initial interface with default number of nodes
|
| 173 |
+
initial_inputs = create_dynamic_interface()
|
| 174 |
+
|
| 175 |
+
iface = gr.Interface(
|
| 176 |
+
fn=simulate_network,
|
| 177 |
+
inputs=initial_inputs,
|
| 178 |
+
outputs=[gr.Image(label="Network Visualization"), gr.Textbox(label="Simulation Results")],
|
| 179 |
+
title="Energy-Efficient Network Path Simulation",
|
| 180 |
+
description="Simulate energy-efficient path selection with custom node parameters and network topology. Specify edges as '0->1,1->2' or [(0,1),(1,2)]."
|
| 181 |
+
)
|
| 182 |
+
|
| 183 |
+
if __name__ == "__main__":
|
| 184 |
iface.launch()
|