mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-05-21 23:24:44 +02:00
feat: Infer node region from neighbors
Nodes without GPS can be assigned to a region based on their neighbors. Uses edge data to build neighbor graph, then assigns unlocated nodes to the most common region among their neighbors. Iterates until no more assignments possible. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c3f1347b4b
commit
584616c8a5
1 changed files with 65 additions and 1 deletions
|
|
@ -369,7 +369,7 @@ class MeshHealthEngine:
|
|||
center_lon=anchor.lon,
|
||||
)
|
||||
|
||||
# Assign nodes to nearest region
|
||||
# Assign nodes to nearest region (first pass: GPS-based)
|
||||
unlocated = []
|
||||
for node in nodes.values():
|
||||
if node.latitude and node.longitude:
|
||||
|
|
@ -382,6 +382,70 @@ class MeshHealthEngine:
|
|||
else:
|
||||
unlocated.append(node.node_id)
|
||||
|
||||
# Build neighbor map from edges
|
||||
# First, create a mapping from numeric node_id to hex id
|
||||
numeric_to_hex: dict[str, str] = {}
|
||||
for node in all_nodes:
|
||||
hex_id = node.get("id")
|
||||
num_id = node.get("node_id")
|
||||
if hex_id and num_id:
|
||||
numeric_to_hex[str(num_id)] = str(hex_id)
|
||||
|
||||
all_edges = source_manager.get_all_edges()
|
||||
neighbors: dict[str, set[str]] = {}
|
||||
for edge in all_edges:
|
||||
# Get edge endpoints (may be numeric)
|
||||
from_raw = edge.get("from") or edge.get("from_node") or edge.get("source")
|
||||
to_raw = edge.get("to") or edge.get("to_node") or edge.get("target")
|
||||
if not from_raw or not to_raw:
|
||||
continue
|
||||
|
||||
# Convert to hex ID format if numeric
|
||||
from_id = numeric_to_hex.get(str(from_raw), str(from_raw))
|
||||
to_id = numeric_to_hex.get(str(to_raw), str(to_raw))
|
||||
|
||||
if from_id not in neighbors:
|
||||
neighbors[from_id] = set()
|
||||
if to_id not in neighbors:
|
||||
neighbors[to_id] = set()
|
||||
neighbors[from_id].add(to_id)
|
||||
neighbors[to_id].add(from_id)
|
||||
|
||||
# Second pass: Assign unlocated nodes based on neighbor regions
|
||||
# Repeat until no more assignments
|
||||
max_iterations = 10
|
||||
for _ in range(max_iterations):
|
||||
newly_assigned = []
|
||||
for node_id in unlocated:
|
||||
if node_id not in nodes:
|
||||
continue
|
||||
node = nodes[node_id]
|
||||
if node.region:
|
||||
continue # Already assigned
|
||||
|
||||
# Count neighbor regions
|
||||
neighbor_ids = neighbors.get(node_id, set())
|
||||
region_counts: dict[str, int] = {}
|
||||
for nid in neighbor_ids:
|
||||
if nid in nodes and nodes[nid].region:
|
||||
r = nodes[nid].region
|
||||
region_counts[r] = region_counts.get(r, 0) + 1
|
||||
|
||||
if region_counts:
|
||||
# Assign to most common neighbor region
|
||||
best_region = max(region_counts, key=region_counts.get)
|
||||
node.region = best_region
|
||||
region_map[best_region].node_ids.append(node_id)
|
||||
newly_assigned.append(node_id)
|
||||
|
||||
# Remove newly assigned from unlocated
|
||||
for nid in newly_assigned:
|
||||
if nid in unlocated:
|
||||
unlocated.remove(nid)
|
||||
|
||||
if not newly_assigned:
|
||||
break # No more progress
|
||||
|
||||
regions = list(region_map.values())
|
||||
|
||||
# Create localities within each region (cluster by proximity)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue