SCN-001: All nodes reachable via BFS from demand/supply paths.
Source code in packages/gds-business/gds_business/supplychain/checks.py
| def check_scn001_network_connectivity(model: SupplyChainModel) -> list[Finding]:
"""SCN-001: All nodes reachable via BFS from demand/supply paths."""
findings: list[Finding] = []
# Build undirected adjacency from shipments
adj: dict[str, set[str]] = {n.name: set() for n in model.nodes}
for s in model.shipments:
if s.source in adj and s.target in adj:
adj[s.source].add(s.target)
adj[s.target].add(s.source)
# Also connect demand source targets
for d in model.demand_sources:
if d.target in adj:
adj[d.target].add(f"__demand_{d.name}")
# BFS from each demand target
reachable: set[str] = set()
for d in model.demand_sources:
if d.target not in adj:
continue
queue = [d.target]
visited: set[str] = set()
while queue:
node = queue.pop(0)
if node in visited or node not in adj:
continue
visited.add(node)
reachable.add(node)
queue.extend(adj[node] - visited)
# If no demands, try from first node
if not model.demand_sources and model.nodes:
queue = [model.nodes[0].name]
visited = set()
while queue:
node = queue.pop(0)
if node in visited or node not in adj:
continue
visited.add(node)
reachable.add(node)
queue.extend(adj[node] - visited)
for node in model.nodes:
is_reachable = node.name in reachable
findings.append(
Finding(
check_id="SCN-001",
severity=Severity.WARNING,
message=(
f"Node {node.name!r} "
f"{'is' if is_reachable else 'is NOT'} reachable "
f"in the supply network"
),
source_elements=[node.name],
passed=is_reachable,
)
)
return findings
|