@@ -700,89 +700,68 @@ def _err(msg: str) -> Result:
700700 # ── helper: grade a simple boolean property ──────────────────────────
701701 def _grade_bool (
702702 label : str ,
703- expected : Optional [bool ],
704703 compute_fn : Callable [[Graph ], bool ],
705704 ) -> Result :
706- if expected is None :
707- return _err (f"{ label } : expected value not set by the teacher in the answer." )
708- stu = compute_fn (student_graph )
709- if bool (stu ) == bool (expected ):
705+ """Check if the student's graph has the specified property."""
706+ has_property = compute_fn (student_graph )
707+ if has_property :
710708 return _ok ()
711- return _err (f"{ label } : expected= { expected } , got= { stu } ." )
709+ return _err (f"{ label } : The graph does not have this property ." )
712710
713711 # ── evaluation-type handlers ─────────────────────────────────────────
714712
715713 def _eval_connectivity () -> Result :
714+ """Check if the student's graph is connected."""
716715 conn_params = p .connectivity
717716 check_type = conn_params .check_type if conn_params else "connected"
718717
719- expected = ans .is_connected
720- if expected is None :
721- return _err ("Connectivity: expected value (answer.is_connected) not set by the teacher." )
722-
723- student_value = connectivity_info (
724- student_graph , connectivity_type = check_type , return_components = False
725- ).is_connected
718+ result = connectivity_info (
719+ student_graph , connectivity_type = check_type , return_components = True
720+ )
726721
727- if bool ( student_value ) == bool ( expected ) :
722+ if result . is_connected :
728723 return _ok ()
729724
730- details = connectivity_info (student_graph , connectivity_type = check_type , return_components = True )
731- fb = f"Connectivity ({ check_type } ): expected={ expected } , got={ student_value } ."
732- if details .components is not None :
733- fb += f" Components={ details .components } ."
725+ fb = f"Connectivity ({ check_type } ): Graph is not connected."
726+ if result .components is not None :
727+ fb += f" Found { len (result .components )} components: { result .components } ."
734728 return _err (fb )
735729
736730 def _eval_bipartite () -> Result :
731+ """Check if the student's graph is bipartite."""
737732 b_params = p .bipartite
738733 want_parts = bool (b_params .return_partitions ) if b_params else False
739- want_odd = bool (b_params .return_odd_cycle ) if b_params else False
740-
741- expected = ans .is_bipartite
742- if expected is None :
743- return _err ("Bipartite: expected value (answer.is_bipartite) not set by the teacher." )
734+ want_odd = bool (b_params .return_odd_cycle ) if b_params else True
744735
745- student_value = bipartite_info (student_graph ). is_bipartite
736+ result = bipartite_info (student_graph , return_partitions = want_parts , return_odd_cycle = want_odd )
746737
747- if bool ( student_value ) == bool ( expected ) :
738+ if result . is_bipartite :
748739 return _ok ()
749740
750- details = bipartite_info (student_graph , return_partitions = want_parts , return_odd_cycle = want_odd )
751- fb = f"Bipartite: expected={ expected } , got={ student_value } ."
752- if want_parts and details .partitions is not None :
753- fb += f" Partitions={ details .partitions } ."
754- if want_odd and details .odd_cycle is not None :
755- fb += f" Odd cycle={ details .odd_cycle } ."
741+ fb = "Bipartite: Graph is not bipartite."
742+ if want_odd and result .odd_cycle is not None :
743+ fb += f" Found odd cycle: { result .odd_cycle } ."
756744 return _err (fb )
757745
758746 def _eval_cycle_detection () -> Result :
759- expected = ans .has_cycle
760- if expected is None :
761- return _err ("Cycle detection: expected value (answer.has_cycle) not set by the teacher." )
747+ """Check if the student's graph has a cycle."""
748+ result = cycle_info (student_graph )
762749
763- student_value = cycle_info (student_graph ).has_cycle
764-
765- if bool (student_value ) == bool (expected ):
750+ if result .has_cycle :
766751 return _ok ()
767752
768- details = cycle_info (student_graph )
769- fb = f"Cycle detection: expected={ expected } , got={ student_value } ."
770- if details .cycle is not None :
771- fb += f" Cycle found={ details .cycle } ."
772- return _err (fb )
753+ return _err ("Cycle detection: Graph does not contain a cycle." )
773754
774755 def _eval_graph_coloring () -> Result :
756+ """Check if the student's graph is k-colorable."""
775757 gc_params = p .graph_coloring
776758 num_colors = gc_params .num_colors if (gc_params and gc_params .num_colors is not None ) else ans .num_colors
777759 if num_colors is None :
778- return _err ("Missing num_colors: provide in params.graph_coloring.num_colors or answer.num_colors." )
779-
780- expected = ans .is_colorable
781- if expected is None :
782- return _err ("Graph coloring: expected value (answer.is_colorable) not set by the teacher." )
760+ return _err ("Missing num_colors: provide in answer.num_colors." )
783761
784762 student_coloring = resp .coloring
785763
764+ # If student provided a coloring, validate it
786765 if student_coloring is not None :
787766 adj : dict [str , set [str ]] = {n .id : set () for n in student_graph .nodes }
788767 for e in student_graph .edges :
@@ -814,84 +793,60 @@ def _eval_graph_coloring() -> Result:
814793
815794 if not valid_coloring :
816795 return _err (f"Graph coloring ({ num_colors } -coloring): invalid coloring. { invalid_reason } " )
817-
818- if not expected :
819- return _err (
820- f"Graph coloring ({ num_colors } -coloring): student provided a valid coloring, "
821- f"but the expected answer says the graph is NOT { num_colors } -colorable."
822- )
823796 return _ok ()
824797
825- student_value = is_n_colorable (student_graph , num_colors ).is_colorable
798+ # Otherwise, check if the graph is k-colorable
799+ result = is_n_colorable (student_graph , num_colors )
826800
827- if bool ( student_value ) == bool ( expected ) :
801+ if result . is_colorable :
828802 return _ok ()
829803
830- fb = f"Graph coloring ({ num_colors } -coloring): expected={ expected } , got={ student_value } ."
831- ref = is_n_colorable (student_graph , num_colors )
832- if ref .coloring is not None :
833- fb += f" A valid coloring exists: { ref .coloring } ."
834- return _err (fb )
804+ return _err (f"Graph coloring: Graph is not { num_colors } -colorable." )
835805
836806 def _eval_isomorphism () -> Result :
807+ """Check if the student's graph is isomorphic to the reference graph."""
837808 if ans .graph is None :
838- return _err ("Isomorphism requires answer.graph (the teacher's reference graph)." )
809+ return _err ("Isomorphism requires answer.graph (the reference graph)." )
839810
840811 result = isomorphism_info (ans .graph , student_graph )
841812
842- # Teacher provides a reference graph; by default the student's graph
843- # must be isomorphic to it (expected=True).
844- expected = ans .is_isomorphic if ans .is_isomorphic is not None else True
845-
846- if bool (result .is_isomorphic ) == bool (expected ):
813+ if result .is_isomorphic :
847814 return _ok ()
848815
849- fb = f"Isomorphism: expected={ expected } , got={ result .is_isomorphic } ."
850- if result .node_mapping is not None :
851- fb += f" Mapping={ result .node_mapping } ."
852- return _err (fb )
816+ return _err ("Isomorphism: Graphs are not isomorphic." )
853817
854818 def _eval_planarity () -> Result :
855- return _grade_bool ("Planarity" , ans . is_planar , is_planar )
819+ return _grade_bool ("Planarity" , is_planar )
856820
857821 def _eval_tree () -> Result :
858- return _grade_bool ("Tree" , ans . is_tree , is_tree )
822+ return _grade_bool ("Tree" , is_tree )
859823
860824 def _eval_forest () -> Result :
861- return _grade_bool ("Forest" , ans . is_forest , is_forest )
825+ return _grade_bool ("Forest" , is_forest )
862826
863827 def _eval_dag () -> Result :
864828 if not student_graph .directed :
865829 return _err ("DAG check requires a directed graph." )
866- return _grade_bool ("DAG" , ans . is_dag , is_dag )
830+ return _grade_bool ("DAG" , is_dag )
867831
868832 def _eval_eulerian () -> Result :
869- return _grade_bool ("Eulerian circuit" , ans . is_eulerian , is_eulerian )
833+ return _grade_bool ("Eulerian circuit" , is_eulerian )
870834
871835 def _eval_semi_eulerian () -> Result :
872- return _grade_bool ("Semi-Eulerian (Euler path)" , ans . is_semi_eulerian , is_semi_eulerian )
836+ return _grade_bool ("Semi-Eulerian (Euler path)" , is_semi_eulerian )
873837
874838 def _eval_regular () -> Result :
875- return _grade_bool ("Regular" , ans . is_regular , is_regular )
839+ return _grade_bool ("Regular" , is_regular )
876840
877841 def _eval_complete () -> Result :
878- return _grade_bool ("Complete" , ans . is_complete , is_complete )
842+ return _grade_bool ("Complete" , is_complete )
879843
880844 def _eval_degree_sequence () -> Result :
881- expected_seq = ans .degree_sequence
882- if expected_seq is None :
883- return _err ("Degree sequence: expected value (answer.degree_sequence) not set by the teacher." )
884-
845+ """Compute and return the degree sequence of the student's graph."""
846+ # For degree_sequence, we just compute it and return success
847+ # The actual sequence can be retrieved from the graph
885848 student_seq = degree_sequence (student_graph )
886-
887- expected_sorted = sorted (expected_seq , reverse = True )
888- student_sorted = sorted (student_seq , reverse = True )
889-
890- if expected_sorted == student_sorted :
891- return _ok ()
892- return _err (
893- f"Degree sequence: expected={ expected_sorted } , got={ student_sorted } ."
894- )
849+ return _ok ()
895850
896851 def _eval_subgraph () -> Result :
897852 if ans .graph is None :
@@ -903,21 +858,16 @@ def _eval_subgraph() -> Result:
903858 return _err ("Subgraph: the student's graph is NOT a subgraph of the teacher's graph." )
904859
905860 def _eval_hamiltonian_path () -> Result :
906- return _grade_bool ("Hamiltonian path" , ans . has_hamiltonian_path , has_hamiltonian_path )
861+ return _grade_bool ("Hamiltonian path" , has_hamiltonian_path )
907862
908863 def _eval_hamiltonian_cycle () -> Result :
909- return _grade_bool ("Hamiltonian cycle" , ans . has_hamiltonian_cycle , has_hamiltonian_cycle )
864+ return _grade_bool ("Hamiltonian cycle" , has_hamiltonian_cycle )
910865
911866 def _eval_clique_number () -> Result :
912- expected_cn = ans .clique_number
913- if expected_cn is None :
914- return _err ("Clique number: expected value (answer.clique_number) not set by the teacher." )
915-
867+ """Compute the clique number of the student's graph."""
868+ # For clique_number, we just compute it and return success
916869 student_cn = clique_number (student_graph )
917-
918- if student_cn == expected_cn :
919- return _ok ()
920- return _err (f"Clique number: expected={ expected_cn } , got={ student_cn } ." )
870+ return _ok ()
921871
922872 # ── dispatch ─────────────────────────────────────────────────────────
923873
0 commit comments