Source code for pytwinnet.optimization.placement
from __future__ import annotations
from dataclasses import dataclass
from itertools import product
from typing import Dict, Iterable, List, Tuple, Any
import random
from ..core.digital_twin import DigitalTwin
from ..optimization.objective import Objective
Bounds2D = Tuple[Tuple[float,float], Tuple[float,float]] # ((x_min,x_max),(y_min,y_max))
[docs]
@dataclass
class PlacementGridOptimizer:
"""
Grid search over positions for a set of nodes (e.g., gNBs).
Beware combinatorics: keep grids small or optimize one node at a time.
"""
grid_x: Iterable[float]
grid_y: Iterable[float]
fixed_z: float = 10.0
copy_twin: bool = True
[docs]
def optimize(self, twin: DigitalTwin, objective: Objective, node_ids: List[str]) -> Dict[str, Any]:
best_score = float("-inf")
best_coords: Dict[str, Tuple[float,float,float]] = {}
points = [(x,y,self.fixed_z) for x in self.grid_x for y in self.grid_y]
combos = list(product(points, repeat=len(node_ids)))
evals = 0
for combo in combos:
sim = twin.snapshot() if self.copy_twin else twin
for nid, pos in zip(node_ids, combo):
n = sim.network.get_node_by_id(nid)
if n: n.move_to(pos)
score = objective.evaluate(sim)
evals += 1
if score > best_score:
best_score = score
best_coords = {nid: pos for nid, pos in zip(node_ids, combo)}
return {"best_score": best_score, "best_positions": best_coords, "evaluations": evals}
[docs]
@dataclass
class PlacementRandomSearchOptimizer:
"""
Randomly sample positions within bounds for given nodes.
"""
bounds: Bounds2D
samples: int = 200
fixed_z: float = 10.0
seed: int = 0
copy_twin: bool = True
[docs]
def optimize(self, twin: DigitalTwin, objective: Objective, node_ids: List[str]) -> Dict[str, Any]:
rng = random.Random(self.seed)
(x0,x1),(y0,y1) = self.bounds
best_score = float("-inf")
best_coords: Dict[str, Tuple[float,float,float]] = {}
for _ in range(self.samples):
sim = twin.snapshot() if self.copy_twin else twin
cur_coords = {}
for nid in node_ids:
x = rng.uniform(x0, x1); y = rng.uniform(y0, y1); z = self.fixed_z
n = sim.network.get_node_by_id(nid)
if n: n.move_to((x,y,z))
cur_coords[nid] = (x,y,z)
score = objective.evaluate(sim)
if score > best_score:
best_score = score
best_coords = cur_coords
return {"best_score": best_score, "best_positions": best_coords, "evaluations": self.samples}