from types import SimpleNamespace import pytest from app.algorithms.pressure_sensor_placement.kmeans_placement import ( optimize_sensor_placement, ) class FakeNetwork: junction_name_list = ["J1", "J2", "J3"] pipe_name_list = ["P1", "P2"] def __init__(self): self._nodes = { "J1": SimpleNamespace(coordinates=(0.0, 0.0)), "J2": SimpleNamespace(coordinates=(1.0, 0.0)), "J3": SimpleNamespace(coordinates=(2.0, 0.0)), } self._links = { "P1": SimpleNamespace( diameter=0.4, start_node_name="J1", end_node_name="J2" ), "P2": SimpleNamespace( diameter=0.1, start_node_name="J2", end_node_name="J3" ), } def get_node(self, node_id): return self._nodes[node_id] def get_link(self, link_id): return self._links[link_id] class DuplicateNearestNodeNetwork: junction_name_list = ["J1", "J2", "J3", "J4"] pipe_name_list = ["P1", "P2", "P3"] def __init__(self): self._nodes = { "J1": SimpleNamespace( coordinates=(-0.2967811321994103, 0.4867937179527957) ), "J2": SimpleNamespace( coordinates=(1.8589649622870763, -1.0070372175769569) ), "J3": SimpleNamespace( coordinates=(-1.4882734126175363, -1.6220731365802619) ), "J4": SimpleNamespace( coordinates=(1.203441836600899, 2.2320704059758474) ), } self._links = { "P1": SimpleNamespace( diameter=0.4, start_node_name="J1", end_node_name="J2" ), "P2": SimpleNamespace( diameter=0.4, start_node_name="J2", end_node_name="J3" ), "P3": SimpleNamespace( diameter=0.4, start_node_name="J3", end_node_name="J4" ), } def get_node(self, node_id): return self._nodes[node_id] def get_link(self, link_id): return self._links[link_id] def test_kmeans_filters_candidates_by_minimum_pipe_diameter(): selected = optimize_sensor_placement( FakeNetwork(), sensor_count=2, min_diameter_mm=300 ) assert set(selected) == {"J1", "J2"} def test_kmeans_rejects_sensor_count_above_eligible_candidates(): with pytest.raises(ValueError, match="候选节点数量"): optimize_sensor_placement( FakeNetwork(), sensor_count=3, min_diameter_mm=300 ) def test_kmeans_returns_unique_monitoring_nodes(): selected = optimize_sensor_placement( DuplicateNearestNodeNetwork(), sensor_count=2, min_diameter_mm=300 ) assert len(selected) == 2 assert len(set(selected)) == 2