def test_matching_static_vs_dynamic_graphs(): target_object = BOX train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] perception_graph = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) temporal_perception_graph = perception_graph.copy_with_temporal_scopes( temporal_scopes=[TemporalScope.AFTER]) perception_pattern = PerceptionGraphPattern.from_graph( perception_graph).perception_graph_pattern temporal_perception_pattern = perception_pattern.copy_with_temporal_scopes( required_temporal_scopes=[TemporalScope.AFTER]) # Test runtime error for matching static pattern against dynamic graph and vice versa with pytest.raises(RuntimeError): perception_pattern.matcher(temporal_perception_graph, match_mode=MatchMode.NON_OBJECT) with pytest.raises(RuntimeError): temporal_perception_pattern.matcher(perception_graph, match_mode=MatchMode.NON_OBJECT)
def test_two_objects(): two_object_template = Phase1SituationTemplate( "two-objects", salient_object_variables=[ object_variable("person", root_node=_PERSON), object_variable("toy_vehicle", required_properties=[_TOY_VEHICLE]), ], ) reference_object_sets = { immutableset(["mom", "toy_truck"]), immutableset(["dad", "toy_truck"]), immutableset(["learner", "toy_truck"]), immutableset(["mom", "toy_car"]), immutableset(["dad", "toy_car"]), immutableset(["learner", "toy_car"]), } generated_object_sets = set( immutableset(situation_object.ontology_node.handle for situation_object in situation.salient_objects) for situation in all_possible( two_object_template, ontology=_TESTING_ONTOLOGY, chooser=RandomChooser.for_seed(0), default_addressee_node=_LEARNER, )) assert generated_object_sets == reference_object_sets
def test_successfully_extending_partial_match(): """ Tests whether we can match a perception pattern against a perception graph when initializing the search from a partial match. """ target_object = BOX # Create train and test templates for the target objects train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] # Original perception graph perception = PerceptionGraph.from_frame( perceptual_representation.frames[0]) # Create a perception pattern for the whole thing # and also a perception pattern for a subset of the whole pattern whole_perception_pattern = PerceptionGraphPattern.from_graph( perception).perception_graph_pattern partial_digraph = whole_perception_pattern.copy_as_digraph() partial_digraph.remove_nodes_from([ node for node in partial_digraph.nodes if isinstance(node, IsColorNodePredicate) ]) partial_perception_pattern = PerceptionGraphPattern(partial_digraph) # get our initial match by matching the partial pattern matcher = partial_perception_pattern.matcher( perception, match_mode=MatchMode.NON_OBJECT) partial_match: PerceptionGraphPatternMatch = first( matcher.matches(use_lookahead_pruning=True)) partial_mapping = partial_match.pattern_node_to_matched_graph_node # Try to extend the partial mapping, to create a complete mapping matcher_2 = whole_perception_pattern.matcher( perception, match_mode=MatchMode.NON_OBJECT) complete_match: PerceptionGraphPatternMatch = first( matcher_2.matches(initial_partial_match=partial_mapping, use_lookahead_pruning=True), None, ) complete_mapping = complete_match.pattern_node_to_matched_graph_node assert len(complete_mapping) == len(perception.copy_as_digraph().nodes) assert len(complete_mapping) == len( whole_perception_pattern.copy_as_digraph().nodes)
def all_possible_test( template: Phase1SituationTemplate ) -> Iterable[HighLevelSemanticsSituation]: """ Shorcut for `all_possible` with the GAILA phase 1 ontology and a `RandomChooser` with seed 0. """ return all_possible(template, chooser=RandomChooser.for_seed(0), ontology=GAILA_PHASE_1_ONTOLOGY)
def _make_drink_cups_curriculum( num_samples: Optional[int], noise_objects: Optional[int], language_generator: LanguageGenerator[ HighLevelSemanticsSituation, LinearizedDependencyTree ], ) -> Phase1InstanceGroup: templates = [] for cup in [CUP, CUP_2, CUP_3, CUP_4]: cup_obj = standard_object("cup", cup) liquid_0 = object_variable("liquid_0", required_properties=[LIQUID]) person_0 = standard_object( "person_0", PERSON, banned_properties=[IS_SPEAKER, IS_ADDRESSEE] ) templates.append( Phase1SituationTemplate( "drink-cup", salient_object_variables=[liquid_0, person_0, cup_obj], background_object_variables=make_noise_objects(noise_objects), actions=[ Action( DRINK, argument_roles_to_fillers=[(AGENT, person_0), (THEME, liquid_0)], auxiliary_variable_bindings=[(DRINK_CONTAINER_AUX, cup_obj)], ) ], asserted_always_relations=[inside(liquid_0, cup_obj)], ) ) return phase2_instances( "drink - cup", chain( *[ sampled( cup_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_2_ONTOLOGY, max_to_sample=num_samples, block_multiple_of_the_same_type=True, ) if num_samples else all_possible( cup_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_2_ONTOLOGY, ) for cup_template in templates ] ), perception_generator=GAILA_PHASE_2_PERCEPTION_GENERATOR, language_generator=language_generator, )
def _make_sit_on_chair_curriculum( num_samples: Optional[int], noise_objects: Optional[int], language_generator: LanguageGenerator[ HighLevelSemanticsSituation, LinearizedDependencyTree ], ) -> Phase1InstanceGroup: templates = [] for chair_type in [CHAIR, CHAIR_2, CHAIR_3, CHAIR_4, CHAIR_5]: sitter = standard_object( "sitter_0", THING, required_properties=[ANIMATE], banned_properties=[IS_SPEAKER, IS_ADDRESSEE], ) seat = standard_object("chair", chair_type) templates.append( make_sit_transitive( sitter, seat, noise_objects, surface=False, syntax_hints=False ) ) templates.append( make_sit_template_intransitive( sitter, seat, noise_objects, surface=False, syntax_hints=False ) ) return phase2_instances( "sit on chair", chain( *[ sampled( template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_2_ONTOLOGY, max_to_sample=num_samples, block_multiple_of_the_same_type=True, ) if num_samples else all_possible( template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_2_ONTOLOGY, ) for template in templates ] ), perception_generator=GAILA_PHASE_2_PERCEPTION_GENERATOR, language_generator=language_generator, )
def test_perception_graph_post_init_edge_cases(): target_object = BOX train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] perception_graph = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) temporal_perception_graph = perception_graph.copy_with_temporal_scopes( temporal_scopes=[TemporalScope.AFTER]) temporal_digraph = temporal_perception_graph.copy_as_digraph() # Test valid edge label # The only feasible test seems to be the instation, since creating a corrupt instance throws the same RuntimeError with pytest.raises(RuntimeError): TemporallyScopedEdgeLabel(None) # In a dynamic graph, all edge labels must be wrapped in TemporallyScopedEdgeLabel new_graph = DiGraph() for (source, target) in temporal_digraph.edges(): new_graph.add_edge(source, target) new_graph[source][target]["label"] = None with pytest.raises(RuntimeError): PerceptionGraph(new_graph, dynamic=True) # TemporallyScopedEdgeLabels may not appear in a static graph new_graph = DiGraph() for (source, target) in temporal_digraph.edges(): new_graph.add_edge(source, target) new_graph[source][target]["label"] = TemporallyScopedEdgeLabel( "attribute", [TemporalScope.AFTER]) with pytest.raises(RuntimeError): PerceptionGraph(new_graph) # Every edge in a PerceptionGraph must have a 'label new_graph = DiGraph() for (source, target) in temporal_digraph.edges(): new_graph.add_edge(source, target) with pytest.raises(RuntimeError): PerceptionGraph(new_graph)
def test_copy_with_temporal_scopes_content(): """ Tests whether copy_with_temporal_scopes converts graphs to be dynamic as intended """ # We use a situation to generate the perceptual representation # for a box with color. target_object = BOX train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] perception_graph = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) temporal_perception_graph = perception_graph.copy_with_temporal_scopes( temporal_scopes=[TemporalScope.AFTER]) for (source, target) in perception_graph.copy_as_digraph().edges(): assert not isinstance( perception_graph.copy_as_digraph()[source][target]["label"], TemporallyScopedEdgeLabel, ) for (source, target) in temporal_perception_graph.copy_as_digraph().edges(): # Check type, and then the content label = temporal_perception_graph.copy_as_digraph( )[source][target]["label"] assert isinstance(label, TemporallyScopedEdgeLabel) assert (label.attribute == perception_graph.copy_as_digraph()[source] [target]["label"]) assert all(specifier in [TemporalScope.AFTER] for specifier in label.temporal_specifiers)
def run_subset_learner_for_object( nodes: Iterable[OntologyNode], *, learner, language_generator: LanguageGenerator[HighLevelSemanticsSituation, LinearizedDependencyTree]): colored_obj_objects = [ object_variable("obj-with-color", node, added_properties=[color_variable("color")]) for node in nodes ] obj_templates = [ Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[colored_obj_object], syntax_hints=[IGNORE_COLORS], ) for colored_obj_object in colored_obj_objects ] obj_curriculum = phase1_instances( "all obj situations", flatten([ all_possible( obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY, ) for obj_template in obj_templates ]), language_generator=language_generator, ) test_obj_curriculum = phase1_instances( "obj test", situations=sampled( obj_templates[0], chooser=PHASE1_TEST_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY, max_to_sample=1, ), language_generator=language_generator, ) for training_stage in [obj_curriculum]: for ( _, linguistic_description, perceptual_representation, ) in training_stage.instances(): learner.observe( LearningExample(perceptual_representation, linguistic_description)) for test_instance_group in [test_obj_curriculum]: for ( _, test_instance_language, test_instance_perception, ) in test_instance_group.instances(): descriptions_from_learner = learner.describe( test_instance_perception) gold = test_instance_language.as_token_sequence() assert gold in [ desc.as_token_sequence() for desc in descriptions_from_learner ]
def test_pursuit_object_learner_with_gaze(language_mode): target_objects = [ BALL, # PERSON, # CHAIR, # TABLE, DOG, # BIRD, BOX, ] language_generator = phase1_language_generator(language_mode) target_test_templates = [] for obj in target_objects: # Create train and test templates for the target objects test_obj_object = object_variable("obj-with-color", obj) test_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[test_obj_object], syntax_hints=[IGNORE_COLORS], gazed_objects=[test_obj_object], ) target_test_templates.extend( all_possible( test_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY, )) rng = random.Random() rng.seed(0) # We can use this to generate the actual pursuit curriculum train_curriculum = make_simple_pursuit_curriculum( target_objects=target_objects, num_instances=30, num_objects_in_instance=3, num_noise_instances=0, language_generator=language_generator, add_gaze=True, ) test_obj_curriculum = phase1_instances( "obj test", situations=target_test_templates, language_generator=language_generator, ) # All parameters should be in the range 0-1. # Learning factor works better when kept < 0.5 # Graph matching threshold doesn't seem to matter that much, as often seems to be either a # complete or a very small match. # The lexicon threshold works better between 0.07-0.3, but we need to play around with it because we end up not # lexicalize items sufficiently because of diminishing lexicon probability through training rng = random.Random() rng.seed(0) learner = IntegratedTemplateLearner(object_learner=PursuitObjectLearnerNew( learning_factor=0.05, graph_match_confirmation_threshold=0.7, lexicon_entry_threshold=0.7, rng=rng, smoothing_parameter=0.002, ontology=GAILA_PHASE_1_ONTOLOGY, language_mode=language_mode, rank_gaze_higher=True, )) for training_stage in [train_curriculum]: for ( _, linguistic_description, perceptual_representation, ) in training_stage.instances(): learner.observe( LearningExample(perceptual_representation, linguistic_description)) for test_instance_group in [test_obj_curriculum]: for ( _, test_instance_language, test_instance_perception, ) in test_instance_group.instances(): logging.info("lang: %s", test_instance_language) descriptions_from_learner = learner.describe( test_instance_perception) gold = test_instance_language.as_token_sequence() assert gold in [ desc.as_token_sequence() for desc in descriptions_from_learner ]
def test_copy_with_temporal_scope_pattern_content(): """ Tests whether copy_with_temporal_scope converts patterns to be dynamic as intended """ # We use a situation to generate the perceptual representation # for a box with color. target_object = BOX train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] perception_graph = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) perception_pattern = PerceptionGraphPattern.from_graph( perception_graph).perception_graph_pattern temporal_perception_graph = perception_graph.copy_with_temporal_scopes( temporal_scopes=[TemporalScope.AFTER]) temporal_perception_pattern = perception_pattern.copy_with_temporal_scopes( required_temporal_scopes=TemporalScope.AFTER) # Exception while applying to dynamic pattern with pytest.raises(RuntimeError): temporal_perception_pattern.copy_with_temporal_scopes( required_temporal_scopes=TemporalScope.AFTER) for (source, target) in perception_pattern.copy_as_digraph().edges(): assert not isinstance( perception_pattern.copy_as_digraph()[source][target]["predicate"], HoldsAtTemporalScopePredicate, ) for (source, target) in temporal_perception_pattern.copy_as_digraph().edges(): # Check type, and then the content predicate = temporal_perception_pattern.copy_as_digraph( )[source][target]["predicate"] # Test HoldsAtTemporalScope dot label, matches predicate assert isinstance(predicate.dot_label(), str) assert predicate.matches_predicate( HoldsAtTemporalScopePredicate(predicate.wrapped_edge_predicate, predicate.temporal_scopes)) assert not predicate.matches_predicate( HoldsAtTemporalScopePredicate(predicate.wrapped_edge_predicate, [TemporalScope.BEFORE])) assert isinstance(predicate, HoldsAtTemporalScopePredicate) assert (predicate.wrapped_edge_predicate == perception_pattern. copy_as_digraph()[source][target]["predicate"]) assert len(predicate.temporal_scopes) == 1 assert only(predicate.temporal_scopes) == TemporalScope.AFTER # Test normal matching behavior temporal_matcher = temporal_perception_pattern.matcher( temporal_perception_graph, match_mode=MatchMode.NON_OBJECT) first(temporal_matcher.matches(use_lookahead_pruning=True)) # Test HoldsAtTemporalScopePredicate for (source, target) in perception_graph.copy_as_digraph().edges(): label = "test edge label" edge_predicate = AnyEdgePredicate() temporal_predicate = HoldsAtTemporalScopePredicate( edge_predicate, [TemporalScope.AFTER]) temporal_edge_label = TemporallyScopedEdgeLabel( label, [TemporalScope.AFTER]) assert temporal_predicate(source, temporal_edge_label, target) # Non temporal edge exception with pytest.raises(RuntimeError): temporal_predicate(source, label, target)
def test_allowed_matches_with_bad_partial_match(): """ Tests whether PatternMarching's allowed_matches functionality works as intended when a bad partial match is specified. """ target_object = BOX train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] perception = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) pattern1: PerceptionGraphPattern = PerceptionGraphPattern.from_graph( perception.subgraph_by_nodes({ cast(PerceptionGraphNode, node) for node in perception._graph.nodes # pylint: disable=protected-access if getattr(node, "debug_handle", None) == "box_0" })).perception_graph_pattern pattern2: PerceptionGraphPattern = PerceptionGraphPattern.from_graph( perception.subgraph_by_nodes({ cast(PerceptionGraphNode, node) for node in perception._graph.nodes # pylint: disable=protected-access if getattr(node, "debug_handle", None) in {"box_0", "the ground"} })).perception_graph_pattern pattern1_box: AnyObjectPerception = cast( AnyObjectPerception, only(node for node in pattern1._graph # pylint: disable=protected-access if getattr(node, "debug_handle", None) == "box_0"), ) pattern2_box: AnyObjectPerception = cast( AnyObjectPerception, only(node for node in pattern2._graph # pylint: disable=protected-access if getattr(node, "debug_handle", None) == "box_0"), ) pattern2_ground: AnyObjectPerception = cast( AnyObjectPerception, only(node for node in pattern2._graph # pylint: disable=protected-access if getattr(node, "debug_handle", None) == "the ground"), ) matcher = PatternMatching( pattern=pattern1, graph_to_match_against=pattern2, matching_pattern_against_pattern=True, match_mode=MatchMode.OBJECT, allowed_matches=immutablesetmultidict([(pattern1_box, pattern2_box)]), ) with pytest.raises(RuntimeError): first( matcher.matches( initial_partial_match={pattern1_box: pattern2_ground}, use_lookahead_pruning=True, ), None, )
def test_syntactically_infeasible_partial_match(): """ Tests whether syntactic feasibility works as intended """ # We use a situation to generate the perceptual representation # for a box with color. target_object = BOX train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] # Original perception graph perception = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) # Create an altered perception graph we remove the color node altered_perception_digraph = perception.copy_as_digraph() nodes = [] for node in perception.copy_as_digraph().nodes: # If we find a color node, we add an extra edge to it if isinstance(node, tuple) and isinstance(node[0], RgbColorPerception): nodes.append(node) # change edge information for node in nodes: random_node = r.choice(list(altered_perception_digraph.nodes)) altered_perception_digraph.add_edge(node, random_node, label=PART_OF) random_node_2 = r.choice(list(altered_perception_digraph.nodes)) altered_perception_digraph.add_edge(random_node_2, node, label=PART_OF) altered_perception_perception_graph = PerceptionGraph( altered_perception_digraph) altered_perception_pattern = PerceptionGraphPattern.from_graph( altered_perception_perception_graph).perception_graph_pattern # Start the matching process, get a partial match first_matcher = altered_perception_pattern.matcher( altered_perception_perception_graph, match_mode=MatchMode.OBJECT) partial_match: PerceptionGraphPatternMatch = first( first_matcher.matches(use_lookahead_pruning=True), None) partial_mapping = partial_match.pattern_node_to_matched_graph_node # Try to extend the partial mapping, we expect a semantic infeasibility runtime error second_matcher = altered_perception_pattern.matcher( perception, match_mode=MatchMode.OBJECT) # The partial mapping (obtained from first matcher with original perception graph) # syntactically doesn't match the one in the altered version (second matcher with altered graph) with pytest.raises(RuntimeError): first( second_matcher.matches(initial_partial_match=partial_mapping, use_lookahead_pruning=True), None, )
def test_semantically_infeasible_partial_match(): """ Tests whether semantic feasibility works as intended """ target_object = BOX # Create train and test templates for the target objects train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) perceptual_representation = only(train_curriculum.instances())[2] # Original perception graph perception = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) whole_perception_pattern = PerceptionGraphPattern.from_graph( perception).perception_graph_pattern # Create an altered perception graph we remove the color node altered_perception_digraph = perception.copy_as_digraph() nodes_to_remove = [] edges = [] different_nodes = [] for node in perception.copy_as_digraph().nodes: # If we find a color node, we make it black if isinstance(node, tuple) and isinstance(node[0], RgbColorPerception): new_node = (RgbColorPerception(0, 0, 0), node[1]) # Get edge information for edge in perception.copy_as_digraph().edges(data=True): if edge[0] == node: edges.append((new_node, edge[1], edge[2])) if edge[1] == node: edges.append((edge[0], new_node, edge[2])) nodes_to_remove.append(node) different_nodes.append(new_node) # remove original node altered_perception_digraph.remove_nodes_from(nodes_to_remove) # add new nodes for node in different_nodes: altered_perception_digraph.add_node(node) # add edge information for edge in edges: altered_perception_digraph.add_edge(edge[0], edge[1]) for k, v in edge[2].items(): altered_perception_digraph[edge[0]][edge[1]][k] = v altered_perception_pattern = PerceptionGraphPattern.from_graph( PerceptionGraph(altered_perception_digraph)).perception_graph_pattern partial_digraph = altered_perception_pattern.copy_as_digraph() partial_digraph.remove_nodes_from([ node for node in partial_digraph.nodes if isinstance(node, IsColorNodePredicate) ]) # Start the matching process, get a partial match matcher = whole_perception_pattern.matcher(perception, match_mode=MatchMode.OBJECT) partial_match: PerceptionGraphPatternMatch = first( matcher.matches(use_lookahead_pruning=True)) partial_mapping = partial_match.pattern_node_to_matched_graph_node # Try to extend the partial mapping, we expect a semantic infeasibility runtime error second_matcher = whole_perception_pattern.matcher( PerceptionGraph(altered_perception_digraph), match_mode=MatchMode.OBJECT) # The partial mapping (obtained from first matcher with original perception graph) # semantically doesn't match the one in the altered version (second matcher with altered graph) with pytest.raises(RuntimeError): first( second_matcher.matches(initial_partial_match=partial_mapping, use_lookahead_pruning=True), None, )
def test_last_failed_pattern_node(): """ Tests whether `MatchFailure` can find the correct node. """ target_object = BOX # Create train and test templates for the target objects train_obj_object = object_variable("obj-with-color", target_object) obj_template = Phase1SituationTemplate( "colored-obj-object", salient_object_variables=[train_obj_object]) template = all_possible(obj_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY) train_curriculum = phase1_instances("all obj situations", situations=template) for (_, _, perceptual_representation) in train_curriculum.instances(): # Original perception graph perception = graph_without_learner( PerceptionGraph.from_frame(perceptual_representation.frames[0])) # Original perception pattern whole_perception_pattern = PerceptionGraphPattern.from_graph( perception).perception_graph_pattern # Create an altered perception graph we replace the color node altered_perception_digraph = perception.copy_as_digraph() nodes_to_remove = [] edges = [] different_nodes = [] for node in perception.copy_as_digraph().nodes: # If we find a color node, we make it black if isinstance(node, tuple) and isinstance(node[0], RgbColorPerception): new_node = (RgbColorPerception(0, 0, 0), 42) # Get edge information for edge in perception.copy_as_digraph().edges(data=True): if edge[0] == node: edges.append((new_node, edge[1], edge[2])) if edge[1] == node: edges.append((edge[0], new_node, edge[2])) nodes_to_remove.append(node) different_nodes.append(new_node) # add new nodes for node in different_nodes: altered_perception_digraph.add_node(node) # add edge information for edge in edges: altered_perception_digraph.add_edge(edge[0], edge[1]) for k, v in edge[2].items(): altered_perception_digraph[edge[0]][edge[1]][k] = v # remove original node altered_perception_digraph.remove_nodes_from(nodes_to_remove) # Start the matching process matcher = whole_perception_pattern.matcher( PerceptionGraph(altered_perception_digraph), match_mode=MatchMode.NON_OBJECT) match_or_failure = matcher.first_match_or_failure_info() assert isinstance(match_or_failure, PatternMatching.MatchFailure) assert isinstance(match_or_failure.last_failed_pattern_node, IsColorNodePredicate)