study-buddy / app /services /graph_algorithm_validator.py
GitHub Actions
deploy d092bea3608b7a29952f16357fda39b7a29e399b
2e818da
Raw
History Blame Contribute Delete
1.89 kB
from __future__ import annotations
from app.schemas.visual_lesson import GraphAlgorithmSpec
from app.services.graph_algorithm_compiler import ALGORITHMS, GraphAlgorithmCompiler
class GraphAlgorithmValidationError(ValueError):
pass
class GraphAlgorithmValidator:
def __init__(self, compiler: GraphAlgorithmCompiler) -> None:
self.compiler = compiler
def validate(self, spec: GraphAlgorithmSpec) -> None:
node_ids = {node.node_id for node in spec.nodes}
if not 2 <= len(node_ids) <= 10 or len(node_ids) != len(spec.nodes):
raise GraphAlgorithmValidationError("A graph must contain 2–10 uniquely named nodes")
if spec.initial_start_node not in node_ids or spec.initial_target_node not in node_ids:
raise GraphAlgorithmValidationError("Initial graph endpoints are invalid")
if spec.primary_algorithm not in ALGORITHMS:
raise GraphAlgorithmValidationError("The selected graph algorithm is unsupported")
edge_ids: set[str] = set()
for edge in spec.edges:
if edge.edge_id in edge_ids or edge.source not in node_ids or edge.target not in node_ids or edge.weight <= 0:
raise GraphAlgorithmValidationError("The graph contains an invalid edge")
edge_ids.add(edge.edge_id)
claim_ids = {claim.claim_id for claim in spec.evidence_claims}
if not {"graph-bfs", "graph-dfs", "graph-dijkstra", "graph-astar"} <= claim_ids:
raise GraphAlgorithmValidationError("The graph visualization is missing algorithm definitions")
compiled = self.compiler.compile_spec(spec)
expected = len(ALGORITHMS) * len(node_ids) * len(node_ids)
if not compiled.assertions_passed or len(compiled.branches) != expected:
raise GraphAlgorithmValidationError("The graph compiler did not produce every endpoint branch")