File size: 1,889 Bytes
2e818da
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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")