Repository: isi-vista/adam

Issue:
Handle core vocabulary verb: Turn
Turn (~250): almost always with PP/ADVP (>200), majority of time with NP (~200)

Turn: almost all locational (over, on, round, off), sometimes with an NP (occasionally intransitive)

Comments:

Patch:
diff --git a/adam/curriculum/phase1_curriculum.py b/adam/curriculum/phase1_curriculum.py
index 49138e7d..66fc795d 100644
--- a/adam/curriculum/phase1_curriculum.py
+++ b/adam/curriculum/phase1_curriculum.py
@@ -68,6 +68,7 @@ from adam.ontology.phase1_ontology import (
     MOVE,
     MOVE_GOAL,
     contacts,
+    SPIN,
 )
 from adam.ontology.phase1_spatial_relations import (
     AWAY_FROM,
@@ -1001,6 +1002,50 @@ def _make_move_curriculum():
     )
 
 
+def _make_spin_curriculum():
+    self_turner = object_variable("self-spinner_0", THING, required_properties=[ANIMATE])
+
+    other_spinner = object_variable("spinner_0", THING, required_properties=[ANIMATE])
+    spinee = object_variable(
+        "spinee_0",
+        THING,
+        required_properties=[INANIMATE],
+        banned_properties=[IS_BODY_PART],
+    )
+
+    bare_spin_template = Phase1SituationTemplate(
+        "bare-spin",
+        salient_object_variables=[self_turner],
+        actions=[Action(SPIN, argument_roles_to_fillers=[(AGENT, self_turner)])],
+    )
+
+    transitive_spin_template = Phase1SituationTemplate(
+        "transitive-spin",
+        salient_object_variables=[other_spinner, spinee],
+        actions=[
+            Action(
+                SPIN, argument_roles_to_fillers=[(AGENT, other_spinner), (THEME, spinee)]
+            )
+        ],
+        constraining_relations=[bigger_than(other_spinner, spinee)],
+    )
+
+    return _phase1_instances(
+        "spin",
+        chain(
+            *[
+                sampled(
+                    situation,
+                    max_to_sample=25,
+                    chooser=_CHOOSER,
+                    ontology=GAILA_PHASE_1_ONTOLOGY,
+                )
+                for situation in (bare_spin_template, transitive_spin_template)
+            ]
+        ),
+    )
+
+
 GAILA_PHASE_1_CURRICULUM = [
     EACH_OBJECT_BY_ITSELF_SUB_CURRICULUM,
     OBJECTS_WITH_COLORS_SUB_CURRICULUM,
@@ -1021,6 +1066,7 @@ GAILA_PHASE_1_CURRICULUM = [
     _make_eat_curriculum(),
     _make_take_curriculum(),
     _make_move_curriculum(),
+    _make_spin_curriculum(),
 ]
 """
 One particular instantiation of the curriculum for GAILA Phase 1.
diff --git a/adam/language_specific/english/english_phase_1_lexicon.py b/adam/language_specific/english/english_phase_1_lexicon.py
index 323e1edd..70fee73e 100644
--- a/adam/language_specific/english/english_phase_1_lexicon.py
+++ b/adam/language_specific/english/english_phase_1_lexicon.py
@@ -52,7 +52,7 @@ from adam.ontology.phase1_ontology import (
     THROW,
     TRANSPARENT,
     TRUCK,
-    TURN,
+    SPIN,
     WATER,
     WHITE,
 )
@@ -106,7 +106,7 @@ GAILA_PHASE_1_ENGLISH_LEXICON = OntologyLexicon(
                 "give", VERB, verb_form_3SG_PRS="gives", properties=[ALLOWS_DITRANSITIVE]
             ),
         ),
-        (TURN, LexiconEntry("turn", VERB, verb_form_3SG_PRS="turns")),
+        (SPIN, LexiconEntry("spin", VERB, verb_form_3SG_PRS="spins")),
         (SIT, LexiconEntry("sit", VERB, verb_form_3SG_PRS="sits")),
         (DRINK, LexiconEntry("drink", VERB, verb_form_3SG_PRS="drinks")),
         (FALL, LexiconEntry("fall", VERB, verb_form_3SG_PRS="falls")),
diff --git a/adam/ontology/phase1_ontology.py b/adam/ontology/phase1_ontology.py
index bb88dc7e..0f43ed27 100644
--- a/adam/ontology/phase1_ontology.py
+++ b/adam/ontology/phase1_ontology.py
@@ -467,8 +467,8 @@ EAT = OntologyNode("eat")
 subtype(EAT, CONSUME)
 GIVE = OntologyNode("give", [TRANSFER_OF_POSSESSION])
 subtype(GIVE, ACTION)
-TURN = OntologyNode("turn")
-subtype(TURN, ACTION)
+SPIN = OntologyNode("spin")
+subtype(SPIN, ACTION)
 SIT = OntologyNode("sit")
 subtype(SIT, ACTION)
 DRINK = OntologyNode("drink")
@@ -1153,31 +1153,48 @@ _GIVE_ACTION_DESCRIPTION = ActionDescription(
     ],
 )
 
-_TURN_AGENT = SituationObject(THING, properties=[ANIMATE])
-_TURN_THEME = SituationObject(THING)
-_TURN_MANIPULATOR = SituationObject(THING, properties=[CAN_MANIPULATE_OBJECTS])
+_SPIN_AGENT = SituationObject(THING, properties=[ANIMATE])
+_SPIN_MANIPULATOR = SituationObject(THING, properties=[CAN_MANIPULATE_OBJECTS])
+
+
+def _make_spin_descriptions() -> Iterable[Tuple[OntologyNode, ActionDescription]]:
+    spin_theme = SituationObject(THING)
+
+    # intransitive
+    yield SPIN, ActionDescription(
+        frame=ActionDescriptionFrame({AGENT: _SPIN_AGENT}),
+        during=DuringAction(
+            objects_to_paths=[(_SPIN_AGENT, spin_around_primary_axis(_SPIN_AGENT))]
+        ),
+        asserted_properties=[
+            (_SPIN_AGENT, VOLITIONALLY_INVOLVED),
+            (_SPIN_AGENT, CAUSES_CHANGE),
+            (_SPIN_AGENT, UNDERGOES_CHANGE),
+        ],
+    )
+
+    # transitive
+    yield SPIN, ActionDescription(
+        frame=ActionDescriptionFrame({AGENT: _SPIN_AGENT, THEME: spin_theme}),
+        during=DuringAction(
+            objects_to_paths=[(spin_theme, spin_around_primary_axis(spin_theme))]
+        ),
+        asserted_properties=[
+            (_SPIN_AGENT, VOLITIONALLY_INVOLVED),
+            (_SPIN_AGENT, CAUSES_CHANGE),
+            (spin_theme, UNDERGOES_CHANGE),
+        ],
+    )
+
+
+def spin_around_primary_axis(object_):
+    return SpatialPath(
+        operator=None,
+        reference_object=object_,
+        reference_axis=Axis.primary_of(object_),
+        orientation_changed=True,
+    )
 
-_TURN_ACTION_DESCRIPTION = ActionDescription(
-    frame=ActionDescriptionFrame({AGENT: _TURN_AGENT, THEME: _TURN_THEME}),
-    during=DuringAction(
-        objects_to_paths=[
-            (
-                _TURN_THEME,
-                SpatialPath(
-                    operator=None,
-                    reference_object=_TURN_THEME,
-                    reference_axis=Axis.primary_of(_TURN_THEME),
-                    orientation_changed=True,
-                ),
-            )
-        ]
-    ),
-    asserted_properties=[
-        (_TURN_AGENT, VOLITIONALLY_INVOLVED),
-        (_TURN_AGENT, CAUSES_CHANGE),
-        (_TURN_THEME, UNDERGOES_CHANGE),
-    ],
-)
 
 SIT_THING_SAT_ON = SituationObject(THING, debug_handle="thing-sat-on")
 SIT_GOAL = SituationObject(THING, debug_handle="sit-goal")  # really a region
@@ -1445,7 +1462,6 @@ _ACTIONS_TO_DESCRIPTIONS = [
     (GIVE, _GIVE_ACTION_DESCRIPTION),
     (TAKE, _TAKE_ACTION_DESCRIPTION),
     (EAT, _EAT_ACTION_DESCRIPTION),
-    (TURN, _TURN_ACTION_DESCRIPTION),
     (FALL, _FALL_ACTION_DESCRIPTION),
     (THROW, _THROW_ACTION_DESCRIPTION),
     (FLY, _FLY_ACTION_DESCRIPTION),
@@ -1456,6 +1472,7 @@ _ACTIONS_TO_DESCRIPTIONS.extend(_make_jump_description())
 _ACTIONS_TO_DESCRIPTIONS.extend(_make_drink_description())
 _ACTIONS_TO_DESCRIPTIONS.extend(_make_sit_action_descriptions())
 _ACTIONS_TO_DESCRIPTIONS.extend(_make_move_descriptions())
+_ACTIONS_TO_DESCRIPTIONS.extend(_make_spin_descriptions())
 
 GAILA_PHASE_1_ONTOLOGY = Ontology(
     "gaila-phase-1",


Test patch:
diff --git a/tests/curriculum/phase1_curriculum_test.py b/tests/curriculum/phase1_curriculum_test.py
index a755b1e8..08ebf813 100644
--- a/tests/curriculum/phase1_curriculum_test.py
+++ b/tests/curriculum/phase1_curriculum_test.py
@@ -12,6 +12,7 @@ from adam.curriculum.phase1_curriculum import (
     _make_put_curriculum,
     _make_take_curriculum,
     _make_move_curriculum,
+    _make_spin_curriculum,
 )
 
 
@@ -70,3 +71,7 @@ def test_take():
 
 def test_move():
     _test_curriculum(_make_move_curriculum())
+
+
+def test_spin():
+    _test_curriculum(_make_spin_curriculum())