|
1 | 1 | import networkx as nx
|
| 2 | +import heapq |
| 3 | +import datetime |
| 4 | +import logging |
2 | 5 |
|
3 |
| -# Metadata-like structure for properties |
4 |
| -properties = { |
5 |
| - "id": { |
6 |
| - "description": "Lowercase, underscore-separated, unique identifier.", |
7 |
| - "pattern": "^[a-z0-9_]+$", |
8 |
| - "title": "Id", |
9 |
| - "type": "string" |
10 |
| - }, |
11 |
| - "name": { |
12 |
| - "description": "Human-readable format, title case with acronyms.", |
13 |
| - "title": "Name", |
14 |
| - "type": "string" |
| 6 | +logging.basicConfig(level=logging.INFO) |
| 7 | + |
| 8 | +node_types = { |
| 9 | + "sensor": { |
| 10 | + "default_state": {"value": 0}, |
| 11 | + "on_threshold_event": lambda node, event: logging.info(f"Sensor {node} event: {event}") |
15 | 12 | },
|
16 |
| - "full_form": { |
17 |
| - "description": "Full acronym expansion.", |
18 |
| - "title": "Full Form", |
19 |
| - "type": "string" |
| 13 | + "controller": { |
| 14 | + "default_state": {"status": "idle"}, |
| 15 | + "on_state_change": lambda node, event: logging.info(f"Controller {node} event: {event}") |
20 | 16 | }
|
21 | 17 | }
|
22 | 18 |
|
23 |
| -# Depth-First Search (DFS) function with metadata |
24 |
| -def dfs(graph, start, max_depth=None): |
25 |
| - """ |
26 |
| - Perform Depth-First Search (DFS) from a starting node. |
27 |
| - |
28 |
| - Parameters: |
29 |
| - - graph: The graph object (directed or undirected). |
30 |
| - - start: The node to start the traversal. |
31 |
| - - max_depth: The maximum depth to search (optional, None for no limit). |
32 |
| - |
33 |
| - Returns: |
34 |
| - - A list of nodes visited during the traversal. |
35 |
| - """ |
36 |
| - visited, result = set(), [] |
37 |
| - |
38 |
| - def _dfs(node, depth): |
39 |
| - if node not in visited and (max_depth is None or depth <= max_depth): |
40 |
| - visited.add(node) |
41 |
| - result.append(node) |
42 |
| - for neighbor in graph.neighbors(node): |
43 |
| - _dfs(neighbor, depth + 1) |
44 |
| - |
45 |
| - _dfs(start, 0) |
46 |
| - return result |
47 |
| - |
48 |
| -# Breadth-First Search (BFS) function with metadata |
49 |
| -def bfs(graph, start, max_depth=None): |
50 |
| - """ |
51 |
| - Perform Breadth-First Search (BFS) from a starting node. |
| 19 | +event_queue = [] |
52 | 20 |
|
53 |
| - Parameters: |
54 |
| - - graph: The graph object (directed or undirected). |
55 |
| - - start: The node to start the traversal. |
56 |
| - - max_depth: The maximum depth to search (optional, None for no limit). |
| 21 | +def add_node_with_type(graph, node_id, node_type, **kwargs): |
| 22 | + state = node_types[node_type]["default_state"].copy() |
| 23 | + state.update(kwargs) |
| 24 | + graph.add_node(node_id, node_type=node_type, **state) |
57 | 25 |
|
58 |
| - Returns: |
59 |
| - - A list of nodes visited during the traversal. |
60 |
| - """ |
61 |
| - visited, queue, result, depth = set(), [start], [], 0 |
| 26 | +def add_event(event_type, node, priority, **kwargs): |
| 27 | + event = {"event_type": event_type, "node": node, "timestamp": datetime.datetime.now(), "priority": priority, **kwargs} |
| 28 | + heapq.heappush(event_queue, (priority, event)) |
| 29 | + logging.info(f"Event added: {event}") |
62 | 30 |
|
63 |
| - while queue and (max_depth is None or depth <= max_depth): |
64 |
| - node = queue.pop(0) |
65 |
| - if node not in visited: |
66 |
| - visited.add(node) |
67 |
| - result.append(node) |
68 |
| - queue.extend(graph.neighbors(node)) |
69 |
| - if not queue: |
70 |
| - depth += 1 |
71 |
| - return result |
| 31 | +def process_events(graph): |
| 32 | + while event_queue: |
| 33 | + priority, event = heapq.heappop(event_queue) |
| 34 | + logging.info(f"Processing: {event}") |
| 35 | + node_type = graph.nodes[event["node"]]["node_type"] |
| 36 | + if event["event_type"] == "threshold_event" and "on_threshold_event" in node_types[node_type]: |
| 37 | + node_types[node_type]["on_threshold_event"](event["node"], event) |
| 38 | + elif event["event_type"] == "state_change" and "on_state_change" in node_types[node_type]: |
| 39 | + node_types[node_type]["on_state_change"](event["node"], event) |
72 | 40 |
|
73 |
| -# Example: Graph Creation and Usage of DFS/BFS |
74 |
| -if __name__ == "__main__": |
75 |
| - G = nx.Graph() |
76 |
| - G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5)]) |
| 41 | +graph = nx.Graph() |
| 42 | +add_node_with_type(graph, "sensor1", "sensor", value=5) |
| 43 | +add_node_with_type(graph, "controller1", "controller", status="active") |
77 | 44 |
|
78 |
| - # Example DFS and BFS |
79 |
| - print("DFS Traversal:", dfs(G, 1)) |
80 |
| - print("BFS Traversal:", bfs(G, 1)) |
| 45 | +add_event("threshold_event", "sensor1", 1, value=10) |
| 46 | +add_event("state_change", "controller1", 2, status="inactive") |
81 | 47 |
|
82 |
| - # Output metadata properties |
83 |
| - print("\nMetadata Properties:") |
84 |
| - for key, value in properties.items(): |
85 |
| - print(f"{key.capitalize()}:") |
86 |
| - for k, v in value.items(): |
87 |
| - print(f" {k}: {v}") |
| 48 | +process_events(graph) |
0 commit comments