Repository: isi-vista/adam

Issue:
Add negation of relations in action perceptions

Comments:

Patch:
diff --git a/adam/ontology/phase1_ontology.py b/adam/ontology/phase1_ontology.py
index 33a828ac..0b7de430 100644
--- a/adam/ontology/phase1_ontology.py
+++ b/adam/ontology/phase1_ontology.py
@@ -832,13 +832,8 @@ _PUT_ACTION_DESCRIPTION = ActionDescription(
         SituationRelation(IN_REGION, _PUT_THEME, _CONTACTING_MANIPULATOR),
         # TODO: that theme is not already located in GOAL
         SituationRelation(PART_OF, _PUT_MANIPULATOR, _PUT_AGENT),
-        SituationRelation(CONTACTS, _PUT_MANIPULATOR, _PUT_THEME),
-        SituationRelation(SUPPORTS, _PUT_MANIPULATOR, _PUT_THEME),
     ],
     postconditions=[
-        # TODO: that theme is located in GOAL
-        # SituationRelation(CONTACTS, _PUT_MANIPULATOR, _PUT_THEME, negated=True),
-        # SituationRelation(SUPPORTS, _PUT_MANIPULATOR, _PUT_THEME, negated=True),
         SituationRelation(IN_REGION, _PUT_THEME, _CONTACTING_MANIPULATOR, negated=True),
         SituationRelation(IN_REGION, _PUT_THEME, _PUT_GOAL),
     ],
diff --git a/adam/perception/high_level_semantics_situation_to_developmental_primitive_perception.py b/adam/perception/high_level_semantics_situation_to_developmental_primitive_perception.py
index 35b62f9a..e7d5ac48 100644
--- a/adam/perception/high_level_semantics_situation_to_developmental_primitive_perception.py
+++ b/adam/perception/high_level_semantics_situation_to_developmental_primitive_perception.py
@@ -417,9 +417,19 @@ class _PerceptionGeneration:
                 arg2=perception_2,
             )
 
-            # TODO: Implement negation issue #121
             if not condition.negated:
                 relations.append(relation_perception)
+            else:
+                # Remove the relation from already known relations
+                relations = [
+                    relation
+                    for relation in relations
+                    if not (
+                        relation.relation_type == condition.relation_type
+                        and relation.arg1 == perception_1
+                        and relation.arg2 == perception_2
+                    )
+                ]
 
         return immutableset(relations)
 


Test patch:
diff --git a/tests/perception/high_level_semantics_situation_to_developmental_primitive_perception_test.py b/tests/perception/high_level_semantics_situation_to_developmental_primitive_perception_test.py
index f67ff6ed..97d3388d 100644
--- a/tests/perception/high_level_semantics_situation_to_developmental_primitive_perception_test.py
+++ b/tests/perception/high_level_semantics_situation_to_developmental_primitive_perception_test.py
@@ -153,18 +153,39 @@ def test_person_put_ball_on_table():
     # assert we generate at least some relations in each frame
     assert first_frame_relations
     assert second_frame_relations
+
     first_frame_relations_strings = {
-        f"{r.relation_type}({r.arg1}, {r.arg2})" for r in first_frame_relations
+        f"{r.relation_type}({r.arg1}, {r.arg2})" for r in perception.frames[0].relations
     }
     second_frame_relations_strings = {
-        f"{r.relation_type}({r.arg1}, {r.arg2})" for r in second_frame_relations
+        f"{r.relation_type}({r.arg1}, {r.arg2})" for r in perception.frames[1].relations
     }
     assert "smallerThan(ball_0, person_0)" in first_frame_relations_strings
     assert "partOf(hand_0, person_0)" in first_frame_relations_strings
-    assert "contacts(hand_0, ball_0)" in first_frame_relations_strings
-    assert "supports(hand_0, ball_0)" in first_frame_relations_strings
+    assert (
+        "in-region(ball_0, Region(reference_object=hand_0, "
+        "distance=Distance(name='exterior-but-in-contact'), direction=None))"
+        in first_frame_relations_strings
+    )
+
+    # continuing relations:
     assert "smallerThan(ball_0, person_0)" in second_frame_relations_strings
 
+    # new relations:
+    assert (
+        "in-region(ball_0, Region(reference_object=table_0, "
+        "distance=Distance(name='exterior-but-in-contact'), "
+        "direction=Direction(positive=True, relative_to_axis='vertical w.r.t. gravity')))"
+        in second_frame_relations_strings
+    )
+
+    # removed relations:
+    assert (
+        "in-region(ball_0, Region(reference_object=hand_0, "
+        "distance=Distance(name='exterior-but-in-contact'), direction=None))"
+        not in second_frame_relations_strings
+    )
+
 
 def _some_object_has_binary_property(
     perception_frame: DevelopmentalPrimitivePerceptionFrame, query_property: OntologyNode