From 2e88e221d4e5507d94b5b6db5862634f378016b1 Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Mon, 20 Jul 2020 17:23:07 -0400 Subject: [PATCH 01/11] Add quantification semantics --- adam/learner/integrated_learner.py | 138 ++++++++--------------------- adam/semantics.py | 119 ++++++++++++++++++++++++- 2 files changed, 153 insertions(+), 104 deletions(-) diff --git a/adam/learner/integrated_learner.py b/adam/learner/integrated_learner.py index c4edbe6f5..9206e95c5 100644 --- a/adam/learner/integrated_learner.py +++ b/adam/learner/integrated_learner.py @@ -3,7 +3,6 @@ from itertools import chain, combinations from pathlib import Path from typing import AbstractSet, Iterable, Iterator, Mapping, Optional, Tuple, List -from more_itertools import flatten, one from adam.language import LinguisticDescription, TokenSequenceLinguisticDescription from adam.language_specific.english import ENGLISH_BLOCK_DETERMINERS @@ -14,7 +13,7 @@ PerceptionSemanticAlignment, ) from adam.learner.language_mode import LanguageMode -from adam.learner.surface_templates import MASS_NOUNS, SLOT1 +from adam.learner.surface_templates import MASS_NOUNS, SLOT1, SurfaceTemplate from adam.learner.template_learner import TemplateLearner from adam.perception import PerceptualRepresentation from adam.perception.developmental_primitive_perception import ( @@ -23,7 +22,7 @@ from adam.perception.perception_graph import PerceptionGraph from adam.semantics import ( ActionSemanticNode, - AttributeSemanticNode, + LearnerSemantics, ObjectSemanticNode, RelationSemanticNode, SemanticNode, @@ -31,13 +30,7 @@ ) from attr import attrib, attrs from attr.validators import instance_of, optional -from immutablecollections import ( - ImmutableSet, - ImmutableSetMultiDict, - immutabledict, - immutablesetmultidict, -) -from immutablecollections.converter_utils import _to_immutableset +from immutablecollections import immutabledict class LanguageLearnerNew: @@ -51,6 +44,22 @@ def observe( pass +class NumberLearner: + """ + A strategy for learning how number is expressed in a human language. + + We assume the learner has built-in awareness that "number" is a concept + which will be expressed in human language, + and is on the lookout to figure out *how* it is expressed. + """ + + def surface_template_for_count(self, count: int) -> Optional[SurfaceTemplate]: + """ + Given the number of instances of some object, get the `SurfaceTemplate` used to + describe its number information, if known. + """ + + @attrs class IntegratedTemplateLearner( TopLevelLanguageLearner[ @@ -74,6 +83,9 @@ class IntegratedTemplateLearner( action_learner: Optional[TemplateLearner] = attrib( validator=optional(instance_of(TemplateLearner)), default=None ) + number_learner: Optional[NumberLearner] = attrib( + validator=optional(instance_of(NumberLearner)), default=None + ) _max_attributes_per_word: int = attrib(validator=instance_of(int), default=3) @@ -145,7 +157,6 @@ def observe( def describe( self, perception: PerceptualRepresentation[DevelopmentalPrimitivePerceptionFrame] ) -> Mapping[LinguisticDescription, float]: - perception_graph = self._extract_perception_graph(perception) cur_description_state = PerceptionSemanticAlignment.create_unaligned( @@ -175,15 +186,22 @@ def _linguistic_descriptions_from_semantics( ) -> Mapping[LinguisticDescription, float]: learner_semantics = LearnerSemantics.from_nodes(semantic_nodes) + ret: List[Tuple[Tuple[str, ...], float]] = [] + ret.extend(self._to_tokens(learner_semantics)) + return immutabledict( + (TokenSequenceLinguisticDescription(tokens), score) for (tokens, score) in ret + ) + + def _to_tokens( + self, semantics: LearnerSemantics + ) -> Iterable[Tuple[Tuple[str, ...], float]]: ret = [] if self.action_learner: ret.extend( [ (action_tokens, 1.0) - for action in learner_semantics.actions - for action_tokens in self._instantiate_action( - action, learner_semantics - ) + for action in semantics.actions + for action_tokens in self._instantiate_action(action, semantics) # ensure we have some way of expressing this action if self.action_learner.templates_for_concept(action.concept) ] @@ -193,10 +211,8 @@ def _linguistic_descriptions_from_semantics( ret.extend( [ (relation_tokens, 1.0) - for relation in learner_semantics.relations - for relation_tokens in self._instantiate_relation( - relation, learner_semantics - ) + for relation in semantics.relations + for relation_tokens in self._instantiate_relation(relation, semantics) # ensure we have some way of expressing this relation if self.relation_learner.templates_for_concept(relation.concept) ] @@ -204,15 +220,13 @@ def _linguistic_descriptions_from_semantics( ret.extend( [ (object_tokens, 1.0) - for object_ in learner_semantics.objects - for object_tokens in self._instantiate_object(object_, learner_semantics) + for object_ in semantics.objects + for object_tokens in self._instantiate_object(object_, semantics) # ensure we have some way of expressing this object if self.object_learner.templates_for_concept(object_.concept) ] ) - return immutabledict( - (TokenSequenceLinguisticDescription(tokens), score) for (tokens, score) in ret - ) + return ret def _add_determiners( self, object_node: ObjectSemanticNode, cur_string: Tuple[str, ...] @@ -353,79 +367,3 @@ def _init_sub_learners(self) -> List[TemplateLearner]: if self.action_learner: valid_sub_learners.append(self.action_learner) return valid_sub_learners - - -@attrs(frozen=True) -class LearnerSemantics: - """ - Represent's the learner's semantic (rather than perceptual) understanding of a situation. - - The learner is assumed to view the situation as a collection of *objects* which possess - *attributes*, have *relations* to one another, and serve as the arguments of *actions*. - """ - - objects: ImmutableSet[ObjectSemanticNode] = attrib(converter=_to_immutableset) - attributes: ImmutableSet[AttributeSemanticNode] = attrib(converter=_to_immutableset) - relations: ImmutableSet[RelationSemanticNode] = attrib(converter=_to_immutableset) - actions: ImmutableSet[ActionSemanticNode] = attrib(converter=_to_immutableset) - - objects_to_attributes: ImmutableSetMultiDict[ - ObjectSemanticNode, AttributeSemanticNode - ] = attrib(init=False) - objects_to_relation_in_slot1: ImmutableSetMultiDict[ - ObjectSemanticNode, RelationSemanticNode - ] = attrib(init=False) - objects_to_actions: ImmutableSetMultiDict[ - ObjectSemanticNode, ActionSemanticNode - ] = attrib(init=False) - - @staticmethod - def from_nodes(semantic_nodes: Iterable[SemanticNode]) -> "LearnerSemantics": - return LearnerSemantics( - objects=[ - node for node in semantic_nodes if isinstance(node, ObjectSemanticNode) - ], - attributes=[ - node for node in semantic_nodes if isinstance(node, AttributeSemanticNode) - ], - relations=[ - node for node in semantic_nodes if isinstance(node, RelationSemanticNode) - ], - actions=[ - node for node in semantic_nodes if isinstance(node, ActionSemanticNode) - ], - ) - - @objects_to_attributes.default - def _init_objects_to_attributes( - self - ) -> ImmutableSetMultiDict[ObjectSemanticNode, AttributeSemanticNode]: - return immutablesetmultidict( - (one(attribute.slot_fillings.values()), attribute) - for attribute in self.attributes - ) - - @objects_to_relation_in_slot1.default - def _init_objects_to_relations( - self - ) -> ImmutableSetMultiDict[ObjectSemanticNode, AttributeSemanticNode]: - return immutablesetmultidict( - flatten( - [ - (slot_filler, relation) - for slot_filler in relation.slot_fillings.values() - ] - for relation in self.relations - ) - ) - - @objects_to_actions.default - def _init_objects_to_actions( - self - ) -> ImmutableSetMultiDict[ObjectSemanticNode, AttributeSemanticNode]: - return immutablesetmultidict( - flatten( - [(slot_filler, action) for slot_filler in action.slot_fillings.values()] - for action in self.actions - ) - ) diff --git a/adam/semantics.py b/adam/semantics.py index 38d7f5e7e..3a898ee9e 100644 --- a/adam/semantics.py +++ b/adam/semantics.py @@ -4,14 +4,22 @@ Really this and `HighLevelSemanticsSituation` should somehow be refactored together, but it's not worth the trouble at this point. """ -from typing import Mapping +from typing import Iterable, Mapping +from more_itertools import flatten, one from typing_extensions import Protocol, runtime from attr import attrib, attrs -from attr.validators import deep_mapping, instance_of -from immutablecollections import ImmutableDict, immutabledict -from immutablecollections.converter_utils import _to_immutabledict +from attr.validators import deep_mapping, in_, instance_of +from immutablecollections import ( + ImmutableDict, + ImmutableSet, + ImmutableSetMultiDict, + immutabledict, + immutablesetmultidict, +) +from immutablecollections.converter_utils import _to_immutabledict, _to_immutableset +from vistautils.range import Range @runtime @@ -48,6 +56,16 @@ class ActionConcept(Concept): debug_string: str = attrib(validator=instance_of(str)) +@attrs(frozen=True, eq=False) +class NumberConcept(Concept): + """ + The concept of some number of things. + """ + + number: int = attrib(validator=in_(Range.at_least(1))) + debug_string: str = attrib(validator=instance_of(str)) + + GROUND_OBJECT_CONCEPT = ObjectConcept("ground") @@ -135,3 +153,96 @@ class ActionSemanticNode(SemanticNode): # def __attrs_post_init__(self) -> None: # for template in self.templates: # check_arg(template.num_slots >= 1) + + +class QuantificationSemanticNode(SemanticNode): + concept: NumberConcept = attrib(validator=instance_of(NumberConcept)) + slot_fillings: ImmutableDict[SyntaxSemanticsVariable, "ObjectSemanticNode"] = attrib( + converter=_to_immutabledict, + validator=deep_mapping( + instance_of(SyntaxSemanticsVariable), instance_of(ObjectSemanticNode) + ), + ) + + def __attrs_post_init__(self) -> None: + if len(self.slot_fillings) != 1: + raise RuntimeError( + f"QuantificationSemanticNode should have only one slot but got " + f"{self.slot_fillings}" + ) + + +@attrs(frozen=True) +class LearnerSemantics: + """ + Represent's the learner's semantic (rather than perceptual) understanding of a situation. + + The learner is assumed to view the situation as a collection of *objects* which possess + *attributes*, have *relations* to one another, and serve as the arguments of *actions*. + """ + + objects: ImmutableSet[ObjectSemanticNode] = attrib(converter=_to_immutableset) + attributes: ImmutableSet[AttributeSemanticNode] = attrib(converter=_to_immutableset) + relations: ImmutableSet[RelationSemanticNode] = attrib(converter=_to_immutableset) + actions: ImmutableSet[ActionSemanticNode] = attrib(converter=_to_immutableset) + + objects_to_attributes: ImmutableSetMultiDict[ + ObjectSemanticNode, AttributeSemanticNode + ] = attrib(init=False) + objects_to_relation_in_slot1: ImmutableSetMultiDict[ + ObjectSemanticNode, RelationSemanticNode + ] = attrib(init=False) + objects_to_actions: ImmutableSetMultiDict[ + ObjectSemanticNode, ActionSemanticNode + ] = attrib(init=False) + + @staticmethod + def from_nodes(semantic_nodes: Iterable[SemanticNode]) -> "LearnerSemantics": + return LearnerSemantics( + objects=[ + node for node in semantic_nodes if isinstance(node, ObjectSemanticNode) + ], + attributes=[ + node for node in semantic_nodes if isinstance(node, AttributeSemanticNode) + ], + relations=[ + node for node in semantic_nodes if isinstance(node, RelationSemanticNode) + ], + actions=[ + node for node in semantic_nodes if isinstance(node, ActionSemanticNode) + ], + ) + + @objects_to_attributes.default + def _init_objects_to_attributes( + self + ) -> ImmutableSetMultiDict[ObjectSemanticNode, AttributeSemanticNode]: + return immutablesetmultidict( + (one(attribute.slot_fillings.values()), attribute) + for attribute in self.attributes + ) + + @objects_to_relation_in_slot1.default + def _init_objects_to_relations( + self + ) -> ImmutableSetMultiDict[ObjectSemanticNode, AttributeSemanticNode]: + return immutablesetmultidict( + flatten( + [ + (slot_filler, relation) + for slot_filler in relation.slot_fillings.values() + ] + for relation in self.relations + ) + ) + + @objects_to_actions.default + def _init_objects_to_actions( + self + ) -> ImmutableSetMultiDict[ObjectSemanticNode, AttributeSemanticNode]: + return immutablesetmultidict( + flatten( + [(slot_filler, action) for slot_filler in action.slot_fillings.values()] + for action in self.actions + ) + ) From 09f674712bf9c745a408ad5e7642cfdb829fc24c Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Wed, 22 Jul 2020 21:31:21 -0400 Subject: [PATCH 02/11] First stab at plural learning --- adam/axis.py | 5 +- adam/curriculum/__init__.py | 11 +- ...ttribute_constraining_action_curriculum.py | 21 +- adam/curriculum/curriculum_utils.py | 20 +- .../imprecise_descriptions_curriculum.py | 91 ++--- adam/curriculum/m6_curriculum.py | 27 +- adam/curriculum/phase1_curriculum.py | 62 ++-- adam/curriculum/phase2_curriculum.py | 57 ++- adam/curriculum/preposition_curriculum.py | 54 +-- adam/curriculum/pursuit_curriculum.py | 22 +- ...bs_with_dynamic_prepositions_curriculum.py | 109 +++--- adam/curriculum_to_html.py | 62 ++-- adam/debugging/intersect_patterns.py | 2 +- adam/experiment/__init__.py | 19 +- adam/experiment/experiment_utils.py | 6 +- adam/experiment/log_experiment.py | 60 +-- adam/experiment/observer.py | 9 +- adam/experiment/run_m13.py | 3 +- adam/experiment/run_m6.py | 3 +- adam/experiment/run_m9.py | 3 +- adam/experiment/run_object_restrictions.py | 3 +- adam/geon.py | 7 +- adam/language/__init__.py | 7 +- adam/language/dependency/__init__.py | 8 +- adam/language/language_generator/__init__.py | 9 +- adam/language/lexicon.py | 3 +- adam/language/ontology_dictionary.py | 7 +- adam/language_specific/__init__.py | 2 +- .../chinese/chinese_language_generator.py | 82 ++--- .../chinese/chinese_phase_1_lexicon.py | 22 +- .../chinese/chinese_phase_2_lexicon.py | 11 +- .../chinese/chinese_syntax.py | 7 +- adam/language_specific/english/__init__.py | 2 + .../english/english_language_generator.py | 56 +-- .../english/english_phase_1_lexicon.py | 18 +- .../english/english_phase_2_lexicon.py | 8 +- .../english/english_syntax.py | 7 +- adam/learner/__init__.py | 44 +-- adam/learner/attributes.py | 19 +- adam/learner/integrated_learner.py | 335 ++++++++++++++--- adam/learner/learner_utils.py | 50 +-- adam/learner/object_recognizer.py | 16 +- adam/learner/objects.py | 17 +- adam/learner/perception_graph_template.py | 6 +- adam/learner/prepositions.py | 9 +- adam/learner/pursuit.py | 18 +- adam/learner/quantifers.py | 342 ++++++++++++++++++ adam/learner/relations.py | 13 +- adam/learner/subset.py | 21 +- adam/learner/surface_templates.py | 8 +- adam/learner/template_learner.py | 59 ++- adam/learner/verbs.py | 19 +- adam/ontology/__init__.py | 3 +- adam/ontology/action_description.py | 9 +- adam/ontology/during.py | 7 +- adam/ontology/ontology.py | 28 +- adam/ontology/phase1_ontology.py | 12 +- adam/ontology/phase1_spatial_relations.py | 10 +- adam/ontology/phase2_ontology.py | 52 +-- adam/ontology/selectors.py | 5 +- adam/ontology/structural_schema.py | 9 +- adam/perception/__init__.py | 13 +- adam/perception/_matcher.py | 8 +- adam/perception/deprecated.py | 8 +- .../developmental_primitive_perception.py | 9 +- .../perception/perception_frame_difference.py | 9 +- adam/perception/perception_graph.py | 9 +- adam/relation_dsl.py | 1 - adam/remappable.py | 2 +- adam/semantics.py | 32 +- adam/situation/__init__.py | 21 +- .../high_level_semantics_situation.py | 12 +- adam/situation/templates/__init__.py | 14 +- .../templates/phase1_situation_templates.py | 20 +- adam/situation/templates/phase1_templates.py | 10 +- adam/utils/networkx_utils.py | 7 +- adam/visualization/make_scenes.py | 87 ++--- adam/visualization/panda3d_interface.py | 43 ++- adam/visualization/positioning.py | 35 +- adam/visualization/render_curriculum.py | 17 +- adam/visualization/utils.py | 49 ++- setup.py | 1 - ...ute_constraining_action_curriculum_test.py | 13 +- .../imprecise_descriptions_curriculum_test.py | 27 +- tests/curriculum/phase1_curriculum_test.py | 22 +- tests/curriculum/phase2_curriculum_test.py | 3 +- .../prepositions_curriculum_test.py | 39 +- tests/curriculum/pursuit_curriculum_test.py | 5 +- ...th_dynamic_prepositions_curriculum_test.py | 21 +- tests/experiment_test.py | 2 +- .../language_generation_test.py | 3 +- .../test_chinese_language_generator.py | 98 +++-- .../chinese/test_chinese_syntax.py | 28 +- .../test_english_language_generator.py | 56 +-- tests/learner/__init__.py | 5 +- tests/learner/object_learner_test.py | 22 +- .../pursuit_preposition_learner_test.py | 29 +- .../learner/subset_attribute_learner_test.py | 34 +- .../subset_preposition_learner_test.py | 8 +- tests/learner/subset_verb_learner_test.py | 111 ++---- tests/learner/test_integrated_learner.py | 5 +- tests/learner/test_object_recognizer.py | 8 +- tests/ontology/ontology_test.py | 5 +- tests/ontology/selectors_test.py | 3 +- ...developmental_primitive_perception_test.py | 4 +- ...developmental_primitive_perception_test.py | 10 +- tests/perception/marr_test.py | 3 +- tests/perception/perception_graph_test.py | 10 +- tests/pipeline_test.py | 3 +- .../high_level_semantics_situation.py | 10 +- .../templates/phase1_template_test.py | 29 +- tests/visualization/make_scenes_test.py | 9 +- tests/visualization/panda_interface_test.py | 1 + tests/visualization/positioning_test.py | 37 +- 114 files changed, 1810 insertions(+), 1276 deletions(-) create mode 100644 adam/learner/quantifers.py diff --git a/adam/axis.py b/adam/axis.py index 779652f8f..62af66357 100644 --- a/adam/axis.py +++ b/adam/axis.py @@ -1,7 +1,6 @@ -from attr import attrs, attrib, evolve -from attr.validators import instance_of - from adam.utilities import sign +from attr import attrib, attrs, evolve +from attr.validators import instance_of @attrs(frozen=True, slots=True, repr=False, eq=False) diff --git a/adam/curriculum/__init__.py b/adam/curriculum/__init__.py index 11b9cb8b1..3ae1e0c77 100644 --- a/adam/curriculum/__init__.py +++ b/adam/curriculum/__init__.py @@ -2,21 +2,20 @@ Code to specify what is shown to `LanguageLearner`\ s and in what order. """ from abc import ABC, abstractmethod -from typing import Generic, Iterable, Optional, Tuple, List - -from attr import attrib, attrs -from attr.validators import instance_of -from immutablecollections.converter_utils import _to_tuple +from typing import Generic, Iterable, Optional, Tuple from adam.language import LinguisticDescriptionT from adam.language.language_generator import LanguageGenerator -from adam.situation import SituationT from adam.perception import ( PerceptionT, PerceptualRepresentation, PerceptualRepresentationGenerator, ) from adam.random_utils import SequenceChooser +from adam.situation import SituationT +from attr import attrib, attrs +from attr.validators import instance_of +from immutablecollections.converter_utils import _to_tuple class InstanceGroup(ABC, Generic[SituationT, LinguisticDescriptionT, PerceptionT]): diff --git a/adam/curriculum/attribute_constraining_action_curriculum.py b/adam/curriculum/attribute_constraining_action_curriculum.py index 5999cabf4..eb7082d6b 100644 --- a/adam/curriculum/attribute_constraining_action_curriculum.py +++ b/adam/curriculum/attribute_constraining_action_curriculum.py @@ -1,26 +1,25 @@ from itertools import chain from typing import Optional, Sequence -from adam.language.language_generator import LanguageGenerator -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.language.dependency import LinearizedDependencyTree -from adam.ontology import IS_SPEAKER, IS_ADDRESSEE from adam.curriculum.curriculum_utils import ( - Phase1InstanceGroup, - standard_object, - phase1_instances, PHASE1_CHOOSER_FACTORY, + Phase1InstanceGroup, make_noise_objects, + phase1_instances, + standard_object, ) from adam.curriculum.phase1_curriculum import make_eat_template -from adam.ontology import THING +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, THING from adam.ontology.phase1_ontology import ( - PERSON, + ANIMATE, EDIBLE, - NONHUMAN_ANIMAL, GAILA_PHASE_1_ONTOLOGY, - ANIMATE, + NONHUMAN_ANIMAL, + PERSON, ) +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_templates import sampled diff --git a/adam/curriculum/curriculum_utils.py b/adam/curriculum/curriculum_utils.py index d50423bfd..b38eb4da3 100644 --- a/adam/curriculum/curriculum_utils.py +++ b/adam/curriculum/curriculum_utils.py @@ -1,21 +1,20 @@ -from typing import Iterable, Union, Optional -from adam.ontology import IS_SPEAKER, IS_ADDRESSEE -from immutablecollections import immutableset -from adam.language.language_generator import LanguageGenerator +from typing import Iterable, Optional, Union + +from adam.curriculum import GeneratedFromSituationsInstanceGroup, InstanceGroup from adam.language.dependency import LinearizedDependencyTree -from adam.curriculum import InstanceGroup, GeneratedFromSituationsInstanceGroup +from adam.language.language_generator import LanguageGenerator from adam.language_specific.english.english_language_generator import ( GAILA_PHASE_1_LANGUAGE_GENERATOR, GAILA_PHASE_2_LANGUAGE_GENERATOR, ) -from adam.ontology import OntologyNode +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, OntologyNode from adam.ontology.phase1_ontology import ( GROUND, INANIMATE_OBJECT, IS_BODY_PART, - THING, - LIQUID, LEARNER, + LIQUID, + THING, ) from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -27,10 +26,11 @@ from adam.random_utils import RandomChooser from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_templates import ( - object_variable, - TemplatePropertyVariable, TemplateObjectVariable, + TemplatePropertyVariable, + object_variable, ) +from immutablecollections import immutableset GROUND_OBJECT_TEMPLATE = object_variable("ground", GROUND) PHASE1_CHOOSER_FACTORY = lambda: RandomChooser.for_seed(0) # noqa: E731 diff --git a/adam/curriculum/imprecise_descriptions_curriculum.py b/adam/curriculum/imprecise_descriptions_curriculum.py index 8224f1a8a..e3a31d0b2 100644 --- a/adam/curriculum/imprecise_descriptions_curriculum.py +++ b/adam/curriculum/imprecise_descriptions_curriculum.py @@ -1,81 +1,82 @@ from itertools import chain -from typing import Sequence, Optional -from immutablecollections import immutableset +from typing import Optional, Sequence + from more_itertools import flatten -from adam.language.language_generator import LanguageGenerator -from adam.language.dependency import LinearizedDependencyTree + from adam.curriculum.curriculum_utils import ( - Phase1InstanceGroup, PHASE1_CHOOSER_FACTORY, - phase1_instances, - standard_object, + Phase1InstanceGroup, learner_template_factory, make_noise_objects, + phase1_instances, + standard_object, ) -from adam.ontology import IS_SPEAKER, IS_ADDRESSEE from adam.curriculum.phase1_curriculum import ( + bare_fly, + bare_move_template, + fall_on_ground_template, + falling_template, + intransitive_roll, + make_jump_template, make_pass_template, + make_push_templates, + make_take_template, + make_walk_run_template, throw_on_ground_template, throw_template, - throw_up_down_template, throw_to_template, - bare_move_template, + throw_up_down_template, transitive_move_template, - make_jump_template, - intransitive_roll, - transitive_roll_with_surface, transitive_roll, - bare_fly, - fall_on_ground_template, - falling_template, - make_take_template, - make_push_templates, - make_walk_run_template, + transitive_roll_with_surface, ) +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator from adam.language_specific.english.english_language_generator import ( USE_ADVERBIAL_PATH_MODIFIER, USE_VERTICAL_MODIFIERS, ) -from adam.ontology import THING +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, THING from adam.ontology.phase1_ontology import ( - GAILA_PHASE_1_ONTOLOGY, + AGENT, ANIMATE, - INANIMATE, + AWAY_FROM, + BABY, + BIRD, BOX, - FAST, - HARD_FORCE, - SOFT_FORCE, - SLOW, - SELF_MOVING, - CAN_JUMP, - ROLLABLE, CAN_HAVE_THINGS_RESTING_ON_THEM, - BIRD, - bigger_than, - EAT, - AGENT, - PATIENT, + CAN_JUMP, + CHAIR, COOKIE, - WATERMELON, - TOWARD, - AWAY_FROM, - MOM, - LEARNER, - DOG, - BABY, DAD, - CHAIR, + DOG, + EAT, + FAST, + GAILA_PHASE_1_ONTOLOGY, + HARD_FORCE, + INANIMATE, + LEARNER, + MOM, + PATIENT, + ROLLABLE, + SELF_MOVING, + SLOW, + SOFT_FORCE, + SPIN, TABLE, THEME, - SPIN, + TOWARD, + WATERMELON, + bigger_than, ) from adam.situation import Action, SituationObject from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_templates import ( - sampled, - TemplateObjectVariable, Phase1SituationTemplate, + TemplateObjectVariable, + sampled, ) +from immutablecollections import immutableset BOOL_SET = immutableset([True, False]) diff --git a/adam/curriculum/m6_curriculum.py b/adam/curriculum/m6_curriculum.py index 8b00698fd..286ba82e3 100644 --- a/adam/curriculum/m6_curriculum.py +++ b/adam/curriculum/m6_curriculum.py @@ -9,21 +9,17 @@ """ import random as r from itertools import chain -from typing import Sequence, List, Optional +from typing import List, Optional, Sequence from more_itertools import flatten -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.language.language_generator import LanguageGenerator -from adam.language.dependency import LinearizedDependencyTree - from adam.curriculum import ExplicitWithSituationInstanceGroup from adam.curriculum.curriculum_utils import ( PHASE1_CHOOSER_FACTORY, Phase1InstanceGroup, + make_noise_objects, phase1_instances, standard_object, - make_noise_objects, ) from adam.curriculum.phase1_curriculum import ( _make_each_object_by_itself_curriculum, @@ -37,8 +33,11 @@ _over_template, _under_template, ) +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator from adam.ontology import IS_ADDRESSEE, IS_SPEAKER from adam.ontology.phase1_ontology import ( + BABY, BALL, BIRD, BOOK, @@ -47,26 +46,26 @@ CHAIR, COOKIE, CUP, + DAD, + DOG, + DOOR, GAILA_PHASE_1_ONTOLOGY, + HAND, HAT, + HEAD, HOUSE, + JUICE, LEARNER, + MILK, MOM, TABLE, TRUCK, - DAD, - BABY, WATER, - HAND, - DOG, - MILK, - HEAD, - JUICE, - DOOR, ) from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import ( GAILA_M6_PERCEPTION_GENERATOR, ) +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_templates import sampled M6_PREPOSITION_CURRICULUM_SMALL_OBJECTS = [BALL, CUP, BOX, HAT, BOOK, COOKIE, BIRD] diff --git a/adam/curriculum/phase1_curriculum.py b/adam/curriculum/phase1_curriculum.py index 4ff7a5ca2..6614c1b15 100644 --- a/adam/curriculum/phase1_curriculum.py +++ b/adam/curriculum/phase1_curriculum.py @@ -1,22 +1,11 @@ """ Curricula for DARPA GAILA Phase 1 """ +from itertools import chain from math import ceil +from typing import Dict, Iterable, List, Optional, Sequence -from adam.language.language_generator import LanguageGenerator -from adam.language.dependency import LinearizedDependencyTree -from itertools import chain -from typing import Iterable, Sequence, List, Dict, Optional -from adam.language_specific.english.english_language_generator import ( - GAILA_PHASE_1_LANGUAGE_GENERATOR, - GAILA_PHASE_2_LANGUAGE_GENERATOR, -) -from adam.language_specific.chinese.chinese_language_generator import ( - GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, - GAILA_PHASE_2_CHINESE_LANGUAGE_GENERATOR, -) -from immutablecollections import immutableset -from more_itertools import flatten, first +from more_itertools import first, flatten from adam.axes import AxesInfo, FacingAddresseeAxis, HorizontalAxisOfObject from adam.curriculum import ExplicitWithSituationInstanceGroup @@ -24,32 +13,43 @@ GROUND_OBJECT_TEMPLATE, PHASE1_CHOOSER_FACTORY, Phase1InstanceGroup, + make_noise_objects, phase1_instances, standard_object, - make_noise_objects, ) from adam.language import TokenSequenceLinguisticDescription +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator +from adam.language_specific.chinese.chinese_language_generator import ( + GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, + GAILA_PHASE_2_CHINESE_LANGUAGE_GENERATOR, +) from adam.language_specific.english.english_language_generator import ( + ATTRIBUTES_AS_X_IS_Y, + GAILA_PHASE_1_LANGUAGE_GENERATOR, + GAILA_PHASE_2_LANGUAGE_GENERATOR, + IGNORE_COLORS, IGNORE_HAS_AS_VERB, PREFER_DITRANSITIVE, USE_ADVERBIAL_PATH_MODIFIER, - ATTRIBUTES_AS_X_IS_Y, - IGNORE_COLORS, ) -from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, THING, OntologyNode +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, OntologyNode, THING from adam.ontology.during import DuringAction from adam.ontology.ontology import Ontology -from adam.ontology.phase1_spatial_relations import PathOperator from adam.ontology.phase1_ontology import ( AGENT, ANIMATE, + BABY, + BALL, BIRD, BOX, CAN_BE_SAT_ON_BY_PEOPLE, CAN_HAVE_THINGS_RESTING_ON_THEM, CAN_JUMP, + CAR, COME, - HARD_FORCE, + DAD, + DOG, DRINK, DRINK_CONTAINER_AUX, EAT, @@ -57,12 +57,13 @@ FALL, FLY, GAILA_PHASE_1_ONTOLOGY, - WALK_SURFACE_AUXILIARY, GIVE, GOAL, GROUND, + HARD_FORCE, HAS_SPACE_UNDER, HOLLOW, + HOUSE, INANIMATE, INANIMATE_OBJECT, IS_BODY_PART, @@ -70,8 +71,10 @@ JUMP_INITIAL_SUPPORTER_AUX, LEARNER, LIQUID, + MOM, MOVE, MOVE_GOAL, + PASS, PATIENT, PERSON, PERSON_CAN_HAVE, @@ -92,6 +95,9 @@ THROW, THROW_GOAL, TRANSFER_OF_POSSESSION, + TRUCK, + WALK, + WALK_SURFACE_AUXILIARY, bigger_than, contacts, far, @@ -100,16 +106,6 @@ is_recognized_particular, near, on, - PASS, - BABY, - TRUCK, - CAR, - DOG, - MOM, - DAD, - HOUSE, - BALL, - WALK, strictly_over, ) from adam.ontology.phase1_spatial_relations import ( @@ -118,6 +114,7 @@ EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_UP, PROXIMAL, + PathOperator, Region, SpatialPath, TO, @@ -130,6 +127,7 @@ from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_situation_templates import ( _fly_over_template, + _fly_under_template, _go_in_template, _go_to_template, _go_under_template, @@ -137,7 +135,6 @@ _put_in_template, _put_on_body_part_template, _put_on_template, - _fly_under_template, ) from adam.situation.templates.phase1_templates import ( Phase1SituationTemplate, @@ -148,6 +145,7 @@ object_variable, sampled, ) +from immutablecollections import immutableset # TODO: fix https://github.com/isi-vista/adam/issues/917 which causes us to have to specify that we don't wish to include ME_HACK and YOU_HACK in our curriculum design diff --git a/adam/curriculum/phase2_curriculum.py b/adam/curriculum/phase2_curriculum.py index 14c2bff60..8b835dfcb 100644 --- a/adam/curriculum/phase2_curriculum.py +++ b/adam/curriculum/phase2_curriculum.py @@ -2,71 +2,68 @@ Additions for the Curricula for DARPA GAILA Phase 2 """ -from adam.ontology import IS_SPEAKER, IS_ADDRESSEE import random - from itertools import chain -from typing import Sequence, Optional +from typing import Optional, Sequence from more_itertools import flatten -from adam.language.language_generator import LanguageGenerator -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.language.dependency import LinearizedDependencyTree from adam.curriculum.curriculum_utils import ( PHASE1_CHOOSER_FACTORY, Phase1InstanceGroup, - standard_object, - phase2_instances, - phase1_instances, make_noise_objects, + phase1_instances, + phase2_instances, + standard_object, ) from adam.curriculum.imprecise_descriptions_curriculum import ( + make_eat_big_small_curriculum, make_imprecise_temporal_descriptions, - make_subtle_verb_distinctions_curriculum, make_spin_tall_short_curriculum, - make_eat_big_small_curriculum, + make_subtle_verb_distinctions_curriculum, ) from adam.curriculum.phase1_curriculum import ( - _make_plural_objects_curriculum, - _make_pass_curriculum, _make_generic_statements_curriculum, _make_part_whole_curriculum, + _make_pass_curriculum, + _make_plural_objects_curriculum, _make_transitive_roll_curriculum, - build_gaila_phase1_object_curriculum, - build_gaila_plurals_curriculum, - build_gaila_phase1_attribute_curriculum, build_gaila_generics_curriculum, + build_gaila_phase1_attribute_curriculum, + build_gaila_phase1_object_curriculum, build_gaila_phase1_verb_curriculum, + build_gaila_plurals_curriculum, ) from adam.curriculum.preposition_curriculum import make_prepositions_curriculum from adam.curriculum.verbs_with_dynamic_prepositions_curriculum import ( make_verb_with_dynamic_prepositions_curriculum, ) +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator from adam.language_specific.english.english_language_generator import IGNORE_COLORS -from adam.ontology import THING +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, THING from adam.ontology.phase1_ontology import ( + AGENT, + ANIMATE, CHAIR, CUP, - ANIMATE, - INANIMATE_OBJECT, - HOLLOW, + DRINK, + DRINK_CONTAINER_AUX, GAILA_PHASE_1_ONTOLOGY, - SIT, - AGENT, - SIT_GOAL, - SIT_THING_SAT_ON, GOAL, - DRINK, + HOLLOW, + INANIMATE_OBJECT, LIQUID, PERSON, + SIT, + SIT_GOAL, + SIT_THING_SAT_ON, THEME, - DRINK_CONTAINER_AUX, ) from adam.ontology.phase1_spatial_relations import ( - Region, - GRAVITATIONAL_UP, EXTERIOR_BUT_IN_CONTACT, + GRAVITATIONAL_UP, + Region, ) from adam.ontology.phase2_ontology import ( CHAIR_2, @@ -82,14 +79,16 @@ GAILA_PHASE_2_PERCEPTION_GENERATOR, ) from adam.situation import Action +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_situation_templates import _put_in_template from adam.situation.templates.phase1_templates import ( Phase1SituationTemplate, all_possible, - sampled, object_variable, + sampled, ) + # TODO: fix https://github.com/isi-vista/adam/issues/917 which causes us to have to specify that we don't wish to include ME_HACK and YOU_HACK in our curriculum design diff --git a/adam/curriculum/preposition_curriculum.py b/adam/curriculum/preposition_curriculum.py index 53410f5c6..69d78d0d2 100644 --- a/adam/curriculum/preposition_curriculum.py +++ b/adam/curriculum/preposition_curriculum.py @@ -1,57 +1,59 @@ from itertools import chain -from typing import Iterable, Sequence, Optional -from immutablecollections import immutableset +from typing import Iterable, Optional, Sequence + from more_itertools import flatten -from adam.language.language_generator import LanguageGenerator -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.language.dependency import LinearizedDependencyTree -from adam.axes import HorizontalAxisOfObject, FacingAddresseeAxis + +from adam.axes import FacingAddresseeAxis, HorizontalAxisOfObject from adam.curriculum.curriculum_utils import ( PHASE1_CHOOSER_FACTORY, - standard_object, Phase1InstanceGroup, - phase1_instances, make_noise_objects, + phase1_instances, + standard_object, ) +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator from adam.language_specific.english.english_language_generator import ( USE_ABOVE_BELOW, USE_NEAR, ) -from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, THING, OntologyNode +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, OntologyNode, THING from adam.ontology.phase1_ontology import ( BALL, BOOK, BOX, - TABLE, - on, + CAN_HAVE_THINGS_RESTING_ON_THEM, + CHAIR, + COOKIE, + CUP, + DAD, GAILA_PHASE_1_ONTOLOGY, - inside, - WATER, + HAS_SPACE_UNDER, + HOLLOW, + IS_BODY_PART, JUICE, - CUP, + LEARNER, MOM, - COOKIE, - CHAIR, - DAD, PERSON, - CAN_HAVE_THINGS_RESTING_ON_THEM, + TABLE, + WATER, bigger_than, - HAS_SPACE_UNDER, - IS_BODY_PART, - HOLLOW, - near, far, - strictly_under, + inside, + near, + on, strictly_over, - LEARNER, + strictly_under, ) -from adam.ontology.phase1_spatial_relations import PROXIMAL, Direction, DISTAL +from adam.ontology.phase1_spatial_relations import DISTAL, Direction, PROXIMAL +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_templates import ( Phase1SituationTemplate, - sampled, TemplateObjectVariable, object_variable, + sampled, ) +from immutablecollections import immutableset BOOL_SET = immutableset([True, False]) diff --git a/adam/curriculum/pursuit_curriculum.py b/adam/curriculum/pursuit_curriculum.py index d2b76ff46..9a333ca4c 100644 --- a/adam/curriculum/pursuit_curriculum.py +++ b/adam/curriculum/pursuit_curriculum.py @@ -4,40 +4,40 @@ metrics to pursue the strongest hypothesis as long as it is supported by the following scenes. Paper: The Pursuit of Word Meanings (Stevens et al., 2017) """ +import random from typing import Optional, Sequence from adam.curriculum import ExplicitWithSituationInstanceGroup -from adam.language.language_generator import LanguageGenerator -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.language.dependency import LinearizedDependencyTree from adam.curriculum.curriculum_utils import ( - phase1_instances, PHASE1_CHOOSER_FACTORY, Phase1InstanceGroup, + phase1_instances, standard_object, ) +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator from adam.ontology.phase1_ontology import ( + BABY, + BALL, BIRD, BOX, - GAILA_PHASE_1_ONTOLOGY, - BALL, CHAIR, - TABLE, + DAD, DOG, + GAILA_PHASE_1_ONTOLOGY, MOM, - DAD, - BABY, + TABLE, ) from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import ( - HighLevelSemanticsSituationToDevelopmentalPrimitivePerceptionGenerator, GAILA_PHASE_1_PERCEPTION_GENERATOR, + HighLevelSemanticsSituationToDevelopmentalPrimitivePerceptionGenerator, ) +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_templates import ( Phase1SituationTemplate, object_variable, sampled, ) -import random # TODO: fix https://github.com/isi-vista/adam/issues/917 which causes us to have to specify that we don't wish to include ME_HACK and YOU_HACK in our curriculum design diff --git a/adam/curriculum/verbs_with_dynamic_prepositions_curriculum.py b/adam/curriculum/verbs_with_dynamic_prepositions_curriculum.py index b6cba70d4..b53ec4537 100644 --- a/adam/curriculum/verbs_with_dynamic_prepositions_curriculum.py +++ b/adam/curriculum/verbs_with_dynamic_prepositions_curriculum.py @@ -1,109 +1,110 @@ -from immutablecollections import immutableset from itertools import chain -from typing import Iterable, Sequence, Optional -from adam.language.language_generator import LanguageGenerator -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.language.dependency import LinearizedDependencyTree +from typing import Iterable, Optional, Sequence + from more_itertools import flatten from adam.axes import ( - HorizontalAxisOfObject, FacingAddresseeAxis, GRAVITATIONAL_AXIS_FUNCTION, + HorizontalAxisOfObject, ) from adam.curriculum.curriculum_utils import ( - standard_object, - phase1_instances, + GROUND_OBJECT_TEMPLATE, PHASE1_CHOOSER_FACTORY, Phase1InstanceGroup, - make_background, body_part_object, - GROUND_OBJECT_TEMPLATE, + make_background, make_noise_objects, + phase1_instances, + standard_object, ) +from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator from adam.language_specific.english.english_language_generator import ( - USE_ADVERBIAL_PATH_MODIFIER, IGNORE_GOAL, + USE_ADVERBIAL_PATH_MODIFIER, ) +from adam.ontology import IN_REGION, IS_ADDRESSEE, IS_SPEAKER, THING from adam.ontology.during import DuringAction from adam.ontology.phase1_ontology import ( AGENT, + ANIMATE, + CAN_BE_SAT_ON_BY_PEOPLE, + CAN_FLY, + CAN_HAVE_THINGS_RESTING_ON_THEM, + CAN_JUMP, + COME, FALL, - GOAL, + FLY, GAILA_PHASE_1_ONTOLOGY, - HOLLOW, - SIT, - SIT_THING_SAT_ON, - CAN_BE_SAT_ON_BY_PEOPLE, + GO, + GOAL, + GROUND, HAS_SPACE_UNDER, + HOLLOW, + INANIMATE_OBJECT, + JUMP, + JUMP_INITIAL_SUPPORTER_AUX, + MOVE, + PERSON, PUSH, - THEME, + PUSH_GOAL, PUSH_SURFACE_AUX, - ANIMATE, - INANIMATE_OBJECT, - CAN_HAVE_THINGS_RESTING_ON_THEM, - GO, + PUT, ROLL, - ROLL_SURFACE_AUXILIARY, ROLLABLE, - GROUND, + ROLL_SURFACE_AUXILIARY, + SELF_MOVING, + SIT, + SIT_THING_SAT_ON, + TAKE, + THEME, + THROW, + THROW_GOAL, above, - on, bigger_than, - near, + contacts, far, inside, - TAKE, - PUT, - PERSON, - THROW, - THROW_GOAL, + near, + on, strictly_above, - MOVE, - contacts, - SELF_MOVING, - JUMP_INITIAL_SUPPORTER_AUX, - CAN_JUMP, - JUMP, - FLY, - CAN_FLY, - PUSH_GOAL, - COME, ) -from adam.ontology import THING, IS_SPEAKER, IS_ADDRESSEE, IN_REGION from adam.ontology.phase1_spatial_relations import ( - Region, - PROXIMAL, - INTERIOR, + AWAY_FROM, + DISTAL, Direction, + EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_DOWN, - DISTAL, GRAVITATIONAL_UP, + INTERIOR, + PROXIMAL, + Region, SpatialPath, - VIA, - EXTERIOR_BUT_IN_CONTACT, TOWARD, - AWAY_FROM, + VIA, ) -from adam.relation import flatten_relations, Relation +from adam.relation import Relation, flatten_relations from adam.relation_dsl import negate from adam.situation import Action +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.situation.templates.phase1_situation_templates import ( _fly_over_template, _fly_under_template, + _go_in_template, + _go_to_template, + _go_under_template, _jump_over_template, _put_in_template, - _put_on_template, _put_on_body_part_template, - _go_in_template, - _go_under_template, - _go_to_template, + _put_on_template, ) from adam.situation.templates.phase1_templates import ( - TemplateObjectVariable, Phase1SituationTemplate, + TemplateObjectVariable, sampled, ) +from immutablecollections import immutableset BOOL_SET = immutableset([True, False]) diff --git a/adam/curriculum_to_html.py b/adam/curriculum_to_html.py index e285407c6..9982c0b41 100644 --- a/adam/curriculum_to_html.py +++ b/adam/curriculum_to_html.py @@ -1,68 +1,58 @@ -from datetime import date +import random import shutil +from datetime import date from pathlib import Path from typing import ( AbstractSet, Any, Callable, + Dict, Iterable, List, + Mapping, + Optional, Tuple, TypeVar, Union, - Optional, - Dict, - Mapping, -) -from adam.language.language_utils import phase2_language_generator -from adam.learner.language_mode import LanguageMode -from adam.language.language_generator import LanguageGenerator -from adam.axis import GeonAxis -from adam.curriculum.curriculum_utils import Phase1InstanceGroup -from attr import attrib, attrs -from attr.validators import instance_of -from immutablecollections import ( - ImmutableSet, - ImmutableSetMultiDict, - immutableset, - immutablesetmultidict, ) + from more_itertools import flatten from networkx import DiGraph -from vistautils.parameters import Parameters -from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from vistautils.preconditions import check_state +from adam.axes import AxesInfo, WORLD_AXES, _GravitationalAxis +from adam.axis import GeonAxis +from adam.curriculum import InstanceGroup +from adam.curriculum.attribute_constraining_action_curriculum import make_german_complete +from adam.curriculum.curriculum_utils import Phase1InstanceGroup from adam.curriculum.imprecise_descriptions_curriculum import ( - make_imprecise_temporal_descriptions, make_imprecise_size_curriculum, + make_imprecise_temporal_descriptions, make_subtle_verb_distinctions_curriculum, ) -from adam.curriculum.attribute_constraining_action_curriculum import make_german_complete - from adam.curriculum.m6_curriculum import make_m6_curriculum +from adam.curriculum.phase1_curriculum import build_gaila_phase_1_curriculum from adam.curriculum.phase2_curriculum import build_gaila_m8_curriculum from adam.curriculum.preposition_curriculum import make_prepositions_curriculum from adam.curriculum.pursuit_curriculum import make_pursuit_curriculum -from adam.curriculum.phase1_curriculum import build_gaila_phase_1_curriculum -from adam.curriculum import InstanceGroup from adam.curriculum.verbs_with_dynamic_prepositions_curriculum import ( make_verb_with_dynamic_prepositions_curriculum, ) from adam.geon import Geon -from adam.axes import WORLD_AXES, AxesInfo, _GravitationalAxis from adam.language import TokenSequenceLinguisticDescription from adam.language.dependency import LinearizedDependencyTree +from adam.language.language_generator import LanguageGenerator +from adam.language.language_utils import phase2_language_generator +from adam.learner.language_mode import LanguageMode from adam.ontology import IN_REGION, IS_SPEAKER, OntologyNode from adam.ontology.during import DuringAction from adam.ontology.phase1_ontology import ( - PART_OF, - SMALLER_THAN, BIGGER_THAN, - MUCH_SMALLER_THAN, MUCH_BIGGER_THAN, + MUCH_SMALLER_THAN, + PART_OF, + SMALLER_THAN, ) -from adam.ontology.phase1_spatial_relations import Region, SpatialPath, Direction +from adam.ontology.phase1_spatial_relations import Direction, Region, SpatialPath from adam.perception import ObjectPerception, PerceptualRepresentation from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -74,7 +64,17 @@ from adam.situation import SituationObject, SituationRegion from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.utilities import sign -import random +from attr import attrib, attrs +from attr.validators import instance_of +from immutablecollections import ( + ImmutableSet, + ImmutableSetMultiDict, + immutableset, + immutablesetmultidict, +) +from vistautils.parameters import Parameters +from vistautils.parameters_only_entrypoint import parameters_only_entry_point +from vistautils.preconditions import check_state USAGE_MESSAGE = """ curriculum_to_html.py param_file diff --git a/adam/debugging/intersect_patterns.py b/adam/debugging/intersect_patterns.py index cbd152b8f..4912005b6 100644 --- a/adam/debugging/intersect_patterns.py +++ b/adam/debugging/intersect_patterns.py @@ -13,9 +13,9 @@ from adam.ontology.phase1_ontology import GAILA_PHASE_1_ONTOLOGY from adam.perception.perception_graph import ( - PerceptionGraphPattern, GraphLogger, MatchMode, + PerceptionGraphPattern, ) if __name__ == "__main__": diff --git a/adam/experiment/__init__.py b/adam/experiment/__init__.py index d68bc26ff..623eddbfe 100644 --- a/adam/experiment/__init__.py +++ b/adam/experiment/__init__.py @@ -2,8 +2,8 @@ Allows managing experimental configurations in code. """ import logging -import pickle import os +import pickle from itertools import chain # for some reason, pylint doesn't recognize the types used in quoted type annotations @@ -12,11 +12,18 @@ Any, Callable, Generic, + Optional, Sequence, Tuple, - Optional, ) # pylint:disable=unused-import +from adam.curriculum import InstanceGroup +from adam.experiment.observer import DescriptionObserver +from adam.language import LinguisticDescriptionT +from adam.learner import LearningExample, TopLevelLanguageLearner +from adam.perception import PerceptionT +from adam.random_utils import SequenceChooser +from adam.situation import SituationT from attr import attrib, attrs from attr.validators import instance_of @@ -24,14 +31,6 @@ from immutablecollections.converter_utils import _to_tuple from vistautils.preconditions import check_arg -from adam.curriculum import InstanceGroup -from adam.experiment.observer import DescriptionObserver -from adam.language import LinguisticDescriptionT -from adam.situation import SituationT -from adam.learner import TopLevelLanguageLearner, LearningExample -from adam.perception import PerceptionT -from adam.random_utils import SequenceChooser - @attrs(frozen=True) class Experiment(Generic[SituationT, LinguisticDescriptionT, PerceptionT]): diff --git a/adam/experiment/experiment_utils.py b/adam/experiment/experiment_utils.py index 0749a618e..82230aa52 100644 --- a/adam/experiment/experiment_utils.py +++ b/adam/experiment/experiment_utils.py @@ -1,16 +1,16 @@ from itertools import repeat -from typing import Sequence, Optional +from typing import Optional, Sequence from adam.curriculum.curriculum_utils import Phase1InstanceGroup from adam.curriculum.m6_curriculum import ( + M6_CURRICULUM_ALL_OBJECTS, M6_PREPOSITION_SUBCURRICULUM_GENERATORS, instantiate_subcurricula, - M6_CURRICULUM_ALL_OBJECTS, ) from adam.curriculum.phase1_curriculum import ( _make_each_object_by_itself_curriculum, - _make_put_on_speaker_addressee_body_part_curriculum, _make_generic_statements_curriculum, + _make_put_on_speaker_addressee_body_part_curriculum, ) from adam.curriculum.pursuit_curriculum import make_simple_pursuit_curriculum from adam.language.dependency import LinearizedDependencyTree diff --git a/adam/experiment/log_experiment.py b/adam/experiment/log_experiment.py index 9dc68a4d4..98dc53dfd 100644 --- a/adam/experiment/log_experiment.py +++ b/adam/experiment/log_experiment.py @@ -1,5 +1,5 @@ import logging -from typing import Callable, Optional, Mapping, Iterable, Tuple +from typing import Callable, Iterable, Mapping, Optional, Tuple from adam.curriculum.curriculum_utils import Phase1InstanceGroup from adam.curriculum.imprecise_descriptions_curriculum import ( @@ -7,6 +7,14 @@ make_imprecise_temporal_descriptions, make_subtle_verb_distinctions_curriculum, ) +from adam.curriculum.m6_curriculum import make_m6_curriculum +from adam.curriculum.phase1_curriculum import ( + build_gaila_phase1_attribute_curriculum, + build_gaila_phase1_object_curriculum, + build_gaila_phase1_relation_curriculum, + build_gaila_phase1_verb_curriculum, + build_gaila_phase_1_curriculum, +) from adam.curriculum.phase2_curriculum import ( build_functionally_defined_objects_curriculum, build_gaila_m13_curriculum, @@ -15,56 +23,48 @@ from adam.curriculum.verbs_with_dynamic_prepositions_curriculum import ( make_verb_with_dynamic_prepositions_curriculum, ) +from adam.experiment import Experiment, execute_experiment from adam.experiment.experiment_utils import ( - build_each_object_by_itself_curriculum_train, - build_each_object_by_itself_curriculum_test, - build_debug_curriculum_train, build_debug_curriculum_test, + build_debug_curriculum_train, + build_each_object_by_itself_curriculum_test, + build_each_object_by_itself_curriculum_train, build_generics_curriculum, build_m6_prepositions_curriculum, build_pursuit_curriculum, ) +from adam.experiment.observer import CandidateAccuracyObserver, LearningProgressHtmlLogger from adam.language.dependency import LinearizedDependencyTree from adam.language.language_generator import LanguageGenerator from adam.language.language_utils import phase2_language_generator from adam.language_specific.english import ENGLISH_DETERMINERS +from adam.learner import TopLevelLanguageLearner from adam.learner.attributes import SubsetAttributeLearner, SubsetAttributeLearnerNew from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode -from adam.learner.relations import SubsetRelationLearnerNew -from adam.learner.verbs import SubsetVerbLearner, SubsetVerbLearnerNew -from adam.ontology.phase2_ontology import GAILA_PHASE_2_ONTOLOGY -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from vistautils.parameters import Parameters -from vistautils.parameters_only_entrypoint import parameters_only_entry_point - -from adam.curriculum.m6_curriculum import make_m6_curriculum -from adam.curriculum.phase1_curriculum import ( - build_gaila_phase1_object_curriculum, - build_gaila_phase1_attribute_curriculum, - build_gaila_phase1_relation_curriculum, - build_gaila_phase1_verb_curriculum, - build_gaila_phase_1_curriculum, -) -from adam.experiment import Experiment, execute_experiment -from adam.experiment.observer import LearningProgressHtmlLogger, CandidateAccuracyObserver -from adam.learner import TopLevelLanguageLearner from adam.learner.object_recognizer import ObjectRecognizer -from adam.learner.prepositions import SubsetPrepositionLearner -from adam.learner.pursuit import HypothesisLogger from adam.learner.objects import ( ObjectPursuitLearner, + ObjectRecognizerAsTemplateLearner, SubsetObjectLearner, SubsetObjectLearnerNew, - ObjectRecognizerAsTemplateLearner, ) +from adam.learner.prepositions import SubsetPrepositionLearner +from adam.learner.pursuit import HypothesisLogger +from adam.learner.quantifers import QuantifierTemplateLearner +from adam.learner.relations import SubsetRelationLearnerNew +from adam.learner.verbs import SubsetVerbLearner, SubsetVerbLearnerNew from adam.ontology.phase1_ontology import ( GAILA_PHASE_1_ONTOLOGY, ME_HACK, - YOU_HACK, PHASE_1_CURRICULUM_OBJECTS, + YOU_HACK, ) +from adam.ontology.phase2_ontology import GAILA_PHASE_2_ONTOLOGY from adam.random_utils import RandomChooser +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation +from vistautils.parameters import Parameters +from vistautils.parameters_only_entrypoint import parameters_only_entry_point LANGUAGE_GEN = LanguageGenerator[ # pylint: disable=invalid-name HighLevelSemanticsSituation, LinearizedDependencyTree @@ -210,6 +210,10 @@ def learner_factory_from_params( beam_size=beam_size, language_mode=language_mode, ), + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode=language_mode + ), + language_mode=language_mode, ) elif learner_type == "integrated-learner-recognizer": return lambda: IntegratedTemplateLearner( @@ -231,6 +235,10 @@ def learner_factory_from_params( beam_size=beam_size, language_mode=language_mode, ), + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode=language_mode + ), + language_mode=language_mode, ) else: raise RuntimeError("can't happen") diff --git a/adam/experiment/observer.py b/adam/experiment/observer.py index d3848a2e6..845ffbe0c 100644 --- a/adam/experiment/observer.py +++ b/adam/experiment/observer.py @@ -4,16 +4,15 @@ from more_itertools import only, take -from attr import attrib, attrs -from attr.validators import instance_of -from vistautils.parameters import Parameters - from adam.curriculum_to_html import CurriculumToHtmlDumper from adam.language import LinguisticDescription, LinguisticDescriptionT -from adam.situation import SituationT from adam.perception import PerceptionT, PerceptualRepresentation +from adam.situation import SituationT from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.visualization.make_scenes import situation_to_filename +from attr import attrib, attrs +from attr.validators import instance_of +from vistautils.parameters import Parameters class DescriptionObserver(Generic[SituationT, LinguisticDescriptionT, PerceptionT], ABC): diff --git a/adam/experiment/run_m13.py b/adam/experiment/run_m13.py index ff59980cb..e7b21e0f8 100644 --- a/adam/experiment/run_m13.py +++ b/adam/experiment/run_m13.py @@ -2,11 +2,10 @@ from pathlib import Path from typing import List +from adam.experiment.log_experiment import log_experiment_entry_point from vistautils.parameters import Parameters, YAMLParametersLoader from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from adam.experiment.log_experiment import log_experiment_entry_point - def main(params: Parameters): adam_root = params.existing_directory("adam_root") diff --git a/adam/experiment/run_m6.py b/adam/experiment/run_m6.py index d8f58d039..e08b43eec 100644 --- a/adam/experiment/run_m6.py +++ b/adam/experiment/run_m6.py @@ -1,10 +1,9 @@ import logging +from adam.experiment.log_experiment import log_experiment_entry_point from vistautils.parameters import Parameters, YAMLParametersLoader from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from adam.experiment.log_experiment import log_experiment_entry_point - def main(params: Parameters): adam_root = params.existing_directory("adam_root") diff --git a/adam/experiment/run_m9.py b/adam/experiment/run_m9.py index 00d6098db..dc7b36b0a 100644 --- a/adam/experiment/run_m9.py +++ b/adam/experiment/run_m9.py @@ -2,11 +2,10 @@ from pathlib import Path from typing import List +from adam.experiment.log_experiment import log_experiment_entry_point from vistautils.parameters import Parameters, YAMLParametersLoader from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from adam.experiment.log_experiment import log_experiment_entry_point - def main(params: Parameters): adam_root = params.existing_directory("adam_root") diff --git a/adam/experiment/run_object_restrictions.py b/adam/experiment/run_object_restrictions.py index 295946ba1..f4efea3d6 100644 --- a/adam/experiment/run_object_restrictions.py +++ b/adam/experiment/run_object_restrictions.py @@ -1,10 +1,9 @@ import logging +from adam.experiment.log_experiment import log_experiment_entry_point from vistautils.parameters import Parameters, YAMLParametersLoader from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from adam.experiment.log_experiment import log_experiment_entry_point - def main(params: Parameters): adam_root = params.existing_directory("adam_root") diff --git a/adam/geon.py b/adam/geon.py index 9a8174830..b2ac2a435 100644 --- a/adam/geon.py +++ b/adam/geon.py @@ -1,13 +1,12 @@ -from typing import Dict, Optional, Mapping +from typing import Dict, Mapping, Optional from typing_extensions import Protocol -from attr import attrib, attrs -from attr.validators import instance_of - from adam.axes import Axes, HasAxes from adam.axis import GeonAxis from adam.utilities import sign +from attr import attrib, attrs +from attr.validators import instance_of @attrs(frozen=True, slots=True, repr=False) diff --git a/adam/language/__init__.py b/adam/language/__init__.py index 6733e392f..26161dc2d 100644 --- a/adam/language/__init__.py +++ b/adam/language/__init__.py @@ -1,12 +1,11 @@ r""" Representations of the linguistic input and outputs of a `LanguageLearner`\ . """ -from abc import ABC, abstractmethod -from typing import Optional, Tuple, TypeVar, Sequence, Sized +from abc import ABC +from typing import Optional, Sequence, Tuple, TypeVar from attr import attrib, attrs -from attr.validators import instance_of, deep_iterable - +from attr.validators import deep_iterable, instance_of from immutablecollections.converter_utils import _to_tuple from vistautils.span import Span diff --git a/adam/language/dependency/__init__.py b/adam/language/dependency/__init__.py index 8e76f8804..060e8af9a 100644 --- a/adam/language/dependency/__init__.py +++ b/adam/language/dependency/__init__.py @@ -4,6 +4,10 @@ from abc import ABC, abstractmethod from typing import Iterable, Tuple +from more_itertools import flatten +from networkx import DiGraph + +from adam.language import LinguisticDescription from attr import attrib, attrs from attr.validators import instance_of from immutablecollections import ImmutableDict, ImmutableSet, immutabledict, immutableset @@ -12,10 +16,6 @@ _to_immutableset, _to_tuple, ) -from more_itertools import flatten -from networkx import DiGraph - -from adam.language import LinguisticDescription @attrs(frozen=True, slots=True, eq=False) diff --git a/adam/language/language_generator/__init__.py b/adam/language/language_generator/__init__.py index f037cc5ef..739701703 100644 --- a/adam/language/language_generator/__init__.py +++ b/adam/language/language_generator/__init__.py @@ -4,15 +4,14 @@ from abc import ABC, abstractmethod from typing import Generic -from attr import attrib, attrs -from attr.validators import instance_of -from immutablecollections import ImmutableSet, immutableset -from vistautils.iter_utils import only - from adam.language import LinguisticDescriptionT, TokenSequenceLinguisticDescription from adam.language.ontology_dictionary import OntologyLexicon from adam.random_utils import SequenceChooser from adam.situation import LocatedObjectSituation, SituationT +from attr import attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableSet, immutableset +from vistautils.iter_utils import only class LanguageGenerator(Generic[SituationT, LinguisticDescriptionT], ABC): diff --git a/adam/language/lexicon.py b/adam/language/lexicon.py index a1ba569ac..95834e4d8 100644 --- a/adam/language/lexicon.py +++ b/adam/language/lexicon.py @@ -6,13 +6,12 @@ """ from typing import Optional +from adam.language.dependency import MorphosyntacticProperty, PartOfSpeechTag from attr import attrib, attrs from attr.validators import instance_of from immutablecollections import ImmutableSet, immutableset from immutablecollections.converter_utils import _to_immutableset -from adam.language.dependency import MorphosyntacticProperty, PartOfSpeechTag - @attrs(frozen=True, slots=True) class LexiconEntry: diff --git a/adam/language/ontology_dictionary.py b/adam/language/ontology_dictionary.py index d3f5b4342..3545ac372 100644 --- a/adam/language/ontology_dictionary.py +++ b/adam/language/ontology_dictionary.py @@ -2,16 +2,15 @@ Mappings from `Ontology`\ s to particular languages. """ +from adam.language.lexicon import LexiconEntry +from adam.ontology import OntologyNode +from adam.ontology.ontology import Ontology from attr import attrib, attrs from attr.validators import instance_of from immutablecollections import ImmutableSet, ImmutableSetMultiDict from immutablecollections.converter_utils import _to_immutablesetmultidict from vistautils.preconditions import check_arg -from adam.language.lexicon import LexiconEntry -from adam.ontology import OntologyNode -from adam.ontology.ontology import Ontology - @attrs(frozen=True, slots=True) class OntologyLexicon: diff --git a/adam/language_specific/__init__.py b/adam/language_specific/__init__.py index b0e60f4e9..d0f3eb60a 100644 --- a/adam/language_specific/__init__.py +++ b/adam/language_specific/__init__.py @@ -1,6 +1,6 @@ """Define language independent properties at the module level""" -from adam.language.lexicon import LexiconEntry, LexiconProperty from adam.language.dependency import MorphosyntacticProperty +from adam.language.lexicon import LexiconProperty # Define universal morphosyntactic properties FIRST_PERSON = MorphosyntacticProperty("1p") diff --git a/adam/language_specific/chinese/chinese_language_generator.py b/adam/language_specific/chinese/chinese_language_generator.py index 1c5003aea..c6754655d 100644 --- a/adam/language_specific/chinese/chinese_language_generator.py +++ b/adam/language_specific/chinese/chinese_language_generator.py @@ -1,14 +1,10 @@ import collections from itertools import chain from typing import Iterable, List, Mapping, MutableMapping, Optional, Tuple, Union, cast -from attr import Factory, attrib, attrs -from attr.validators import instance_of -from immutablecollections import ImmutableSet, immutableset, immutablesetmultidict + from more_itertools import first, only from networkx import DiGraph -from adam.language_specific.chinese.chinese_phase_2_lexicon import ( - GAILA_PHASE_2_CHINESE_LEXICON, -) + from adam.axes import FacingAddresseeAxis, GRAVITATIONAL_DOWN_TO_UP_AXIS from adam.language.dependency import ( DependencyRole, @@ -18,104 +14,102 @@ LinearizedDependencyTree, ) from adam.language.dependency.universal_dependencies import ( - PARTICLE, - CLASSIFIER, - NOUN, ADJECTIVAL_MODIFIER, + ADJECTIVE, ADPOSITION, ADVERB, + ADVERBIAL_CLAUSE_MODIFIER, ADVERBIAL_MODIFIER, CASE_POSSESSIVE, CASE_SPATIAL, - DETERMINER, - DETERMINER_ROLE, + CLASSIFIER, INDIRECT_OBJECT, + IS_ATTRIBUTE, NOMINAL_MODIFIER, NOMINAL_MODIFIER_POSSESSIVE, NOMINAL_SUBJECT, - ADJECTIVE, + NOUN, NUMERAL, NUMERIC_MODIFIER, OBJECT, OBLIQUE_NOMINAL, + PARTICLE, PROPER_NOUN, VERB, - IS_ATTRIBUTE, - ADVERBIAL_CLAUSE_MODIFIER, ) from adam.language.language_generator import LanguageGenerator from adam.language.lexicon import LexiconEntry from adam.language.ontology_dictionary import OntologyLexicon +from adam.language_specific import ALLOWS_DITRANSITIVE from adam.language_specific.chinese.chinese_phase_1_lexicon import ( + BABY, + BIRD, + DAD, + DOG, GAILA_PHASE_1_CHINESE_LEXICON, + GRAB, ME, - YOU, + MOM, RUN, - GRAB, SHOVE, TOSS, - MOM, - DAD, - BABY, - DOG, - BIRD, + YOU, ) -from adam.language_specific import ( - FIRST_PERSON, - SECOND_PERSON, - ALLOWS_DITRANSITIVE, - MASS_NOUN, +from adam.language_specific.chinese.chinese_phase_2_lexicon import ( + GAILA_PHASE_2_CHINESE_LEXICON, ) from adam.language_specific.chinese.chinese_syntax import ( SIMPLE_CHINESE_DEPENDENCY_TREE_LINEARIZER, ) from adam.ontology import IN_REGION, IS_ADDRESSEE, IS_SPEAKER, OntologyNode from adam.ontology.phase1_ontology import ( - ANIMATE, AGENT, - PUSH, + BIGGER_THAN, COLOR, + COME, FALL, + FAST, + GIVE, + GO, GOAL, + GOAL_MANIPULATOR, GROUND, + HARD_FORCE, HAS, + JUMP, LEARNER, + PASS, PATIENT, + PUSH, SIT, - THEME, - JUMP, - GIVE, - GO, - COME, - HARD_FORCE, - SOFT_FORCE, - FAST, SLOW, - BIGGER_THAN, SMALLER_THAN, - WALK, + SOFT_FORCE, TAKE, - PASS, - GOAL_MANIPULATOR, + THEME, + WALK, ) from adam.ontology.phase1_spatial_relations import ( + AWAY_FROM, + DISTAL, EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_DOWN, + GRAVITATIONAL_UP, INTERIOR, PROXIMAL, Region, - TOWARD, - GRAVITATIONAL_UP, - DISTAL, SpatialPath, - AWAY_FROM, TO, + TOWARD, VIA, ) from adam.random_utils import SequenceChooser from adam.relation import Relation from adam.situation import Action, SituationObject, SituationRegion from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation +from attr import Factory, attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableSet, immutableset, immutablesetmultidict @attrs(frozen=True, slots=True) diff --git a/adam/language_specific/chinese/chinese_phase_1_lexicon.py b/adam/language_specific/chinese/chinese_phase_1_lexicon.py index c31901903..3e661d931 100644 --- a/adam/language_specific/chinese/chinese_phase_1_lexicon.py +++ b/adam/language_specific/chinese/chinese_phase_1_lexicon.py @@ -9,12 +9,6 @@ This vocabulary has been verified by a native speaker. """ -from adam.language_specific import ( - FIRST_PERSON, - SECOND_PERSON, - MASS_NOUN, - ALLOWS_DITRANSITIVE, -) from adam.language.dependency.universal_dependencies import ( ADJECTIVE, NOUN, @@ -23,6 +17,12 @@ ) from adam.language.lexicon import LexiconEntry from adam.language.ontology_dictionary import OntologyLexicon +from adam.language_specific import ( + ALLOWS_DITRANSITIVE, + FIRST_PERSON, + MASS_NOUN, + SECOND_PERSON, +) from adam.ontology.phase1_ontology import ( BABY, BALL, @@ -37,6 +37,7 @@ COOKIE, CUP, DAD, + DARK_BROWN, DOG, DOOR, DRINK, @@ -55,9 +56,11 @@ HOUSE, JUICE, JUMP, + LIGHT_BROWN, MILK, MOM, MOVE, + PASS, PUSH, PUT, RED, @@ -69,13 +72,10 @@ THROW, TRANSPARENT, TRUCK, + WALK, WATER, - WHITE, - LIGHT_BROWN, - DARK_BROWN, WATERMELON, - PASS, - WALK, + WHITE, ) ME = LexiconEntry("wo3", NOUN, intrinsic_morphosyntactic_properties=[FIRST_PERSON]) diff --git a/adam/language_specific/chinese/chinese_phase_2_lexicon.py b/adam/language_specific/chinese/chinese_phase_2_lexicon.py index d3b69b87d..a5b0785f9 100644 --- a/adam/language_specific/chinese/chinese_phase_2_lexicon.py +++ b/adam/language_specific/chinese/chinese_phase_2_lexicon.py @@ -4,18 +4,15 @@ from adam.language_specific.chinese.chinese_phase_1_lexicon import ( GAILA_PHASE_1_CHINESE_LEXICON, ) -from adam.language_specific.english.english_phase_1_lexicon import ( - GAILA_PHASE_1_ENGLISH_LEXICON, -) from adam.ontology.phase2_ontology import ( - GAILA_PHASE_2_ONTOLOGY, + CHAIR_2, + CHAIR_3, + CHAIR_4, CHAIR_5, CUP_2, CUP_3, CUP_4, - CHAIR_2, - CHAIR_3, - CHAIR_4, + GAILA_PHASE_2_ONTOLOGY, ) GAILA_PHASE_2_CHINESE_LEXICON = OntologyLexicon( diff --git a/adam/language_specific/chinese/chinese_syntax.py b/adam/language_specific/chinese/chinese_syntax.py index 616362e9d..448b966c9 100644 --- a/adam/language_specific/chinese/chinese_syntax.py +++ b/adam/language_specific/chinese/chinese_syntax.py @@ -2,7 +2,7 @@ by native speaker asked for grammaticality judgments.""" from typing import Tuple -from immutablecollections import ImmutableDict, immutabledict + from adam.language.dependency import ( DependencyRole, HEAD, @@ -15,7 +15,9 @@ ADVERBIAL_MODIFIER, CASE_POSSESSIVE, CASE_SPATIAL, + CLASSIFIER, INDIRECT_OBJECT, + IS_ATTRIBUTE, NOMINAL_MODIFIER, NOMINAL_MODIFIER_POSSESSIVE, NOMINAL_SUBJECT, @@ -25,9 +27,8 @@ OBLIQUE_NOMINAL, PROPER_NOUN, VERB, - IS_ATTRIBUTE, - CLASSIFIER, ) +from immutablecollections import ImmutableDict _CHINESE_HEAD_TO_ROLE_ORDER: ImmutableDict[ PartOfSpeechTag, Tuple[DependencyRole, ...] diff --git a/adam/language_specific/english/__init__.py b/adam/language_specific/english/__init__.py index 9c44edbd0..99dc5b8fe 100644 --- a/adam/language_specific/english/__init__.py +++ b/adam/language_specific/english/__init__.py @@ -12,3 +12,5 @@ """ These words block the addition of the determiners above to English noun phrases. """ +ENGLISH_MASS_NOUNS = ["juice", "water", "milk"] +ENGLISH_RECOGNIZED_PARTICULARS = immutableset(["me", "you", "Mom", "Dad"]) diff --git a/adam/language_specific/english/english_language_generator.py b/adam/language_specific/english/english_language_generator.py index 8eda2fb21..9a455ddf7 100644 --- a/adam/language_specific/english/english_language_generator.py +++ b/adam/language_specific/english/english_language_generator.py @@ -2,9 +2,6 @@ from itertools import chain from typing import Iterable, List, Mapping, MutableMapping, Optional, Tuple, Union, cast -from attr import Factory, attrib, attrs -from attr.validators import instance_of -from immutablecollections import ImmutableSet, immutableset, immutablesetmultidict from more_itertools import first, only from networkx import DiGraph @@ -18,6 +15,7 @@ ) from adam.language.dependency.universal_dependencies import ( ADJECTIVAL_MODIFIER, + ADJECTIVE, ADPOSITION, ADVERB, ADVERBIAL_MODIFIER, @@ -26,6 +24,8 @@ DETERMINER, DETERMINER_ROLE, INDIRECT_OBJECT, + IS_ATTRIBUTE, + MARKER, NOMINAL_MODIFIER, NOMINAL_MODIFIER_POSSESSIVE, NOMINAL_SUBJECT, @@ -33,79 +33,79 @@ NUMERIC_MODIFIER, OBJECT, OBLIQUE_NOMINAL, + OTHER, PROPER_NOUN, VERB, - IS_ATTRIBUTE, - OTHER, - MARKER, - ADJECTIVE, ) from adam.language.language_generator import LanguageGenerator from adam.language.lexicon import LexiconEntry from adam.language.ontology_dictionary import OntologyLexicon +from adam.language_specific import ( + ALLOWS_DITRANSITIVE, + FIRST_PERSON, + MASS_NOUN, + SECOND_PERSON, +) from adam.language_specific.english.english_phase_1_lexicon import ( GAILA_PHASE_1_ENGLISH_LEXICON, + GRAB, I, ME, - YOU, - GRAB, + RUN, SHOVE, TOSS, - RUN, + YOU, ) from adam.language_specific.english.english_phase_2_lexicon import ( GAILA_PHASE_2_ENGLISH_LEXICON, ) -from adam.language_specific import ( - FIRST_PERSON, - SECOND_PERSON, - ALLOWS_DITRANSITIVE, - MASS_NOUN, -) from adam.language_specific.english.english_syntax import ( SIMPLE_ENGLISH_DEPENDENCY_TREE_LINEARIZER, ) from adam.ontology import IN_REGION, IS_ADDRESSEE, IS_SPEAKER, OntologyNode from adam.ontology.phase1_ontology import ( AGENT, + BIGGER_THAN, COLOR, FALL, + FAST, GOAL, GROUND, + HARD_FORCE, HAS, + JUMP, LEARNER, + PASS, PATIENT, + PUSH, SIT, - THEME, - JUMP, - FAST, SLOW, - BIGGER_THAN, SMALLER_THAN, - WALK, - PASS, - PUSH, TAKE, - HARD_FORCE, + THEME, + WALK, ) from adam.ontology.phase1_spatial_relations import ( + AWAY_FROM, + DISTAL, EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_DOWN, + GRAVITATIONAL_UP, INTERIOR, PROXIMAL, Region, - TOWARD, - GRAVITATIONAL_UP, SpatialPath, - AWAY_FROM, TO, - DISTAL, + TOWARD, VIA, ) from adam.random_utils import SequenceChooser from adam.relation import Relation from adam.situation import Action, SituationObject, SituationRegion from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation +from attr import Factory, attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableSet, immutableset, immutablesetmultidict @attrs(frozen=True, slots=True) diff --git a/adam/language_specific/english/english_phase_1_lexicon.py b/adam/language_specific/english/english_phase_1_lexicon.py index 597b05755..206368e86 100644 --- a/adam/language_specific/english/english_phase_1_lexicon.py +++ b/adam/language_specific/english/english_phase_1_lexicon.py @@ -7,12 +7,12 @@ from adam.language.lexicon import LexiconEntry from adam.language.ontology_dictionary import OntologyLexicon from adam.language_specific import ( - FIRST_PERSON, - SECOND_PERSON, - NOMINATIVE, ACCUSATIVE, - MASS_NOUN, ALLOWS_DITRANSITIVE, + FIRST_PERSON, + MASS_NOUN, + NOMINATIVE, + SECOND_PERSON, ) from adam.ontology.phase1_ontology import ( BABY, @@ -28,6 +28,7 @@ COOKIE, CUP, DAD, + DARK_BROWN, DOG, DOOR, DRINK, @@ -46,9 +47,11 @@ HOUSE, JUICE, JUMP, + LIGHT_BROWN, MILK, MOM, MOVE, + PASS, PUSH, PUT, RED, @@ -60,13 +63,10 @@ THROW, TRANSPARENT, TRUCK, + WALK, WATER, - WHITE, - LIGHT_BROWN, - DARK_BROWN, - PASS, WATERMELON, - WALK, + WHITE, ) I = LexiconEntry( # noqa: E741 diff --git a/adam/language_specific/english/english_phase_2_lexicon.py b/adam/language_specific/english/english_phase_2_lexicon.py index 83689155f..6740bdcdf 100644 --- a/adam/language_specific/english/english_phase_2_lexicon.py +++ b/adam/language_specific/english/english_phase_2_lexicon.py @@ -5,14 +5,14 @@ GAILA_PHASE_1_ENGLISH_LEXICON, ) from adam.ontology.phase2_ontology import ( - GAILA_PHASE_2_ONTOLOGY, + CHAIR_2, + CHAIR_3, + CHAIR_4, CHAIR_5, CUP_2, CUP_3, CUP_4, - CHAIR_2, - CHAIR_3, - CHAIR_4, + GAILA_PHASE_2_ONTOLOGY, ) GAILA_PHASE_2_ENGLISH_LEXICON = OntologyLexicon( diff --git a/adam/language_specific/english/english_syntax.py b/adam/language_specific/english/english_syntax.py index 92742f8cb..b043dbee2 100644 --- a/adam/language_specific/english/english_syntax.py +++ b/adam/language_specific/english/english_syntax.py @@ -1,7 +1,5 @@ from typing import Tuple -from immutablecollections import ImmutableDict, immutabledict - from adam.language.dependency import ( DependencyRole, HEAD, @@ -15,6 +13,8 @@ CASE_SPATIAL, DETERMINER_ROLE, INDIRECT_OBJECT, + IS_ATTRIBUTE, + MARKER, NOMINAL_MODIFIER, NOMINAL_MODIFIER_POSSESSIVE, NOMINAL_SUBJECT, @@ -24,9 +24,8 @@ OBLIQUE_NOMINAL, PROPER_NOUN, VERB, - IS_ATTRIBUTE, - MARKER, ) +from immutablecollections import ImmutableDict, immutabledict _ENGLISH_HEAD_TO_ROLE_ORDER: ImmutableDict[ PartOfSpeechTag, Tuple[DependencyRole, ...] diff --git a/adam/learner/__init__.py b/adam/learner/__init__.py index a0c82ca85..7b75c4b48 100644 --- a/adam/learner/__init__.py +++ b/adam/learner/__init__.py @@ -1,56 +1,42 @@ """ Interfaces for language learning code. """ -from adam.learner.language_mode import LanguageMode from abc import ABC, abstractmethod from pathlib import Path -from typing import ( - Dict, - Generic, - Mapping, - Optional, - Callable, - Tuple, - Iterable, - List, - AbstractSet, -) -from immutablecollections import ImmutableSet, immutableset +from typing import Callable, Dict, Generic, Mapping, Optional + +from more_itertools import first +from networkx import isolates + +from adam.language import LinguisticDescription, LinguisticDescriptionT from adam.learner.alignments import ( + LanguageConceptAlignment, LanguagePerceptionSemanticAlignment, PerceptionSemanticAlignment, ) +from adam.learner.language_mode import LanguageMode from adam.learner.surface_templates import ( STANDARD_SLOT_VARIABLES, SurfaceTemplate, SurfaceTemplateBoundToSemanticNodes, ) -from enum import Enum, auto -import itertools -from adam.learner.alignments import LanguageConceptAlignment -from adam.semantics import SemanticNode -from vistautils.span import Span from adam.ontology.ontology import Ontology -from attr import Factory, attrib, attrs -from attr.validators import instance_of -from immutablecollections import immutabledict -from more_itertools import first -from networkx import isolates - -from adam.language import LinguisticDescription, LinguisticDescriptionT from adam.ontology.phase1_ontology import LEARNER from adam.perception import ( + MatchMode, + ObjectPerception, PerceptionT, PerceptualRepresentation, - ObjectPerception, - MatchMode, ) from adam.perception.perception_graph import ( - PerceptionGraph, - PerceptionGraphPattern, DebugCallableType, GraphLogger, + PerceptionGraph, + PerceptionGraphPattern, ) +from attr import Factory, attrib, attrs +from attr.validators import instance_of +from immutablecollections import immutabledict @attrs(frozen=True) diff --git a/adam/learner/attributes.py b/adam/learner/attributes.py index dadc73ce2..a3046e37a 100644 --- a/adam/learner/attributes.py +++ b/adam/learner/attributes.py @@ -1,16 +1,18 @@ from abc import ABC -from typing import AbstractSet, Union, Optional +from typing import AbstractSet, Optional, Union + from adam.language import LinguisticDescription from adam.learner import LearningExample -from adam.learner.language_mode import LanguageMode from adam.learner.alignments import ( LanguagePerceptionSemanticAlignment, PerceptionSemanticAlignment, ) +from adam.learner.language_mode import LanguageMode from adam.learner.learner_utils import ( + SyntaxSemanticsVariable, assert_static_situation, - pattern_remove_incomplete_region_or_spatial_path, covers_entire_utterance, + pattern_remove_incomplete_region_or_spatial_path, ) from adam.learner.object_recognizer import ( ObjectRecognizer, @@ -28,10 +30,10 @@ SurfaceTemplateBoundToSemanticNodes, ) from adam.learner.template_learner import ( - AbstractTemplateLearner, - AbstractTemplateLearnerNew, + AbstractPerceptualTemplateLearner, + AbstractPerceptualTemplateLearnerNew, ) -from adam.perception import PerceptualRepresentation, MatchMode +from adam.perception import MatchMode, PerceptualRepresentation from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -42,11 +44,10 @@ from attr.validators import instance_of from immutablecollections import immutabledict, immutableset, immutablesetmultidict from vistautils.span import Span -from adam.learner.learner_utils import SyntaxSemanticsVariable @attrs -class AbstractAttributeTemplateLearnerNew(AbstractTemplateLearnerNew, ABC): +class AbstractAttributeTemplateLearnerNew(AbstractPerceptualTemplateLearnerNew, ABC): # pylint:disable=abstract-method def _candidate_templates( self, language_perception_semantic_alignment: LanguagePerceptionSemanticAlignment @@ -124,7 +125,7 @@ def _candidate_templates( @attrs -class AbstractAttributeTemplateLearner(AbstractTemplateLearner, ABC): +class AbstractAttributeTemplateLearner(AbstractPerceptualTemplateLearner, ABC): # mypy doesn't realize that fields without defaults can come after those with defaults # if they are keyword-only. _object_recognizer: ObjectRecognizer = attrib( # type: ignore diff --git a/adam/learner/integrated_learner.py b/adam/learner/integrated_learner.py index 9206e95c5..141d345eb 100644 --- a/adam/learner/integrated_learner.py +++ b/adam/learner/integrated_learner.py @@ -1,11 +1,17 @@ import itertools import logging -from itertools import chain, combinations +from itertools import combinations from pathlib import Path -from typing import AbstractSet, Iterable, Iterator, Mapping, Optional, Tuple, List +from typing import AbstractSet, Iterable, Iterator, List, Mapping, Optional, Tuple + +import more_itertools from adam.language import LinguisticDescription, TokenSequenceLinguisticDescription -from adam.language_specific.english import ENGLISH_BLOCK_DETERMINERS +from adam.language_specific.english import ( + ENGLISH_BLOCK_DETERMINERS, + ENGLISH_MASS_NOUNS, + ENGLISH_RECOGNIZED_PARTICULARS, +) from adam.learner import LearningExample, TopLevelLanguageLearner from adam.learner.alignments import ( LanguageConceptAlignment, @@ -13,8 +19,8 @@ PerceptionSemanticAlignment, ) from adam.learner.language_mode import LanguageMode -from adam.learner.surface_templates import MASS_NOUNS, SLOT1, SurfaceTemplate -from adam.learner.template_learner import TemplateLearner +from adam.learner.surface_templates import SLOT1, SLOT2 +from adam.learner.template_learner import SemanticTemplateLearner, TemplateLearner from adam.perception import PerceptualRepresentation from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -22,15 +28,18 @@ from adam.perception.perception_graph import PerceptionGraph from adam.semantics import ( ActionSemanticNode, + AttributeSemanticNode, LearnerSemantics, + NumberConcept, ObjectSemanticNode, + QuantificationSemanticNode, RelationSemanticNode, SemanticNode, - GROUND_OBJECT_CONCEPT, ) from attr import attrib, attrs from attr.validators import instance_of, optional -from immutablecollections import immutabledict +from immutablecollections import immutabledict, immutablelistmultidict +from vistautils.iter_utils import only class LanguageLearnerNew: @@ -44,22 +53,6 @@ def observe( pass -class NumberLearner: - """ - A strategy for learning how number is expressed in a human language. - - We assume the learner has built-in awareness that "number" is a concept - which will be expressed in human language, - and is on the lookout to figure out *how* it is expressed. - """ - - def surface_template_for_count(self, count: int) -> Optional[SurfaceTemplate]: - """ - Given the number of instances of some object, get the `SurfaceTemplate` used to - describe its number information, if known. - """ - - @attrs class IntegratedTemplateLearner( TopLevelLanguageLearner[ @@ -71,23 +64,38 @@ class IntegratedTemplateLearner( and actions all at once. """ - object_learner: TemplateLearner = attrib(validator=instance_of(TemplateLearner)) + object_learner: TemplateLearner = attrib( + validator=instance_of(TemplateLearner), kw_only=True + ) + + number_learner: SemanticTemplateLearner = attrib( + validator=instance_of(SemanticTemplateLearner), kw_only=True + ) + + _language_mode: LanguageMode = attrib( + validator=instance_of(LanguageMode), kw_only=True + ) + """ + Why does a language-independent learner need to know what language it is learning? + This is to support language-specific logic for English determiners, + which is out-of-scope for ADAM and therefore hard-coded. + """ + attribute_learner: Optional[TemplateLearner] = attrib( - validator=optional(instance_of(TemplateLearner)), default=None + validator=optional(instance_of(TemplateLearner)), default=None, kw_only=True ) relation_learner: Optional[TemplateLearner] = attrib( - validator=optional(instance_of(TemplateLearner)), default=None + validator=optional(instance_of(TemplateLearner)), default=None, kw_only=True ) action_learner: Optional[TemplateLearner] = attrib( - validator=optional(instance_of(TemplateLearner)), default=None - ) - number_learner: Optional[NumberLearner] = attrib( - validator=optional(instance_of(NumberLearner)), default=None + validator=optional(instance_of(TemplateLearner)), default=None, kw_only=True ) - _max_attributes_per_word: int = attrib(validator=instance_of(int), default=3) + _max_attributes_per_word: int = attrib( + validator=instance_of(int), default=3, kw_only=True + ) _observation_num: int = attrib(init=False, default=0) _sub_learners: List[TemplateLearner] = attrib(init=False) @@ -187,11 +195,199 @@ def _linguistic_descriptions_from_semantics( learner_semantics = LearnerSemantics.from_nodes(semantic_nodes) ret: List[Tuple[Tuple[str, ...], float]] = [] - ret.extend(self._to_tokens(learner_semantics)) + + # To handle numbers/plurality, we build copies of the semantics pruned + # to contain only those things which are predicated in common of + # each set of multiple copies of the same object type. + # The case of single objects is handled within this as a special case. + for quantification_sub_semantics in self._quantification_sub_semantics( + learner_semantics + ): + ret.extend(self._to_tokens(quantification_sub_semantics)) + return immutabledict( (TokenSequenceLinguisticDescription(tokens), score) for (tokens, score) in ret ) + def _quantification_sub_semantics( + self, semantics: LearnerSemantics + ) -> Iterable[LearnerSemantics]: + """ + Our approach to handling plurals and other quantifiers is + to identify when there are multiple objects of the same type, + and produce representations of all the aspects of the semantics + which are common to all of them. + These "quantification sub-semantics", + along with indications of the quantification information, + can then be turned into tokens by `_to_tokens`. + """ + # Below we will use the running example of a scene which has + # * three balls (b_1,b_2,b_3), two of which are red (b_1,b_2) + # and one of which is green ( b_3) + # * two tables (t_1, t_2). One red ball (b_1) is on one table (t_1), + # and both other balls (b2, b3) are on another (t_2). + + # First, determine groups of objects with the same concept + # (e.g. that there are three balls and two tables in a scene). + concept_to_objects = immutablelistmultidict( + (object_.concept, object_) for object_ in semantics.objects + ) + # Second, for each group, iterate determine all subsets of the objects. + # e.g. for balls, ball by itself, {b_1, b_2}, {b_1, b_3}, {b_2, b_3}, {b_1, b_2, b_3} + # and for tables, each table by itself and {t_1, t_2}. + concept_to_object_combinations = immutablelistmultidict( + (concept, combo) + for (concept, objects) in concept_to_objects.as_dict().items() + for combo in more_itertools.powerset(objects) + # exclude the empty set + if combo + ) + + # Now we take all combinations of subsets. + # e.g. ({b_1, b_2}, t_1), ({b_1, b_2}, {t_1, t_2}), etc. + for object_grouping in itertools.product( + *concept_to_object_combinations.value_groups() + ): + # For each combination of subsets, we determine what original_attributes, relations, and verbs + # hold true for *all* the the selected elements of a type, + # taking into account the collapsing together of other nodes. + # For example, if {b_1, b_2) are grouped, + # then "red" is a valid modifier for the collapsed group. + # on(table_obj) is a valid modified for {b_1, b_2} if t_1 and t_2 are grouped, + # but it is not if they are not grouped. + # Note this allows only one grouping per object type, + # so we cannot handle e.g. "two red balls beside three green balls" + + # We start by making new "quantified" ObjectSemanticNodes to represent each group, + # and we attach a quantification node to each. + # We will call these "quantified objects" or "Q-Objects". + # They are the only thing which will appear in the returned "quantified semantics". + # The objects in the original semantics we will call "original objects" or "O-Objects". + original_object_to_quantified_object = {} + quantified_object_to_original_objects_builder = [] + quantified_semantics: List[SemanticNode] = [] + for concept, original_objects_for_concept in zip( + concept_to_object_combinations.keys(), object_grouping + ): + num_objects = len(original_objects_for_concept) + if num_objects > 1: + quantified_object = ObjectSemanticNode(concept) + quantified_semantics.append(quantified_object) + quantified_semantics.append( + QuantificationSemanticNode( + NumberConcept(num_objects, debug_string=str(num_objects)), + slot_fillings=[(SLOT1, quantified_object)], + ) + ) + for original_object in original_objects_for_concept: + original_object_to_quantified_object[ + original_object + ] = quantified_object + quantified_object_to_original_objects_builder.append( + (quantified_object, original_object) + ) + else: + # If there's only one instance of a concept, + # we can just use the original object itself as the "quantified object". + original_object = only(original_objects_for_concept) + quantified_semantics.append(original_object) + quantified_semantics.append( + QuantificationSemanticNode( + NumberConcept(1, debug_string="1"), + slot_fillings=[(SLOT1, original_object)], + ) + ) + original_object_to_quantified_object[ + original_object + ] = original_object + quantified_object_to_original_objects_builder.append( + (original_object, original_object) + ) + + quantified_object_to_original_objects = immutablelistmultidict( + quantified_object_to_original_objects_builder + ) + + # Each attribute in the original semantics can be "projected" up to an attribute + # of a Q-Object in the quantified semantics, + # if there is a matching "original attribute" asserted for each O-Object which is + # mapped to the Q-Object. + # e.g. if b_1 and b_2 are mapped to the same Q-Object B_0, + # then you can say B_0 is red iff both b_1 and b_2 are red. + for original_attribute in semantics.attributes: + original_argument = original_attribute.slot_fillings[SLOT1] + if original_argument not in original_object_to_quantified_object: + # This is the case where e.g. there are three balls, + # but we are only including two in this particular quantified semantics. + continue + quantified_argument = original_object_to_quantified_object[ + original_argument + ] + + include_projection_in_quantified_semantics = True + other_objects_mapped_to_same_quantified_object = quantified_object_to_original_objects[ + quantified_argument + ] + + if len(other_objects_mapped_to_same_quantified_object) == 1: + # Since the original object is the same as the quantified object, + # we can just reuse the assertion object as well. + quantified_semantics.append(original_attribute) + continue + + for ( + other_original_argument_mapped_to_quantified_argument + ) in other_objects_mapped_to_same_quantified_object: + if ( + other_original_argument_mapped_to_quantified_argument + is not original_argument + ): + found_a_matching_attribute = False + for attribute in semantics.attributes: + if ( + attribute.concept == original_attribute.concept + and attribute.slot_fillings[SLOT1] + is other_original_argument_mapped_to_quantified_argument + ): + found_a_matching_attribute = True + if not found_a_matching_attribute: + include_projection_in_quantified_semantics = False + if include_projection_in_quantified_semantics: + # Note that duplicates attributes will get added to the quantified semantics + # because each of the original attributes which are projected to the + # "quantified attribute" will add a copy. + # But it all ends up in a set anyway, so it doesn't matter. + quantified_semantics.append( + AttributeSemanticNode( + concept=original_attribute.concept, + slot_fillings=[(SLOT1, quantified_argument)], + ) + ) + + # TODO: discuss difficulties with relations and actions + for assertion_set in (semantics.relations, semantics.actions): + for assertion in assertion_set: # type: ignore + all_arguments_already_quantified = True + for slot in (SLOT1, SLOT2): + original_slot_filler = assertion.slot_fillings[slot] + quantified_slot_filler = original_object_to_quantified_object[ + original_slot_filler + ] + if ( + len( + quantified_object_to_original_objects[ + quantified_slot_filler + ] + ) + > 1 + ): + all_arguments_already_quantified = False + break + if all_arguments_already_quantified: + quantified_semantics.append(assertion) + + yield LearnerSemantics.from_nodes(quantified_semantics) + def _to_tokens( self, semantics: LearnerSemantics ) -> Iterable[Tuple[Tuple[str, ...], float]]: @@ -228,28 +424,43 @@ def _to_tokens( ) return ret - def _add_determiners( - self, object_node: ObjectSemanticNode, cur_string: Tuple[str, ...] - ) -> Tuple[str, ...]: - if ( - self.object_learner._language_mode # pylint: disable=protected-access - != LanguageMode.ENGLISH - ): - return cur_string - # English-specific hack to deal with us not understanding determiners: + def _handle_quantifiers( + self, + semantics: LearnerSemantics, + object_node: ObjectSemanticNode, + cur_string: Tuple[str, ...], + ) -> Iterable[Tuple[str, ...]]: + # English-specific special case, since we don't handle learning determiner information # https://github.com/isi-vista/adam/issues/498 - # The "is lower" check is a hack to block adding a determiner to proper names. - # Ground is a specific thing so we special case this to be assigned - if object_node.concept == GROUND_OBJECT_CONCEPT: - return tuple(chain(("the",), cur_string)) - elif ( - object_node.concept.debug_string not in MASS_NOUNS - and object_node.concept.debug_string.islower() - and not cur_string[0] in ENGLISH_BLOCK_DETERMINERS - ): - return tuple(chain(("a",), cur_string)) - else: - return cur_string + block_determiners = False + if self._language_mode == LanguageMode.ENGLISH: + for attribute in semantics.objects_to_attributes[object_node]: + if attribute.concept.debug_string in ENGLISH_BLOCK_DETERMINERS: + # These are things like "your" which block determiners + block_determiners = True + if object_node.concept.debug_string in ENGLISH_MASS_NOUNS: + block_determiners = True + if object_node.concept.debug_string in ENGLISH_RECOGNIZED_PARTICULARS: + block_determiners = True + if block_determiners: + return cur_string + + found_a_quantifier = False + for quantifier in semantics.quantifiers: + if quantifier.slot_fillings[SLOT1] == object_node: + found_a_quantifier = True + for quantifier_template in self.number_learner.templates_for_concept( + quantifier.concept + ): + yield quantifier_template.instantiate( + {SLOT1: cur_string} + ).as_token_sequence() + + if not found_a_quantifier: + raise RuntimeError( + f"Every object node should have a quantifier but could not find one " + f"for {object_node}" + ) def _instantiate_object( self, object_node: ObjectSemanticNode, learner_semantics: "LearnerSemantics" @@ -269,9 +480,11 @@ def _instantiate_object( # See https://github.com/isi-vista/adam/issues/794 . # relations_for_object = learner_semantics.objects_to_relation_in_slot1[object_node] - for template in self.object_learner.templates_for_concept(object_node.concept): + for object_template in self.object_learner.templates_for_concept( + object_node.concept + ): - cur_string = template.instantiate( + object_string = object_template.instantiate( template_variable_to_filler=immutabledict() ).as_token_sequence() @@ -283,6 +496,7 @@ def _instantiate_object( # +1 because the range starts at 0 num_attributes + 1, ): + cur_string = object_string for attribute in attribute_combinations: # we know, but mypy does not, that self.attribute_learner is not None for ( @@ -290,13 +504,18 @@ def _instantiate_object( ) in self.attribute_learner.templates_for_concept( # type: ignore attribute.concept ): - yield self._add_determiners( + for quantified in self._handle_quantifiers( + learner_semantics, object_node, attribute_template.instantiate( template_variable_to_filler={SLOT1: cur_string} ).as_token_sequence(), - ) - yield self._add_determiners(object_node, cur_string) + ): + yield quantified + for quantified in self._handle_quantifiers( + learner_semantics, object_node, object_string + ): + yield quantified def _instantiate_relation( self, relation_node: RelationSemanticNode, learner_semantics: "LearnerSemantics" diff --git a/adam/learner/learner_utils.py b/adam/learner/learner_utils.py index ec6a05b06..a6fe8f603 100644 --- a/adam/learner/learner_utils.py +++ b/adam/learner/learner_utils.py @@ -1,49 +1,50 @@ +import itertools import logging +from enum import Enum, auto from typing import ( - Mapping, - Tuple, - Union, - cast, - List, AbstractSet, + Callable, Dict, Iterable, + List, + Mapping, Optional, - Callable, + Tuple, + Union, + cast, ) -import itertools -from adam.learner.alignments import LanguagePerceptionSemanticAlignment -from attr.validators import instance_of + from networkx import ( - number_weakly_connected_components, DiGraph, + number_weakly_connected_components, weakly_connected_components, ) -from attr import attrib, attrs -from enum import Enum, auto + from adam.language import LinguisticDescription, TokenSequenceLinguisticDescription from adam.learner import LearningExample -from adam.learner.alignments import LanguageConceptAlignment +from adam.learner.alignments import ( + LanguageConceptAlignment, + LanguagePerceptionSemanticAlignment, +) from adam.learner.language_mode import LanguageMode from adam.learner.perception_graph_template import PerceptionGraphTemplate -from adam.perception import PerceptualRepresentation -from adam.perception.developmental_primitive_perception import ( - DevelopmentalPrimitivePerceptionFrame, -) from adam.learner.surface_templates import ( STANDARD_SLOT_VARIABLES, SurfaceTemplate, SurfaceTemplateBoundToSemanticNodes, ) - +from adam.perception import PerceptualRepresentation +from adam.perception.developmental_primitive_perception import ( + DevelopmentalPrimitivePerceptionFrame, +) from adam.perception.perception_graph import ( + IsPathPredicate, + NodePredicate, ObjectSemanticNodePerceptionPredicate, - PerceptionGraphPatternMatch, PerceptionGraphPattern, - IsPathPredicate, - RegionPredicate, + PerceptionGraphPatternMatch, REFERENCE_OBJECT_LABEL, - NodePredicate, + RegionPredicate, RelationTypeIsPredicate, ) from adam.semantics import ( @@ -52,9 +53,10 @@ SemanticNode, SyntaxSemanticsVariable, ) -from immutablecollections import immutabledict, immutableset, ImmutableSet - from adam.utils.networkx_utils import subgraph +from attr import attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableSet, immutabledict, immutableset from vistautils.span import Span diff --git a/adam/learner/object_recognizer.py b/adam/learner/object_recognizer.py index 08a1d7f7d..9ce6a929f 100644 --- a/adam/learner/object_recognizer.py +++ b/adam/learner/object_recognizer.py @@ -2,37 +2,37 @@ from itertools import chain from typing import AbstractSet, Iterable, List, Mapping, Sequence, Set, Tuple, Union -from adam.axis import GeonAxis -from adam.language_specific.chinese.chinese_phase_1_lexicon import ( - GAILA_PHASE_1_CHINESE_LEXICON, -) -from adam.learner.language_mode import LanguageMode from contexttimer import Timer from more_itertools import first from networkx import DiGraph from adam.axes import GRAVITATIONAL_DOWN_TO_UP_AXIS, LEARNER_AXES, WORLD_AXES +from adam.axis import GeonAxis from adam.language import LinguisticDescription +from adam.language_specific.chinese.chinese_phase_1_lexicon import ( + GAILA_PHASE_1_CHINESE_LEXICON, +) from adam.learner.alignments import ( LanguageConceptAlignment, LanguagePerceptionSemanticAlignment, PerceptionSemanticAlignment, ) +from adam.learner.language_mode import LanguageMode from adam.ontology import OntologyNode from adam.ontology.ontology import Ontology from adam.ontology.phase1_ontology import ( + BIGGER_THAN, GAILA_PHASE_1_ONTOLOGY, PART_OF, PHASE_1_CURRICULUM_OBJECTS, - BIGGER_THAN, SMALLER_THAN, ) from adam.ontology.phase1_spatial_relations import Region from adam.perception import ( GROUND_PERCEPTION, LEARNER_PERCEPTION, - ObjectPerception, MatchMode, + ObjectPerception, ) from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.perception_graph import ( @@ -50,9 +50,9 @@ ) from adam.semantics import ( Concept, + GROUND_OBJECT_CONCEPT, ObjectConcept, ObjectSemanticNode, - GROUND_OBJECT_CONCEPT, ) from adam.utils.networkx_utils import subgraph from attr import attrib, attrs diff --git a/adam/learner/objects.py b/adam/learner/objects.py index 37e038d56..eb0e7caf0 100644 --- a/adam/learner/objects.py +++ b/adam/learner/objects.py @@ -3,10 +3,11 @@ from pathlib import Path from random import Random from typing import AbstractSet, Iterable, List, Optional, Sequence, Union + +from adam.language import LinguisticDescription from adam.language_specific.chinese.chinese_phase_1_lexicon import ( GAILA_PHASE_1_CHINESE_LEXICON, ) -from adam.language import LinguisticDescription from adam.learner import ( LearningExample, get_largest_matching_pattern, @@ -26,8 +27,8 @@ from adam.learner.perception_graph_template import PerceptionGraphTemplate from adam.learner.pursuit import ( AbstractPursuitLearner, - HypothesisLogger, AbstractPursuitLearnerNew, + HypothesisLogger, ) from adam.learner.subset import ( AbstractTemplateSubsetLearner, @@ -38,20 +39,20 @@ SurfaceTemplateBoundToSemanticNodes, ) from adam.learner.template_learner import ( - AbstractTemplateLearner, - AbstractTemplateLearnerNew, + AbstractPerceptualTemplateLearner, + AbstractPerceptualTemplateLearnerNew, TemplateLearner, ) from adam.ontology.phase1_ontology import GAILA_PHASE_1_ONTOLOGY from adam.ontology.phase1_spatial_relations import Region -from adam.perception import ObjectPerception, PerceptualRepresentation, MatchMode +from adam.perception import MatchMode, ObjectPerception, PerceptualRepresentation from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, RgbColorPerception, ) from adam.perception.perception_graph import PerceptionGraph, PerceptionGraphPattern -from adam.semantics import Concept, ObjectConcept, GROUND_OBJECT_CONCEPT +from adam.semantics import Concept, GROUND_OBJECT_CONCEPT, ObjectConcept from adam.utils import networkx_utils from attr import attrib, attrs, evolve from attr.validators import instance_of, optional @@ -65,7 +66,7 @@ from vistautils.parameters import Parameters -class AbstractObjectTemplateLearnerNew(AbstractTemplateLearnerNew): +class AbstractObjectTemplateLearnerNew(AbstractPerceptualTemplateLearnerNew): # pylint:disable=abstract-method def _can_learn_from( self, language_perception_semantic_alignment: LanguagePerceptionSemanticAlignment @@ -111,7 +112,7 @@ def _candidate_templates( ) -class AbstractObjectTemplateLearner(AbstractTemplateLearner, ABC): +class AbstractObjectTemplateLearner(AbstractPerceptualTemplateLearner, ABC): def _assert_valid_input( self, to_check: Union[ diff --git a/adam/learner/perception_graph_template.py b/adam/learner/perception_graph_template.py index 37a3ac80c..bed109738 100644 --- a/adam/learner/perception_graph_template.py +++ b/adam/learner/perception_graph_template.py @@ -2,26 +2,26 @@ from pathlib import Path from typing import Any, Callable, List, Mapping, Optional -from attr.validators import deep_mapping, instance_of from networkx import number_weakly_connected_components from adam.ontology.ontology import Ontology from adam.perception import MatchMode from adam.perception.perception_graph import ( GraphLogger, + NodePredicate, ObjectSemanticNodePerceptionPredicate, PerceptionGraph, PerceptionGraphPattern, raise_graph_exception, - NodePredicate, ) from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs +from attr.validators import deep_mapping, instance_of from immutablecollections import ( ImmutableDict, + ImmutableSetMultiDict, immutabledict, immutablesetmultidict, - ImmutableSetMultiDict, ) from immutablecollections.converter_utils import _to_immutabledict diff --git a/adam/learner/prepositions.py b/adam/learner/prepositions.py index a59c458de..6009deb17 100644 --- a/adam/learner/prepositions.py +++ b/adam/learner/prepositions.py @@ -1,12 +1,13 @@ from abc import ABC from pathlib import Path from typing import Iterable, Mapping, Optional, Sequence, Union -from adam.learner.language_mode import LanguageMode + from more_itertools import flatten from networkx import all_shortest_paths, subgraph from adam.language import LinguisticDescription from adam.learner import LearningExample, get_largest_matching_pattern +from adam.learner.language_mode import LanguageMode from adam.learner.learner_utils import assert_static_situation from adam.learner.object_recognizer import ( ObjectRecognizer, @@ -16,8 +17,8 @@ from adam.learner.pursuit import AbstractPursuitLearner from adam.learner.subset import AbstractTemplateSubsetLearner from adam.learner.surface_templates import SLOT1, SLOT2, SurfaceTemplate -from adam.learner.template_learner import AbstractTemplateLearner -from adam.perception import ObjectPerception, PerceptualRepresentation, MatchMode +from adam.learner.template_learner import AbstractPerceptualTemplateLearner +from adam.perception import MatchMode, ObjectPerception, PerceptualRepresentation from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -35,7 +36,7 @@ @attrs -class AbstractPrepositionTemplateLearner(AbstractTemplateLearner, ABC): +class AbstractPrepositionTemplateLearner(AbstractPerceptualTemplateLearner, ABC): # mypy doesn't realize that fields without defaults can come after those with defaults # if they are keyword-only. _object_recognizer: ObjectRecognizer = attrib( # type: ignore diff --git a/adam/learner/pursuit.py b/adam/learner/pursuit.py index f4e27f1bc..5b4e9c7f4 100644 --- a/adam/learner/pursuit.py +++ b/adam/learner/pursuit.py @@ -4,6 +4,7 @@ from pathlib import Path from random import Random from typing import ( + AbstractSet, Any, Dict, Iterable, @@ -13,14 +14,9 @@ Sequence, Set, Tuple, - AbstractSet, ) -from attr import Factory, attrib, attrs -from attr.validators import in_, instance_of, optional -from immutablecollections import immutabledict, immutableset from more_itertools import first -from vistautils.range import Range from adam.learner import LanguagePerceptionSemanticAlignment from adam.learner.perception_graph_template import PerceptionGraphTemplate @@ -29,8 +25,8 @@ SurfaceTemplateBoundToSemanticNodes, ) from adam.learner.template_learner import ( - AbstractTemplateLearner, - AbstractTemplateLearnerNew, + AbstractPerceptualTemplateLearner, + AbstractPerceptualTemplateLearnerNew, ) from adam.ontology.ontology import Ontology from adam.perception.deprecated import LanguageAlignedPerception @@ -40,6 +36,10 @@ PerceptionGraph, ) from adam.semantics import Concept +from attr import Factory, attrib, attrs +from attr.validators import in_, instance_of, optional +from immutablecollections import immutabledict, immutableset +from vistautils.range import Range @attrs @@ -73,7 +73,7 @@ def log_hypothesis_graph( @attrs -class AbstractPursuitLearner(AbstractTemplateLearner, ABC): +class AbstractPursuitLearner(AbstractPerceptualTemplateLearner, ABC): """ An implementation of `LanguageLearner` for pursuit learning as a base for different pursuit based learners. Paper on Pursuit Learning Algorithm: https://www.ling.upenn.edu/~ycharles/papers/pursuit-final.pdf @@ -553,7 +553,7 @@ def _are_isomorphic( @attrs -class AbstractPursuitLearnerNew(AbstractTemplateLearnerNew, ABC): +class AbstractPursuitLearnerNew(AbstractPerceptualTemplateLearnerNew, ABC): """ An implementation of `TemplateLearnerNew` for pursuit learning as a base for different pursuit based learners. Paper on Pursuit Learning Algorithm: https://www.ling.upenn.edu/~ycharles/papers/pursuit-final.pdf diff --git a/adam/learner/quantifers.py b/adam/learner/quantifers.py new file mode 100644 index 000000000..348e641b8 --- /dev/null +++ b/adam/learner/quantifers.py @@ -0,0 +1,342 @@ +from abc import ABC +from collections import defaultdict +from enum import Enum, auto +from math import log +from pathlib import Path +from typing import AbstractSet, Dict, Iterable, List + +from more_itertools import only + +from adam.learner import LanguageConceptAlignment, LanguageMode, SurfaceTemplate +from adam.learner.surface_templates import SLOT1 +from adam.learner.template_learner import SemanticTemplateLearner +from adam.semantics import ( + Concept, + GROUND_OBJECT_CONCEPT, + LearnerSemantics, + NumberConcept, + ObjectConcept, +) +from attr import Factory, attrib, attrs +from attr.validators import instance_of +from immutablecollections import immutableset, immutablesetmultidict +from vistautils.span import Span + +CHINESE_NO_QUANTIFIER_TEMPLATE = SurfaceTemplate( + [SLOT1], language_mode=LanguageMode.CHINESE +) + + +class QuantifierTemplateLearner( + SemanticTemplateLearner, ABC +): # pylint:disable=abstract-method + @staticmethod + def pretrained_for_language_mode( + language_mode: LanguageMode + ) -> "QuantifierTemplateLearner": + """ + Get a `QuantifierTemplateLearner` which already knows the correct number information + for a language. + + This is useful when you are experimenting with other things and don't want to wait + for numbers to be learned + (or the training data for them is not included in your curriculum). + """ + if language_mode == LanguageMode.ENGLISH: + return PretrainedEnglishQuantifiers() + elif language_mode == LanguageMode.CHINESE: + return PretrainedChineseQuantifiers() + else: + raise RuntimeError(f"No pretrained quantifiers available for {language_mode}") + + +class LinguisticNumber(Enum): + SINGULAR = auto() + DUAL = auto() + PLURAL = auto() + + +NO_OP_TEMPLATE_ENGLISH = SurfaceTemplate((SLOT1,), language_mode=LanguageMode.ENGLISH) +NO_OP_TEMPLATE_CHINESE = SurfaceTemplate((SLOT1,), language_mode=LanguageMode.CHINESE) + + +@attrs(frozen=True) +class ToleranceRuleQuantifierTemplateLearner(SemanticTemplateLearner): + language_mode: LanguageMode = attrib(validator=instance_of(LanguageMode)) + min_types_to_lexicalize: int = attrib(default=5) + + _lexicalized_number_to_template: Dict[LinguisticNumber, SurfaceTemplate] = attrib( + init=False, default=Factory(dict) + ) + _number_to_concept_to_hypotheses: Dict[ + LinguisticNumber, Dict[ObjectConcept, List[SurfaceTemplate]] + ] = attrib( + init=False, default=Factory(lambda: defaultdict(lambda: defaultdict(list))) + ) + _number_to_template_to_count: Dict[ + LinguisticNumber, Dict[SurfaceTemplate, int] + ] = attrib(init=False, default=Factory(lambda: defaultdict(lambda: defaultdict(int)))) + + _dont_know_template: SurfaceTemplate = attrib(init=False) + """ + Template to return if we haven't yet learned how to express a given number. + """ + + @_dont_know_template.default + def _default_dont_know_template(self) -> SurfaceTemplate: + if self.language_mode == LanguageMode.ENGLISH: + return NO_OP_TEMPLATE_ENGLISH + elif self.language_mode == LanguageMode.CHINESE: + return NO_OP_TEMPLATE_CHINESE + else: + raise RuntimeError( + f"Don't know how to make a no-op template for {self.language_mode}" + ) + + def learn_from( + self, + language_concept_alignment: LanguageConceptAlignment, + semantics: LearnerSemantics, + ) -> None: + # First, if there are multiple token spans aligned to objects of the same type + # (e.g. the red boxes beside the pink boxes) + # we bail out and don't try to learn anything at all, + # because it would violate some assumptions we make below. + object_types_to_language_span_of_aligned_objects = immutablesetmultidict( + (object_node.concept, token_span) + for ( + object_node, + token_span, + ) in language_concept_alignment.node_to_language_span.items() + ) + + if any( + len(spans_aligned_to_objects_of_same_type) > 1 + for spans_aligned_to_objects_of_same_type in object_types_to_language_span_of_aligned_objects.value_groups() + ): + return + + # TODO: the below assumes the language marks number obligatorily if it marks it at all. + # Do all do so? + + number_properties_modified_on_this_update = [] + + # Otherwise, we learn for each object_type separately + # (e.g. for "the red boxes and the green cups" we learn for boxes and cups separately) + for object_type in object_types_to_language_span_of_aligned_objects: + # # For English-special case determiner cases, bail out and don't try to learn. + # if ( + # self.language_mode == LanguageMode.ENGLISH + # and is_english_determiner_special_case(object_type) + # ): + # continue + + # We count how many there are of the relevant object type + # and bucket them as singular, dual, plural. + num_objects_of_type = 0 + for object_node in semantics.objects: + if object_node.concept == object_type: + num_objects_of_type += 1 + + if num_objects_of_type == 0: + raise RuntimeError("This should be impossible") + elif num_objects_of_type == 1: + number_property = LinguisticNumber.SINGULAR + elif num_objects_of_type == 2: + number_property = LinguisticNumber.DUAL + else: + number_property = LinguisticNumber.PLURAL + + if number_property in self._lexicalized_number_to_template: + # We already "lexicalized" how to express this number, + # so no need to keep trying to learn. + continue + + object_span = only( + object_types_to_language_span_of_aligned_objects[object_type] + ) + + # We then hypothesize ways that number is being expressed in this situation + for surface_template_hypothesis in self._number_expression_hypotheses( + object_span, language_concept_alignment + ): + self._number_to_template_to_count[number_property][ + surface_template_hypothesis + ] += 1 + if ( + surface_template_hypothesis + not in self._number_to_concept_to_hypotheses[number_property][ + object_type + ] + ): + self._number_to_concept_to_hypotheses[number_property][ + object_type + ].append(surface_template_hypothesis) + number_properties_modified_on_this_update.append(number_property) + + # Now check if we can lexicalize any of our number properties. + for number_property in immutableset(number_properties_modified_on_this_update): + if number_property not in self._lexicalized_number_to_template: + concept_to_hypothesis = self._number_to_concept_to_hypotheses[ + number_property + ] + template_to_count = self._number_to_template_to_count[number_property] + + # Loop through templates in descending order of frequency. + hypotheses_by_decreasing_frequency = [ + hypothesis + for (hypothesis, count) in sorted( + template_to_count.items(), key=lambda x: x[1], reverse=True + ) + ] + for hypothesis in hypotheses_by_decreasing_frequency: + votes_for = 0 + votes_against = 0 + for concept in concept_to_hypothesis: + # A concept is a vote "for" a template if it occurs with that template + # for the given number. + if hypothesis in concept_to_hypothesis[concept]: + votes_for += 1 + # It is a vote "against" the template if it occurs with some *other* + # template + # for the given number and not this template. + elif concept_to_hypothesis[concept]: + votes_against += 1 + # If the number of vote "for" exceeds the number of votes "against" + # by the TP threshold, we lexicalize. + num_types = votes_for + votes_against + if ( + votes_for > self.min_types_to_lexicalize + and votes_against <= num_types / log(num_types) + ): + self._lexicalized_number_to_template[number_property] = hypothesis + break + + def templates_for_concept(self, concept: Concept) -> AbstractSet[SurfaceTemplate]: + if isinstance(concept, NumberConcept): + if concept.number == 1: + linguistic_number = LinguisticNumber.SINGULAR + elif concept.number == 2: + linguistic_number = LinguisticNumber.DUAL + else: + linguistic_number = LinguisticNumber.PLURAL + else: + raise RuntimeError( + f"Should only be called for number concepts, but got {concept}" + ) + + return immutableset( + [ + self._lexicalized_number_to_template.get( + linguistic_number, self._dont_know_template + ) + ] + ) + + def _number_expression_hypotheses( + self, span_for_object: Span, language_concept_alignment: LanguageConceptAlignment + ) -> Iterable[SurfaceTemplate]: + ret = [] + + object_at_left_edge = span_for_object.start == 0 + token_sequence = language_concept_alignment.language.as_token_sequence() + object_at_right_edge = span_for_object.end == len(token_sequence) + + # We currently limit ourselves to cases + # where the object + plural marker is the entire utterance. + + # Any tokens immediately before or after the expression of an object + # are candidate expressions of pluralization. + preceding_token_index = span_for_object.start - 1 + if ( + not object_at_left_edge + and not language_concept_alignment.token_index_is_aligned( + preceding_token_index + ) + and object_at_right_edge + ): + ret.append( + SurfaceTemplate( + [token_sequence[0], SLOT1], language_mode=self.language_mode + ) + ) + following_token_index = span_for_object.end + 1 + if ( + not object_at_right_edge + and not language_concept_alignment.token_index_is_aligned( + following_token_index + ) + and object_at_left_edge + ): + ret.append( + SurfaceTemplate( + [SLOT1, token_sequence[-1]], language_mode=self.language_mode + ) + ) + + # We will consider a no-op hypothesis only if everything on both sides + # is aready aligned + if object_at_left_edge and object_at_right_edge: + ret.append(SurfaceTemplate([SLOT1], language_mode=self.language_mode)) + + return immutableset(ret) + + +class AbstractPretrainedQuantifiers( + QuantifierTemplateLearner +): # pylint:disable=abstract-method + def learn_from( + self, + language_concept_alignment: LanguageConceptAlignment, + semantics: LearnerSemantics, + ) -> None: + # Pretrained - nothing to learn. + pass + + def log_hypotheses(self, log_output_path: Path) -> None: + pass + + +THE_TEMPLATE = SurfaceTemplate(["the", SLOT1], language_mode=LanguageMode.ENGLISH) +A_TEMPLATE = SurfaceTemplate(["a", SLOT1], language_mode=LanguageMode.ENGLISH) +PLURAL_TEMPLATE = SurfaceTemplate([SLOT1, "s"], language_mode=LanguageMode.ENGLISH) +TWO_TEMPLATE = SurfaceTemplate(["two", SLOT1, "s"], language_mode=LanguageMode.ENGLISH) +MANY_TEMPLATE = SurfaceTemplate(["many", SLOT1, "s"], language_mode=LanguageMode.ENGLISH) +ENGLISH_NO_QUANTIFIER_TEMPLATE = SurfaceTemplate( + [SLOT1], language_mode=LanguageMode.ENGLISH +) + + +class PretrainedEnglishQuantifiers(AbstractPretrainedQuantifiers): + def templates_for_concept(self, concept: Concept) -> AbstractSet[SurfaceTemplate]: + if not isinstance(concept, NumberConcept): + raise RuntimeError( + f"Quantification learner only understands NumberConcepts, but got " + f"{concept}" + ) + + number = concept.number + + ret = [] + # Ground is a specific thing so we special case this to be assigned + if concept == GROUND_OBJECT_CONCEPT: + ret.append(THE_TEMPLATE) + elif number == 1: + ret.append(A_TEMPLATE) + else: + ret.append(PLURAL_TEMPLATE) + if number == 2: + ret.append(TWO_TEMPLATE) + elif number > 2: + ret.append(MANY_TEMPLATE) + + if not ret: + ret.append(ENGLISH_NO_QUANTIFIER_TEMPLATE) + + return immutableset(ret) + + +class PretrainedChineseQuantifiers(AbstractPretrainedQuantifiers): + def templates_for_concept(self, concept: Concept) -> AbstractSet[SurfaceTemplate]: + # TODO: this is wrong, but classifiers make things complicated in Chinese + return immutableset([CHINESE_NO_QUANTIFIER_TEMPLATE]) diff --git a/adam/learner/relations.py b/adam/learner/relations.py index cf235d52b..9ab856743 100644 --- a/adam/learner/relations.py +++ b/adam/learner/relations.py @@ -1,22 +1,23 @@ -from abc import ABC -from typing import AbstractSet, Optional, Iterable, Tuple import itertools +from abc import ABC +from typing import AbstractSet, Iterable, Optional, Tuple + from adam.learner import LanguagePerceptionSemanticAlignment, PerceptionSemanticAlignment +from adam.learner.learner_utils import AlignmentSlots, candidate_templates from adam.learner.perception_graph_template import PerceptionGraphTemplate from adam.learner.subset import AbstractTemplateSubsetLearnerNew from adam.learner.surface_templates import SurfaceTemplateBoundToSemanticNodes -from attr import attrs -from adam.learner.template_learner import AbstractTemplateLearnerNew +from adam.learner.template_learner import AbstractPerceptualTemplateLearnerNew from adam.perception import MatchMode from adam.semantics import RelationConcept +from attr import attrs from immutablecollections import immutableset, immutablesetmultidict -from adam.learner.learner_utils import candidate_templates, AlignmentSlots _MAXIMUM_RELATION_TEMPLATE_TOKEN_LENGTH = 5 @attrs -class AbstractRelationTemplateLearnerNew(AbstractTemplateLearnerNew, ABC): +class AbstractRelationTemplateLearnerNew(AbstractPerceptualTemplateLearnerNew, ABC): # pylint:disable=abstract-method def _candidate_templates( self, language_perception_semantic_alignment: LanguagePerceptionSemanticAlignment diff --git a/adam/learner/subset.py b/adam/learner/subset.py index d560f54bc..4f5726fc9 100644 --- a/adam/learner/subset.py +++ b/adam/learner/subset.py @@ -3,10 +3,6 @@ from pathlib import Path from typing import AbstractSet, Dict, Iterable, Mapping, Optional, Sequence, Set, Tuple -from attr import Factory, attrib, attrs -from attr.validators import instance_of -from immutablecollections import ImmutableSet, immutabledict, immutableset - from adam.language import TokenSequenceLinguisticDescription from adam.learner.alignments import LanguagePerceptionSemanticAlignment from adam.learner.perception_graph_template import PerceptionGraphTemplate @@ -15,17 +11,20 @@ SurfaceTemplateBoundToSemanticNodes, ) from adam.learner.template_learner import ( - AbstractTemplateLearner, - AbstractTemplateLearnerNew, + AbstractPerceptualTemplateLearner, + AbstractPerceptualTemplateLearnerNew, ) from adam.ontology.ontology import Ontology from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.perception_graph import DebugCallableType from adam.semantics import Concept +from attr import Factory, attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableSet, immutabledict, immutableset @attrs -class AbstractSubsetLearner(AbstractTemplateLearner, ABC): +class AbstractSubsetLearner(AbstractPerceptualTemplateLearner, ABC): _surface_template_to_hypothesis: Dict[ SurfaceTemplate, PerceptionGraphTemplate ] = attrib(init=False, default=Factory(dict)) @@ -121,7 +120,7 @@ def _post_process_descriptions( @attrs -class AbstractSubsetLearnerNew(AbstractTemplateLearnerNew, ABC): +class AbstractSubsetLearnerNew(AbstractPerceptualTemplateLearnerNew, ABC): _beam_size: int = attrib(validator=instance_of(int), kw_only=True) _concept_to_hypotheses: Dict[Concept, ImmutableSet[PerceptionGraphTemplate]] = attrib( init=False, default=Factory(dict) @@ -329,7 +328,9 @@ def _fallback_templates( @attrs # pylint:disable=abstract-method -class AbstractTemplateSubsetLearner(AbstractSubsetLearner, AbstractTemplateLearner, ABC): +class AbstractTemplateSubsetLearner( + AbstractSubsetLearner, AbstractPerceptualTemplateLearner, ABC +): def log_hypotheses(self, log_output_path: Path) -> None: logging.info( "Logging %s hypotheses to %s", @@ -345,7 +346,7 @@ def log_hypotheses(self, log_output_path: Path) -> None: class AbstractTemplateSubsetLearnerNew( - AbstractSubsetLearnerNew, AbstractTemplateLearnerNew, ABC + AbstractSubsetLearnerNew, AbstractPerceptualTemplateLearnerNew, ABC ): # pylint:disable=abstract-method def log_hypotheses(self, log_output_path: Path) -> None: diff --git a/adam/learner/surface_templates.py b/adam/learner/surface_templates.py index 025db34c3..93931fb79 100644 --- a/adam/learner/surface_templates.py +++ b/adam/learner/surface_templates.py @@ -2,9 +2,11 @@ Representations of template-with-slots-like patterns over token strings. """ from typing import List, Mapping, Optional, Tuple, Union + from more_itertools import quantify from adam.language import TokenSequenceLinguisticDescription +from adam.language_specific.english import ENGLISH_MASS_NOUNS from adam.learner.language_mode import LanguageMode from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs @@ -61,7 +63,7 @@ def instantiate( and element in self._determiner_prefix_slots and len(filler_words) == 1 and filler_words[0][0].islower() - and filler_words[0] not in MASS_NOUNS + and filler_words[0] not in ENGLISH_MASS_NOUNS ): output_tokens.append("a") output_tokens.extend(filler_words) @@ -183,7 +185,3 @@ class SurfaceTemplateBoundToSemanticNodes: SLOT6 = SyntaxSemanticsVariable("slot6") STANDARD_SLOT_VARIABLES = (SLOT1, SLOT2, SLOT3, SLOT4, SLOT5, SLOT6) - -# These nouns are hard-coded not to receive determiners -# See https://github.com/isi-vista/adam/issues/498 -MASS_NOUNS = ["juice", "water", "milk"] diff --git a/adam/learner/template_learner.py b/adam/learner/template_learner.py index 34cba4570..9d2e3e313 100644 --- a/adam/learner/template_learner.py +++ b/adam/learner/template_learner.py @@ -1,14 +1,13 @@ import logging - -from attr.validators import instance_of from abc import ABC, abstractmethod -from typing import AbstractSet, Iterable, List, Mapping, Sequence, Tuple, Union, cast, Set +from typing import AbstractSet, Iterable, List, Mapping, Sequence, Set, Tuple, Union, cast from more_itertools import one from adam.language import LinguisticDescription, TokenSequenceLinguisticDescription from adam.learner import ComposableLearner, LearningExample, TopLevelLanguageLearner from adam.learner.alignments import ( + LanguageConceptAlignment, LanguagePerceptionSemanticAlignment, PerceptionSemanticAlignment, ) @@ -19,33 +18,69 @@ ) from adam.learner.object_recognizer import ( PerceptionGraphFromObjectRecognizer, - replace_match_root_with_object_semantic_node, _get_root_object_perception, + replace_match_root_with_object_semantic_node, ) from adam.learner.perception_graph_template import PerceptionGraphTemplate from adam.learner.surface_templates import ( SurfaceTemplate, SurfaceTemplateBoundToSemanticNodes, ) -from adam.perception import PerceptualRepresentation, ObjectPerception, MatchMode +from adam.perception import MatchMode, ObjectPerception, PerceptualRepresentation from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, ) from adam.perception.perception_graph import PerceptionGraph, PerceptionGraphPatternMatch -from adam.semantics import Concept, ObjectConcept, ObjectSemanticNode, SemanticNode +from adam.semantics import ( + Concept, + LearnerSemantics, + ObjectConcept, + ObjectSemanticNode, + SemanticNode, +) from attr import attrib, attrs, evolve +from attr.validators import instance_of from immutablecollections import immutabledict, immutableset from vistautils.preconditions import check_state +class ConceptToTemplateMapper(ABC): + @abstractmethod + def templates_for_concept(self, concept: Concept) -> AbstractSet[SurfaceTemplate]: + pass + + +class SemanticTemplateLearner(ConceptToTemplateMapper, ABC): + """ + A learner which learns `SurfaceTemplate` from simplified predicate-argument structure + instead of from perception. + """ + + @abstractmethod + def learn_from( + self, + language_concept_alignment: LanguageConceptAlignment, + semantics: LearnerSemantics, + ) -> None: + """ + Learn from language + simplified predicate argument structure + """ + + @attrs -class AbstractTemplateLearner( +class AbstractPerceptualTemplateLearner( TopLevelLanguageLearner[ DevelopmentalPrimitivePerceptionFrame, TokenSequenceLinguisticDescription ], ABC, ): + r""" + Learn `SurfaceTemplate`\ s from perceptions. + + e.g. learn to recognize an object/attribute/relation/action by what it looks like. + """ + _observation_num: int = attrib(init=False, default=0) _language_mode: LanguageMode = attrib( validator=instance_of(LanguageMode), kw_only=True @@ -247,16 +282,14 @@ def _post_process_descriptions( ) -class TemplateLearner(ComposableLearner, ABC): +class TemplateLearner( + ComposableLearner, ConceptToTemplateMapper, ABC +): # pylint: disable=abstract-method _language_mode: LanguageMode = attrib(validator=instance_of(LanguageMode)) - @abstractmethod - def templates_for_concept(self, concept: Concept) -> AbstractSet[SurfaceTemplate]: - pass - @attrs -class AbstractTemplateLearnerNew(TemplateLearner, ABC): +class AbstractPerceptualTemplateLearnerNew(TemplateLearner, ABC): """ Super-class for learners using template-based syntax-semantics mappings. """ diff --git a/adam/learner/verbs.py b/adam/learner/verbs.py index a0cbcb659..f309a24b7 100644 --- a/adam/learner/verbs.py +++ b/adam/learner/verbs.py @@ -1,13 +1,15 @@ import itertools from abc import ABC -from typing import AbstractSet, Mapping, Union, Iterable, Optional, Tuple -from adam.learner.language_mode import LanguageMode +from typing import AbstractSet, Iterable, Mapping, Optional, Tuple, Union + from adam.language import LinguisticDescription from adam.learner import LearningExample from adam.learner.alignments import ( LanguagePerceptionSemanticAlignment, PerceptionSemanticAlignment, ) +from adam.learner.language_mode import LanguageMode +from adam.learner.learner_utils import AlignmentSlots, candidate_templates from adam.learner.object_recognizer import ( ObjectRecognizer, PerceptionGraphFromObjectRecognizer, @@ -23,10 +25,10 @@ SurfaceTemplateBoundToSemanticNodes, ) from adam.learner.template_learner import ( - AbstractTemplateLearner, - AbstractTemplateLearnerNew, + AbstractPerceptualTemplateLearner, + AbstractPerceptualTemplateLearnerNew, ) -from adam.perception import PerceptualRepresentation, MatchMode +from adam.perception import MatchMode, PerceptualRepresentation from adam.perception.deprecated import LanguageAlignedPerception from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -34,9 +36,8 @@ from adam.perception.perception_graph import PerceptionGraph from adam.semantics import ActionConcept, ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs -from immutablecollections import immutabledict, immutableset, immutablesetmultidict from attr.validators import instance_of -from adam.learner.learner_utils import candidate_templates, AlignmentSlots +from immutablecollections import immutabledict, immutableset, immutablesetmultidict # This is the maximum number of tokens we will hypothesize # as the non-argument-slots portion of a surface template for an action. @@ -44,7 +45,7 @@ @attrs -class AbstractVerbTemplateLearnerNew(AbstractTemplateLearnerNew, ABC): +class AbstractVerbTemplateLearnerNew(AbstractPerceptualTemplateLearnerNew, ABC): # pylint:disable=abstract-method def _candidate_templates( self, language_perception_semantic_alignment: LanguagePerceptionSemanticAlignment @@ -111,7 +112,7 @@ def candidate_verb_templates() -> Iterable[Tuple[AlignmentSlots, ...]]: @attrs -class AbstractVerbTemplateLearner(AbstractTemplateLearner, ABC): +class AbstractVerbTemplateLearner(AbstractPerceptualTemplateLearner, ABC): # mypy doesn't realize that fields without defaults can come after those with defaults # if they are keyword-only. _object_recognizer: ObjectRecognizer = attrib( # type: ignore diff --git a/adam/ontology/__init__.py b/adam/ontology/__init__.py index 399dd59e8..45c697b11 100644 --- a/adam/ontology/__init__.py +++ b/adam/ontology/__init__.py @@ -4,11 +4,12 @@ These ontologies are intended to be used when describing `Situation`\ s and writing `SituationTemplate`\ s. """ +from networkx import DiGraph + from attr import attrib, attrs from attr.validators import instance_of from immutablecollections import ImmutableSet, immutableset from immutablecollections.converter_utils import _to_immutableset -from networkx import DiGraph @attrs(frozen=True, slots=True, repr=False, cache_hash=True) diff --git a/adam/ontology/action_description.py b/adam/ontology/action_description.py index cfa1f4623..1c5bb4681 100644 --- a/adam/ontology/action_description.py +++ b/adam/ontology/action_description.py @@ -1,6 +1,10 @@ from itertools import chain from typing import List, Optional +from adam.ontology import OntologyNode +from adam.ontology.during import DuringAction +from adam.relation import Relation, flatten_relations +from attr import attrib, attrs from attr.validators import instance_of, optional from immutablecollections import ( ImmutableDict, @@ -16,11 +20,6 @@ _to_immutablesetmultidict, ) -from adam.ontology import OntologyNode -from adam.ontology.during import DuringAction -from adam.relation import Relation, flatten_relations -from attr import attrib, attrs - @attrs(frozen=True, slots=True, hash=None, eq=False, repr=False) class ActionDescriptionVariable: diff --git a/adam/ontology/during.py b/adam/ontology/during.py index 548b8df16..ce5384690 100644 --- a/adam/ontology/during.py +++ b/adam/ontology/during.py @@ -1,6 +1,8 @@ from itertools import chain -from typing import Generic, List, Mapping, TypeVar, Tuple, Set +from typing import Generic, List, Mapping, Set, Tuple, TypeVar +from adam.ontology.phase1_spatial_relations import SpatialPath +from adam.relation import Relation, flatten_relations from attr import attrib, attrs from immutablecollections import ( ImmutableSet, @@ -10,9 +12,6 @@ ) from immutablecollections.converter_utils import _to_immutablesetmultidict -from adam.ontology.phase1_spatial_relations import SpatialPath -from adam.relation import Relation, flatten_relations - _ObjectT = TypeVar("_ObjectT") _NewObjectT = TypeVar("_NewObjectT") diff --git a/adam/ontology/ontology.py b/adam/ontology/ontology.py index 64736bbd1..514bd3f46 100644 --- a/adam/ontology/ontology.py +++ b/adam/ontology/ontology.py @@ -1,34 +1,34 @@ from itertools import chain from typing import AbstractSet, Any, Iterable, List, Union -from attr import attrib, attrs -from attr.validators import instance_of -from immutablecollections import ( - ImmutableSet, - ImmutableSetMultiDict, - immutableset, - immutablesetmultidict, -) -from immutablecollections.converter_utils import ( - _to_immutableset, - _to_immutablesetmultidict, -) from more_itertools import only from networkx import DiGraph, ancestors, dfs_preorder_nodes, has_path, simple_cycles -from vistautils.preconditions import check_arg from adam.ontology import ( CAN_FILL_TEMPLATE_SLOT, + IS_SUBSTANCE, OntologyNode, REQUIRED_ONTOLOGY_NODES, THING, - IS_SUBSTANCE, ) # convenience method for use in Ontology from adam.ontology.action_description import ActionDescription from adam.ontology.structural_schema import ObjectStructuralSchema from adam.relation import Relation +from attr import attrib, attrs +from attr.validators import instance_of +from immutablecollections import ( + ImmutableSet, + ImmutableSetMultiDict, + immutableset, + immutablesetmultidict, +) +from immutablecollections.converter_utils import ( + _to_immutableset, + _to_immutablesetmultidict, +) +from vistautils.preconditions import check_arg def _copy_digraph(digraph: DiGraph) -> DiGraph: diff --git a/adam/ontology/phase1_ontology.py b/adam/ontology/phase1_ontology.py index aaa52a9a2..5084347a2 100644 --- a/adam/ontology/phase1_ontology.py +++ b/adam/ontology/phase1_ontology.py @@ -15,7 +15,6 @@ """ from typing import Iterable, Optional, Sequence, Tuple, TypeVar -from immutablecollections import ImmutableDict, immutabledict, immutableset from more_itertools import flatten from adam.axes import ( @@ -32,6 +31,7 @@ from adam.geon import ( CIRCULAR, CONSTANT, + CrossSectionSize, Geon, IRREGULAR, LARGE_TO_SMALL, @@ -40,21 +40,20 @@ SMALL_TO_LARGE, SMALL_TO_LARGE_TO_SMALL, SQUARE, - CrossSectionSize, ) from adam.ontology import ( ACTION, BINARY, CAN_FILL_TEMPLATE_SLOT, IN_REGION, + IS_ADDRESSEE, + IS_SPEAKER, IS_SUBSTANCE, OntologyNode, PERCEIVABLE, PROPERTY, RELATION, THING, - IS_SPEAKER, - IS_ADDRESSEE, minimal_ontology_graph, ) from adam.ontology.action_description import ( @@ -68,6 +67,8 @@ from adam.ontology.phase1_spatial_relations import ( AWAY_FROM, DISTAL, + Direction, + Distance, EXTERIOR_BUT_IN_CONTACT, FROM, GRAVITATIONAL_DOWN, @@ -78,8 +79,6 @@ SpatialPath, TO, TOWARD, - Distance, - Direction, ) from adam.ontology.structural_schema import ObjectStructuralSchema, SubObject from adam.relation import Relation, flatten_relations @@ -92,6 +91,7 @@ make_symmetric_dsl_region_relation, negate, ) +from immutablecollections import ImmutableDict, immutabledict, immutableset _ontology_graph = minimal_ontology_graph() # pylint:disable=invalid-name diff --git a/adam/ontology/phase1_spatial_relations.py b/adam/ontology/phase1_spatial_relations.py index b6d9f57e9..5a428e472 100644 --- a/adam/ontology/phase1_spatial_relations.py +++ b/adam/ontology/phase1_spatial_relations.py @@ -1,17 +1,15 @@ from itertools import chain from typing import Generic, List, Mapping, Optional, TypeVar, Union -from immutablecollections.converter_utils import _to_immutableset - +from adam.axes import AxesInfo, AxisFunction, GRAVITATIONAL_AXIS_FUNCTION from adam.axis import GeonAxis +from adam.ontology import OntologyNode from attr import attrib, attrs from attr.validators import in_, instance_of, optional -from immutablecollections import immutabledict, ImmutableSet, immutableset +from immutablecollections import ImmutableSet, immutabledict, immutableset +from immutablecollections.converter_utils import _to_immutableset from vistautils.preconditions import check_arg -from adam.axes import AxesInfo, AxisFunction, GRAVITATIONAL_AXIS_FUNCTION -from adam.ontology import OntologyNode - @attrs(frozen=True, slots=True, repr=False) class Distance: diff --git a/adam/ontology/phase2_ontology.py b/adam/ontology/phase2_ontology.py index 12c58c29a..7ddabbc4a 100644 --- a/adam/ontology/phase2_ontology.py +++ b/adam/ontology/phase2_ontology.py @@ -1,38 +1,38 @@ -from adam.geon import LARGE_TO_SMALL, CONSTANT, SMALL_TO_LARGE_TO_SMALL -from adam.ontology import OntologyNode, CAN_FILL_TEMPLATE_SLOT +from adam.geon import CONSTANT, LARGE_TO_SMALL, SMALL_TO_LARGE_TO_SMALL +from adam.ontology import CAN_FILL_TEMPLATE_SLOT, OntologyNode from adam.ontology.ontology import Ontology from adam.ontology.phase1_ontology import ( - _make_cup_schema, - _CHAIR_SCHEMA_BACK, - _CHAIR_SCHEMA_SQUARE_SEAT, - _CHAIR_SCHEMA_FRONT_LEFT_LEG, - _CHAIR_SCHEMA_FRONT_RIGHT_LEG, - _CHAIR_SCHEMA_BACK_LEFT_LEG, - _CHAIR_SCHEMA_BACK_RIGHT_LEG, - _CHAIR_LEGS, - _CHAIR_SCHEMA_SEAT, - _CHAIR_THREE_LEGS, - _ontology_graph, - _ACTIONS_TO_DESCRIPTIONS, - CAN_HAVE_THINGS_RESTING_ON_THEM, + BIGGER_THAN, + BLUE, CAN_BE_SAT_ON_BY_PEOPLE, - LIGHT_BROWN, + CAN_HAVE_THINGS_RESTING_ON_THEM, + CHAIR, DARK_BROWN, - INANIMATE_OBJECT, - subtype, + GAILA_PHASE_1_ONTOLOGY, + GAILA_PHASE_1_SIZE_GRADES, + GREEN, HOLLOW, + INANIMATE_OBJECT, + LIGHT_BROWN, PERSON_CAN_HAVE, RED, - BLUE, - GREEN, + SMALLER_THAN, TRANSPARENT, - CHAIR, - contacts, + _ACTIONS_TO_DESCRIPTIONS, + _CHAIR_LEGS, + _CHAIR_SCHEMA_BACK, + _CHAIR_SCHEMA_BACK_LEFT_LEG, + _CHAIR_SCHEMA_BACK_RIGHT_LEG, + _CHAIR_SCHEMA_FRONT_LEFT_LEG, + _CHAIR_SCHEMA_FRONT_RIGHT_LEG, + _CHAIR_SCHEMA_SEAT, + _CHAIR_SCHEMA_SQUARE_SEAT, + _CHAIR_THREE_LEGS, + _make_cup_schema, + _ontology_graph, above, - GAILA_PHASE_1_ONTOLOGY, - GAILA_PHASE_1_SIZE_GRADES, - SMALLER_THAN, - BIGGER_THAN, + contacts, + subtype, ) from adam.ontology.phase1_size_relationships import build_size_relationships from adam.ontology.structural_schema import ObjectStructuralSchema diff --git a/adam/ontology/selectors.py b/adam/ontology/selectors.py index 65d8bb9e2..4e9866494 100644 --- a/adam/ontology/selectors.py +++ b/adam/ontology/selectors.py @@ -5,15 +5,14 @@ from itertools import chain from typing import AbstractSet +from adam.ontology import OntologyNode +from adam.ontology.ontology import Ontology from attr import attrib, attrs from attr.validators import deep_iterable, instance_of from immutablecollections import ImmutableSet, immutableset from immutablecollections.converter_utils import _to_immutableset from vistautils.preconditions import check_arg -from adam.ontology import OntologyNode -from adam.ontology.ontology import Ontology - class OntologyNodeSelector(ABC): r""" diff --git a/adam/ontology/structural_schema.py b/adam/ontology/structural_schema.py index b23736a18..d59e121cd 100644 --- a/adam/ontology/structural_schema.py +++ b/adam/ontology/structural_schema.py @@ -1,15 +1,14 @@ from typing import Optional +from adam.axes import Axes, HasAxes +from adam.geon import Geon, MaybeHasGeon +from adam.ontology import OntologyNode +from adam.relation import Relation from attr import attrib, attrs from attr.validators import instance_of, optional from immutablecollections import ImmutableSet, immutableset from immutablecollections.converter_utils import _to_immutableset -from adam.geon import Geon, MaybeHasGeon -from adam.axes import Axes, HasAxes -from adam.ontology import OntologyNode -from adam.relation import Relation - @attrs(frozen=True, slots=True, repr=False, eq=False) class ObjectStructuralSchema(HasAxes, MaybeHasGeon): diff --git a/adam/perception/__init__.py b/adam/perception/__init__.py index 36e25a447..56daf398c 100644 --- a/adam/perception/__init__.py +++ b/adam/perception/__init__.py @@ -6,19 +6,18 @@ from enum import Enum from typing import Generic, Optional, Tuple, TypeVar -from attr import attrib, attrs -from attr.validators import instance_of, optional -from immutablecollections import ImmutableSet, immutableset -from immutablecollections.converter_utils import _to_immutableset -from vistautils.preconditions import check_arg - +from adam.axes import Axes, HasAxes, LEARNER_AXES, WORLD_AXES from adam.geon import Geon, MaybeHasGeon -from adam.axes import Axes, HasAxes, WORLD_AXES, LEARNER_AXES from adam.math_3d import Point from adam.ontology.during import DuringAction from adam.ontology.phase1_spatial_relations import Region from adam.random_utils import SequenceChooser from adam.situation import LocatedObjectSituation, Situation +from attr import attrib, attrs +from attr.validators import instance_of, optional +from immutablecollections import ImmutableSet, immutableset +from immutablecollections.converter_utils import _to_immutableset +from vistautils.preconditions import check_arg _SituationT = TypeVar("_SituationT", bound=Situation) diff --git a/adam/perception/_matcher.py b/adam/perception/_matcher.py index 2027a5bc1..ac60e6c39 100644 --- a/adam/perception/_matcher.py +++ b/adam/perception/_matcher.py @@ -18,15 +18,13 @@ import logging import sys from collections import defaultdict -from itertools import chain -from typing import Mapping, Any, Dict, Callable, Optional +from typing import Any, Callable, Dict, Mapping, Optional -from immutablecollections import immutableset, ImmutableSet, immutabledict -from more_itertools import flatten from networkx import DiGraph from adam.ontology.phase1_ontology import PART_OF -from adam.perception import ObjectPerception, MatchMode +from adam.perception import MatchMode, ObjectPerception +from immutablecollections import ImmutableSet, immutabledict, immutableset class GraphMatching: diff --git a/adam/perception/deprecated.py b/adam/perception/deprecated.py index c585c9196..543824815 100644 --- a/adam/perception/deprecated.py +++ b/adam/perception/deprecated.py @@ -1,14 +1,14 @@ from typing import Iterable, List, Mapping, Optional, Union -from adam.learner.language_mode import LanguageMode -from adam.learner.surface_templates import SurfaceTemplate -from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable -from attr.validators import instance_of from more_itertools import pairwise from adam.language import LinguisticDescription +from adam.learner.language_mode import LanguageMode +from adam.learner.surface_templates import SurfaceTemplate from adam.perception.perception_graph import PerceptionGraph, PerceptionGraphNode +from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs +from attr.validators import instance_of from immutablecollections import ImmutableDict, ImmutableSet, immutabledict, immutableset from vistautils.span import Span diff --git a/adam/perception/developmental_primitive_perception.py b/adam/perception/developmental_primitive_perception.py index 776f81d63..06e1bf78e 100644 --- a/adam/perception/developmental_primitive_perception.py +++ b/adam/perception/developmental_primitive_perception.py @@ -1,5 +1,9 @@ from abc import ABC +from adam.axes import AxesInfo +from adam.ontology import OntologyNode +from adam.perception import ObjectPerception, PerceptualRepresentationFrame +from adam.relation import Relation, flatten_relations from attr import attrib, attrs from attr.validators import in_, instance_of from immutablecollections import ImmutableSet, immutableset @@ -7,11 +11,6 @@ from vistautils.preconditions import check_arg from vistautils.range import Range -from adam.axes import AxesInfo -from adam.ontology import OntologyNode -from adam.perception import ObjectPerception, PerceptualRepresentationFrame -from adam.relation import Relation, flatten_relations - @attrs(slots=True, frozen=True, repr=False) class DevelopmentalPrimitivePerceptionFrame(PerceptualRepresentationFrame): diff --git a/adam/perception/perception_frame_difference.py b/adam/perception/perception_frame_difference.py index 4a0059c2f..8554aa87e 100644 --- a/adam/perception/perception_frame_difference.py +++ b/adam/perception/perception_frame_difference.py @@ -1,8 +1,3 @@ -from attr import attrib, attrs -from attr.validators import instance_of -from immutablecollections import ImmutableSet, immutableset -from immutablecollections.converter_utils import _to_immutableset - from adam.axes import AxesInfo from adam.perception import ObjectPerception from adam.perception.developmental_primitive_perception import ( @@ -10,6 +5,10 @@ PropertyPerception, ) from adam.relation import Relation +from attr import attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableSet, immutableset +from immutablecollections.converter_utils import _to_immutableset @attrs(slots=True, frozen=True) diff --git a/adam/perception/perception_graph.py b/adam/perception/perception_graph.py index 5a5dfd78a..ada367de2 100644 --- a/adam/perception/perception_graph.py +++ b/adam/perception/perception_graph.py @@ -45,8 +45,8 @@ from adam.axes import AxesInfo, HasAxes from adam.axis import GeonAxis -from adam.geon import Geon, MaybeHasGeon, CrossSection -from adam.ontology import OntologyNode +from adam.geon import CrossSection, Geon, MaybeHasGeon +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, OntologyNode from adam.ontology.ontology import Ontology from adam.ontology.phase1_ontology import ( COLOR, @@ -55,7 +55,6 @@ PART_OF, RECOGNIZED_PARTICULAR_PROPERTY, ) -from adam.ontology import IS_SPEAKER, IS_ADDRESSEE from adam.ontology.phase1_spatial_relations import ( Direction, Distance, @@ -64,7 +63,7 @@ SpatialPath, ) from adam.ontology.structural_schema import ObjectStructuralSchema -from adam.perception import ObjectPerception, PerceptualRepresentation, MatchMode +from adam.perception import MatchMode, ObjectPerception, PerceptualRepresentation from adam.perception._matcher import GraphMatching from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -87,10 +86,10 @@ from immutablecollections import ( ImmutableDict, ImmutableSet, + ImmutableSetMultiDict, immutabledict, immutableset, immutablesetmultidict, - ImmutableSetMultiDict, ) from immutablecollections.converter_utils import ( _to_immutabledict, diff --git a/adam/relation_dsl.py b/adam/relation_dsl.py index df1a2cdc6..a16f97af1 100644 --- a/adam/relation_dsl.py +++ b/adam/relation_dsl.py @@ -9,7 +9,6 @@ from adam.ontology.phase1_spatial_relations import Direction, Distance, Region from adam.relation import Relation, _ensure_iterable - _ObjectT = TypeVar("_ObjectT") diff --git a/adam/remappable.py b/adam/remappable.py index 94ffa8957..1929199b5 100644 --- a/adam/remappable.py +++ b/adam/remappable.py @@ -1,4 +1,4 @@ -from typing import TypeVar, Generic, Mapping, List +from typing import Generic, List, Mapping, TypeVar from typing_extensions import Protocol, runtime diff --git a/adam/semantics.py b/adam/semantics.py index 3a898ee9e..d5f3aab5a 100644 --- a/adam/semantics.py +++ b/adam/semantics.py @@ -155,6 +155,7 @@ class ActionSemanticNode(SemanticNode): # check_arg(template.num_slots >= 1) +@attrs(frozen=True, slots=True) class QuantificationSemanticNode(SemanticNode): concept: NumberConcept = attrib(validator=instance_of(NumberConcept)) slot_fillings: ImmutableDict[SyntaxSemanticsVariable, "ObjectSemanticNode"] = attrib( @@ -185,6 +186,9 @@ class LearnerSemantics: attributes: ImmutableSet[AttributeSemanticNode] = attrib(converter=_to_immutableset) relations: ImmutableSet[RelationSemanticNode] = attrib(converter=_to_immutableset) actions: ImmutableSet[ActionSemanticNode] = attrib(converter=_to_immutableset) + quantifiers: ImmutableSet[QuantificationSemanticNode] = attrib( + converter=_to_immutableset + ) objects_to_attributes: ImmutableSetMultiDict[ ObjectSemanticNode, AttributeSemanticNode @@ -198,18 +202,38 @@ class LearnerSemantics: @staticmethod def from_nodes(semantic_nodes: Iterable[SemanticNode]) -> "LearnerSemantics": + semantic_nodes_tuple = tuple(semantic_nodes) + for node in semantic_nodes_tuple: + if not isinstance(node, SemanticNode): + raise RuntimeError( + f"Tried to add something which is not a semantic node to " + f"LearnerSemantics: {node}" + ) return LearnerSemantics( objects=[ - node for node in semantic_nodes if isinstance(node, ObjectSemanticNode) + node + for node in semantic_nodes_tuple + if isinstance(node, ObjectSemanticNode) ], attributes=[ - node for node in semantic_nodes if isinstance(node, AttributeSemanticNode) + node + for node in semantic_nodes_tuple + if isinstance(node, AttributeSemanticNode) ], relations=[ - node for node in semantic_nodes if isinstance(node, RelationSemanticNode) + node + for node in semantic_nodes_tuple + if isinstance(node, RelationSemanticNode) ], actions=[ - node for node in semantic_nodes if isinstance(node, ActionSemanticNode) + node + for node in semantic_nodes_tuple + if isinstance(node, ActionSemanticNode) + ], + quantifiers=[ + node + for node in semantic_nodes_tuple + if isinstance(node, QuantificationSemanticNode) ], ) diff --git a/adam/situation/__init__.py b/adam/situation/__init__.py index 87ebd9a07..c9867def6 100644 --- a/adam/situation/__init__.py +++ b/adam/situation/__init__.py @@ -2,18 +2,20 @@ Structures for describing situations in the world at an abstracted, human-friendly level. """ from abc import ABC -from typing import Generic, List, Mapping, Optional, TypeVar, Union, Iterable, Dict +from typing import Generic, Iterable, List, Mapping, Optional, TypeVar, Union -from more_itertools import first, only -from vistautils.preconditions import check_arg +from more_itertools import only +from adam.axes import Axes, HasAxes, WORLD_AXES from adam.axis import GeonAxis +from adam.math_3d import Point +from adam.ontology import IS_SUBSTANCE, OntologyNode from adam.ontology.action_description import ActionDescriptionVariable +from adam.ontology.during import DuringAction from adam.ontology.ontology import Ontology -from adam.ontology.phase1_ontology import GAILA_PHASE_1_ONTOLOGY -from adam.ontology.structural_schema import ObjectStructuralSchema +from adam.ontology.phase1_spatial_relations import Region from attr import attrib, attrs -from attr.validators import instance_of, optional, deep_mapping +from attr.validators import deep_mapping, instance_of, optional from immutablecollections import ( ImmutableDict, ImmutableSet, @@ -29,12 +31,7 @@ _to_immutableset, _to_immutablesetmultidict, ) - -from adam.axes import Axes, HasAxes, WORLD_AXES -from adam.math_3d import Point -from adam.ontology import OntologyNode, IS_SUBSTANCE -from adam.ontology.during import DuringAction -from adam.ontology.phase1_spatial_relations import Region +from vistautils.preconditions import check_arg class Situation(ABC): diff --git a/adam/situation/high_level_semantics_situation.py b/adam/situation/high_level_semantics_situation.py index bc8d93bf5..80438db17 100644 --- a/adam/situation/high_level_semantics_situation.py +++ b/adam/situation/high_level_semantics_situation.py @@ -2,20 +2,20 @@ from itertools import chain from typing import Optional -from attr import attrib, attrs -from attr.validators import instance_of, optional -from immutablecollections import ImmutableSet, immutableset -from immutablecollections.converter_utils import _to_immutableset from more_itertools import flatten -from vistautils.preconditions import check_arg from adam.axes import AxesInfo -from adam.ontology import OntologyNode, IN_REGION +from adam.ontology import IN_REGION, OntologyNode from adam.ontology.ontology import Ontology from adam.ontology.phase1_ontology import is_recognized_particular from adam.ontology.phase1_spatial_relations import Region from adam.relation import Relation, flatten_relations from adam.situation import Action, Situation, SituationObject +from attr import attrib, attrs +from attr.validators import instance_of, optional +from immutablecollections import ImmutableSet, immutableset +from immutablecollections.converter_utils import _to_immutableset +from vistautils.preconditions import check_arg @attrs(slots=True, repr=False) diff --git a/adam/situation/templates/__init__.py b/adam/situation/templates/__init__.py index f8ea427d8..8f548c2bf 100644 --- a/adam/situation/templates/__init__.py +++ b/adam/situation/templates/__init__.py @@ -9,7 +9,14 @@ from abc import ABC, abstractmethod from typing import Generic, Iterable, List, Sequence, Tuple, TypeVar +from more_itertools import take + +from adam.math_3d import Point +from adam.ontology import OntologyNode +from adam.ontology.ontology import Ontology from adam.ontology.phase1_ontology import GAILA_PHASE_1_ONTOLOGY +from adam.random_utils import RandomChooser, SequenceChooser +from adam.situation import LocatedObjectSituation, SituationObject, SituationT from attr import Factory, attrib, attrs from attr.validators import instance_of from immutablecollections import ( @@ -26,13 +33,6 @@ _to_immutableset, _to_immutablesetmultidict, ) -from more_itertools import take - -from adam.math_3d import Point -from adam.ontology import OntologyNode -from adam.ontology.ontology import Ontology -from adam.random_utils import RandomChooser, SequenceChooser -from adam.situation import LocatedObjectSituation, SituationObject, SituationT class SituationTemplate(ABC): diff --git a/adam/situation/templates/phase1_situation_templates.py b/adam/situation/templates/phase1_situation_templates.py index 5e54b678f..8dee41008 100644 --- a/adam/situation/templates/phase1_situation_templates.py +++ b/adam/situation/templates/phase1_situation_templates.py @@ -6,27 +6,27 @@ from adam.curriculum.curriculum_utils import GROUND_OBJECT_TEMPLATE from adam.ontology.during import DuringAction from adam.ontology.phase1_ontology import ( - strictly_above, AGENT, FLY, - bigger_than, - JUMP_INITIAL_SUPPORTER_AUX, - JUMP, + GO, GOAL, - THEME, + JUMP, + JUMP_INITIAL_SUPPORTER_AUX, PUT, + THEME, + bigger_than, has, - GO, near, + strictly_above, ) from adam.ontology.phase1_spatial_relations import ( - INTERIOR, - Region, - GRAVITATIONAL_UP, + DISTAL, EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_DOWN, + GRAVITATIONAL_UP, + INTERIOR, PROXIMAL, - DISTAL, + Region, ) from adam.relation import flatten_relations from adam.situation import Action diff --git a/adam/situation/templates/phase1_templates.py b/adam/situation/templates/phase1_templates.py index e47fc718d..1cf00d024 100644 --- a/adam/situation/templates/phase1_templates.py +++ b/adam/situation/templates/phase1_templates.py @@ -13,17 +13,13 @@ Mapping, Optional, Sequence, + Tuple, TypeVar, Union, - Tuple, ) -from attr.validators import instance_of -from immutablecollections import ImmutableDict, ImmutableSet, immutabledict, immutableset -from immutablecollections.converter_utils import _to_immutabledict, _to_immutableset from more_itertools import only, take from typing_extensions import Protocol -from vistautils.preconditions import check_arg from adam.axes import AxesInfo, HorizontalAxisOfObject from adam.ontology import ( @@ -61,6 +57,10 @@ SituationTemplateProcessor, ) from attr import Factory, attrib, attrs +from attr.validators import instance_of +from immutablecollections import ImmutableDict, ImmutableSet, immutabledict, immutableset +from immutablecollections.converter_utils import _to_immutabledict, _to_immutableset +from vistautils.preconditions import check_arg _ExplicitOrVariableActionType = Union[OntologyNode, "TemplateActionTypeVariable"] diff --git a/adam/utils/networkx_utils.py b/adam/utils/networkx_utils.py index 54017f77d..ef2aac1c3 100644 --- a/adam/utils/networkx_utils.py +++ b/adam/utils/networkx_utils.py @@ -1,10 +1,11 @@ from typing import Any, Callable, Iterable -from attr import attrs, attrib -from immutablecollections import immutableset, ImmutableSet -from immutablecollections.converter_utils import _to_immutableset from networkx import DiGraph, nx +from attr import attrib, attrs +from immutablecollections import ImmutableSet, immutableset +from immutablecollections.converter_utils import _to_immutableset + def digraph_with_nodes_sorted_by( graph: DiGraph, sort_key: Callable[[Any], Any] diff --git a/adam/visualization/make_scenes.py b/adam/visualization/make_scenes.py index 2c50f08f1..b6269f482 100644 --- a/adam/visualization/make_scenes.py +++ b/adam/visualization/make_scenes.py @@ -4,86 +4,79 @@ operating and when other code (gathering and processing scene information) is executing in a serial manner. """ +import logging +import random +from collections import defaultdict +from functools import partial +from hashlib import md5 +from math import isnan +from pathlib import Path from typing import ( - Iterable, - List, - Tuple, - Union, - DefaultDict, - Optional, - Callable, Any, + Callable, + DefaultDict, + Dict, Generator, + Iterable, + List, Mapping, - Dict, + Optional, Set, + Tuple, + Union, ) -from functools import partial -import random -from pathlib import Path -from collections import defaultdict import numpy as np -import logging +# consider refactoring away this dependency +from panda3d.core import ( + LPoint3f, + NodePath, +) # pylint: disable=no-name-in-module; pylint: disable=no-name-in-module + +import attr +from adam.curriculum.phase1_curriculum import Phase1InstanceGroup # currently useful for positioning multiple objects: from adam.curriculum.verbs_with_dynamic_prepositions_curriculum import ( _make_take_with_prepositions as make_curriculum, ) -from adam.curriculum.phase1_curriculum import Phase1InstanceGroup - - -import attr -from attr import attrs - +from adam.curriculum_to_html import CurriculumToHtmlDumper from adam.language.language_utils import phase2_language_generator from adam.learner import LanguageMode -from vistautils.parameters import Parameters -from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from immutablecollections import ImmutableSet, immutableset - -# consider refactoring away this dependency -from panda3d.core import NodePath # pylint: disable=no-name-in-module -from panda3d.core import LPoint3f # pylint: disable=no-name-in-module - from adam.math_3d import Point -from math import isnan -from hashlib import md5 - -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from adam.perception.developmental_primitive_perception import ( - RgbColorPerception, - HasColor, - HasBinaryProperty, - ObjectPerception, - Relation, -) from adam.ontology import OntologyNode from adam.ontology.phase1_ontology import ( AGENT, - THEME, GOAL, PUSH_GOAL, PUSH_SURFACE_AUX, ROLL_SURFACE_AUXILIARY, + THEME, +) +from adam.ontology.phase1_spatial_relations import Region +from adam.perception.developmental_primitive_perception import ( + HasBinaryProperty, + HasColor, + ObjectPerception, + Relation, + RgbColorPerception, ) from adam.relation import IN_REGION from adam.situation import SituationObject - +from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam.visualization.panda3d_interface import SituationVisualizer +from adam.visualization.positioning import PositionsMap, run_model from adam.visualization.utils import ( OBJECT_NAMES_TO_EXCLUDE, - cross_section_to_geon, OBJECT_SCALE_MULTIPLIER_MAP, + cross_section_to_geon, model_lookup, ) - -from adam.visualization.positioning import run_model, PositionsMap -from adam.ontology.phase1_spatial_relations import Region - - -from adam.curriculum_to_html import CurriculumToHtmlDumper +from attr import attrs +from immutablecollections import ImmutableSet, immutableset +from vistautils.parameters import Parameters +from vistautils.parameters_only_entrypoint import parameters_only_entry_point USAGE_MESSAGE = """make_scenes.py param_file \twhere param_file has the following parameters: diff --git a/adam/visualization/panda3d_interface.py b/adam/visualization/panda3d_interface.py index 49baccab3..e7756928d 100644 --- a/adam/visualization/panda3d_interface.py +++ b/adam/visualization/panda3d_interface.py @@ -11,36 +11,39 @@ supplied from elsewhere. """ -from typing import Tuple, Optional, Dict, List -import sys import os - +import sys import time -from direct.showbase.ShowBase import ShowBase # pylint: disable=no-name-in-module - -from panda3d.core import DirectionalLight # pylint: disable=no-name-in-module -from panda3d.core import AmbientLight # pylint: disable=no-name-in-module -from panda3d.core import PointLight # pylint: disable=no-name-in-module -from panda3d.core import Material # pylint: disable=no-name-in-module -from panda3d.core import NodePath # pylint: disable=no-name-in-module -from panda3d.core import TextNode # pylint: disable=no-name-in-module -from panda3d.core import AntialiasAttrib # pylint: disable=no-name-in-module -from panda3d.core import LPoint3f # pylint: disable=no-name-in-module -from panda3d.core import Filename # pylint: disable=no-name-in-module +from typing import Dict, List, Optional, Tuple from direct.gui.OnscreenText import OnscreenText # pylint: disable=no-name-in-module +from direct.showbase.ShowBase import ShowBase # pylint: disable=no-name-in-module +from panda3d.core import ( + AmbientLight, + AntialiasAttrib, + DirectionalLight, + Filename, + LPoint3f, + Material, + NodePath, + PointLight, + TextNode, +) # pylint: disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: + +# disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: +# disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: +# disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: disable=no-name-in-module +from torch import Tensor + +from adam.perception.developmental_primitive_perception import RgbColorPerception from adam.visualization.positioning import PositionsMap from adam.visualization.utils import ( - Shape, - OBJECT_NAMES_TO_EXCLUDE, GEON_SHAPES, MODEL_NAMES, + OBJECT_NAMES_TO_EXCLUDE, + Shape, ) -from adam.perception.developmental_primitive_perception import RgbColorPerception - -from torch import Tensor - class SituationVisualizer(ShowBase): model_to_file = { diff --git a/adam/visualization/positioning.py b/adam/visualization/positioning.py index 698d10d38..631eca2d6 100644 --- a/adam/visualization/positioning.py +++ b/adam/visualization/positioning.py @@ -7,47 +7,40 @@ main() function used for testing purposes. Primary function made available to outside callers is run_model() """ -from itertools import combinations -from typing import Mapping, AbstractSet, Optional, List, Iterable, Tuple, DefaultDict -from attr import attrs, attrib from collections import defaultdict +from itertools import combinations from math import isnan, pi +from typing import AbstractSet, DefaultDict, Iterable, List, Mapping, Optional, Tuple import numpy as np import torch import torch.nn as nn -from torch.nn import Parameter import torch.optim as optim -from torch.optim.lr_scheduler import ReduceLROnPlateau -from torch.nn import PairwiseDistance - from panda3d.core import LPoint3f # pylint: disable=no-name-in-module - -from immutablecollections import immutabledict, immutableset, ImmutableDict, ImmutableSet -from vistautils.preconditions import check_arg +from torch.nn import PairwiseDistance, Parameter +from torch.optim.lr_scheduler import ReduceLROnPlateau from adam.axes import ( Axes, + FacingAddresseeAxis, HorizontalAxisOfObject, straight_up, - # directed, symmetric, symmetric_vertical, - FacingAddresseeAxis, -) - +) # directed, from adam.ontology.phase1_spatial_relations import ( - PROXIMAL, DISTAL, - EXTERIOR_BUT_IN_CONTACT, - Region, -) -from adam.ontology.phase1_spatial_relations import ( Direction, - GRAVITATIONAL_UP, + EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_DOWN, + GRAVITATIONAL_UP, + PROXIMAL, + Region, ) -from adam.perception import ObjectPerception, GROUND_PERCEPTION +from adam.perception import GROUND_PERCEPTION, ObjectPerception +from attr import attrib, attrs +from immutablecollections import ImmutableDict, ImmutableSet, immutabledict, immutableset +from vistautils.preconditions import check_arg # see https://github.com/pytorch/pytorch/issues/24807 re: pylint issue diff --git a/adam/visualization/render_curriculum.py b/adam/visualization/render_curriculum.py index 448c2e5b5..ff259c2d4 100644 --- a/adam/visualization/render_curriculum.py +++ b/adam/visualization/render_curriculum.py @@ -1,21 +1,20 @@ -from typing import List +import os from pathlib import Path +from typing import List + from adam.curriculum.phase1_curriculum import ( build_gaila_phase_1_curriculum as build_curriculum, ) + +# helper function to locating a curriculum +from adam.experiment.log_experiment import curriculum_from_params from adam.language_specific.english.english_language_generator import ( GAILA_PHASE_1_LANGUAGE_GENERATOR, ) -from vistautils.parameters_only_entrypoint import parameters_only_entry_point -from vistautils.parameters import Parameters, YAMLParametersLoader - -import os - from adam.visualization.make_scenes import main as make_scenes from adam.visualization.panda3d_interface import SituationVisualizer - -# helper function to locating a curriculum -from adam.experiment.log_experiment import curriculum_from_params +from vistautils.parameters import Parameters, YAMLParametersLoader +from vistautils.parameters_only_entrypoint import parameters_only_entry_point USAGE_MESSAGE = """""" diff --git a/adam/visualization/utils.py b/adam/visualization/utils.py index 1b786ebfe..7140a7da3 100644 --- a/adam/visualization/utils.py +++ b/adam/visualization/utils.py @@ -1,44 +1,43 @@ # pragma: no cover import enum -from typing import Optional, List, Tuple -from immutablecollections import immutableset, immutabledict, ImmutableDict +from typing import List, Optional, Tuple + from panda3d.core import NodePath # pylint: disable=no-name-in-module -from adam.perception import ObjectPerception + from adam.geon import CrossSection from adam.ontology.phase1_ontology import ( - PHASE_1_CURRICULUM_OBJECTS, - OntologyNode, + DAD, GAILA_PHASE_1_SIZE_GRADES, + HAND, + HEAD, MOM, - DAD, + OntologyNode, PERSON, -) - -from adam.ontology.phase1_ontology import ( - _ARM, - _TORSO, + PHASE_1_CURRICULUM_OBJECTS, _ANIMAL_LEG, - _INANIMATE_LEG, + _ARM, + _ARM_SEGMENT, + _BIRD_HEAD, + _BODY, _CHAIR_BACK, _CHAIR_SEAT, + _DOG_HEAD, + _FLATBED, + _FOOT, + _INANIMATE_LEG, + _LEG_SEGMENT, + _ROOF, _TABLETOP, _TAIL, - _WING, - _ARM_SEGMENT, - _WALL, - _ROOF, _TIRE, - _TRUCK_CAB, + _TORSO, _TRAILER, - _FLATBED, - _BODY, - _DOG_HEAD, - _BIRD_HEAD, - _LEG_SEGMENT, - _FOOT, - HEAD, - HAND, + _TRUCK_CAB, + _WALL, + _WING, ) +from adam.perception import ObjectPerception +from immutablecollections import ImmutableDict, immutabledict, immutableset OBJECT_NAMES_TO_EXCLUDE = immutableset(["the ground", "learner"]) diff --git a/setup.py b/setup.py index d81009448..2fb286f76 100755 --- a/setup.py +++ b/setup.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from distutils.core import setup -from setuptools import find_packages from os.path import abspath, dirname, join diff --git a/tests/curriculum/attribute_constraining_action_curriculum_test.py b/tests/curriculum/attribute_constraining_action_curriculum_test.py index ce7cc5600..0622af93d 100644 --- a/tests/curriculum/attribute_constraining_action_curriculum_test.py +++ b/tests/curriculum/attribute_constraining_action_curriculum_test.py @@ -1,16 +1,17 @@ +import pytest + from adam.curriculum.attribute_constraining_action_curriculum import ( - make_german_eat_test_curriculum, make_animal_eat_curriculum, + make_german_eat_test_curriculum, make_human_eat_curriculum, ) -from tests.curriculum.phase1_curriculum_test import curriculum_test -from adam.language_specific.english.english_language_generator import ( - GAILA_PHASE_1_LANGUAGE_GENERATOR, -) from adam.language_specific.chinese.chinese_language_generator import ( GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, ) -import pytest +from adam.language_specific.english.english_language_generator import ( + GAILA_PHASE_1_LANGUAGE_GENERATOR, +) +from tests.curriculum.phase1_curriculum_test import curriculum_test @pytest.mark.parametrize( diff --git a/tests/curriculum/imprecise_descriptions_curriculum_test.py b/tests/curriculum/imprecise_descriptions_curriculum_test.py index 206a7b6bd..774601682 100644 --- a/tests/curriculum/imprecise_descriptions_curriculum_test.py +++ b/tests/curriculum/imprecise_descriptions_curriculum_test.py @@ -1,26 +1,27 @@ +import pytest + from adam.curriculum.imprecise_descriptions_curriculum import ( - make_move_imprecise_temporal_descriptions, - make_throw_imprecise_temporal_descriptions, - make_jump_imprecise_temporal_descriptions, - make_roll_imprecise_temporal_descriptions, - make_fly_imprecise_temporal_descriptions, + make_eat_big_small_curriculum, make_fall_imprecise_temporal_descriptions, + make_fly_imprecise_temporal_descriptions, make_imprecise_size_descriptions, - make_walk_run_subtle_verb_distinction, + make_jump_imprecise_temporal_descriptions, + make_move_imprecise_temporal_descriptions, make_pass_toss_subtle_verb_distinction, make_push_shove_subtle_verb_distinctions, - make_take_grab_subtle_verb_distinction, - make_eat_big_small_curriculum, + make_roll_imprecise_temporal_descriptions, make_spin_tall_short_curriculum, -) -from tests.curriculum.phase1_curriculum_test import curriculum_test -from adam.language_specific.english.english_language_generator import ( - GAILA_PHASE_1_LANGUAGE_GENERATOR, + make_take_grab_subtle_verb_distinction, + make_throw_imprecise_temporal_descriptions, + make_walk_run_subtle_verb_distinction, ) from adam.language_specific.chinese.chinese_language_generator import ( GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, ) -import pytest +from adam.language_specific.english.english_language_generator import ( + GAILA_PHASE_1_LANGUAGE_GENERATOR, +) +from tests.curriculum.phase1_curriculum_test import curriculum_test @pytest.mark.parametrize( diff --git a/tests/curriculum/phase1_curriculum_test.py b/tests/curriculum/phase1_curriculum_test.py index 837d4d3ca..088610ba5 100644 --- a/tests/curriculum/phase1_curriculum_test.py +++ b/tests/curriculum/phase1_curriculum_test.py @@ -1,3 +1,5 @@ +import pytest + from adam.curriculum.phase1_curriculum import ( Phase1InstanceGroup, _make_behind_in_front_curriculum, @@ -7,16 +9,22 @@ _make_eat_curriculum, _make_fall_curriculum, _make_fly_curriculum, + _make_generic_statements_curriculum, _make_go_curriculum, _make_jump_curriculum, _make_move_curriculum, + _make_my_your_object_curriculum, _make_object_beside_object_curriculum, _make_object_in_other_object_curriculum, _make_object_on_ground_curriculum, _make_object_on_object_curriculum, _make_object_under_or_over_object_curriculum, _make_objects_with_colors_curriculum, + _make_objects_with_colors_is_curriculum, + _make_part_whole_curriculum, + _make_pass_curriculum, _make_person_has_object_curriculum, + _make_plural_objects_curriculum, _make_push_curriculum, _make_put_curriculum, _make_put_on_speaker_addressee_body_part_curriculum, @@ -27,22 +35,14 @@ _make_take_curriculum, _make_throw_curriculum, _make_transfer_of_possession_curriculum, - _make_objects_with_colors_is_curriculum, - _make_pass_curriculum, - _make_part_whole_curriculum, - _make_plural_objects_curriculum, - _make_generic_statements_curriculum, _make_transitive_roll_curriculum, - _make_my_your_object_curriculum, -) - -from adam.language_specific.english.english_language_generator import ( - GAILA_PHASE_1_LANGUAGE_GENERATOR, ) from adam.language_specific.chinese.chinese_language_generator import ( GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, ) -import pytest +from adam.language_specific.english.english_language_generator import ( + GAILA_PHASE_1_LANGUAGE_GENERATOR, +) def curriculum_test(curriculum: Phase1InstanceGroup) -> None: diff --git a/tests/curriculum/phase2_curriculum_test.py b/tests/curriculum/phase2_curriculum_test.py index edd096b06..afc827a99 100644 --- a/tests/curriculum/phase2_curriculum_test.py +++ b/tests/curriculum/phase2_curriculum_test.py @@ -1,3 +1,5 @@ +import pytest + from adam.curriculum.curriculum_utils import Phase1InstanceGroup from adam.curriculum.phase2_curriculum import ( _make_drink_cups_curriculum, @@ -10,7 +12,6 @@ from adam.language_specific.english.english_language_generator import ( GAILA_PHASE_2_LANGUAGE_GENERATOR, ) -import pytest def curriculum_test(curriculum: Phase1InstanceGroup) -> None: diff --git a/tests/curriculum/prepositions_curriculum_test.py b/tests/curriculum/prepositions_curriculum_test.py index be34ea520..8aa3afdb3 100644 --- a/tests/curriculum/prepositions_curriculum_test.py +++ b/tests/curriculum/prepositions_curriculum_test.py @@ -1,29 +1,30 @@ -from adam.language_specific.chinese.chinese_language_generator import ( - GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, -) -from adam.language_specific.english.english_language_generator import ( - GAILA_PHASE_1_LANGUAGE_GENERATOR, -) import pytest + from adam.curriculum.preposition_curriculum import ( - _make_on_training, - _make_beside_training, - _make_under_training, - _make_over_training, - _make_in_training, - _make_in_front_training, + _make_behind_tests, _make_behind_training, + _make_beside_tests, + _make_beside_training, + _make_far_tests, + _make_far_training, _make_in_front_tests, - _make_behind_tests, + _make_in_front_training, _make_in_tests, + _make_in_training, + _make_near_tests, + _make_near_training, + _make_on_tests, + _make_on_training, _make_over_tests, + _make_over_training, _make_under_tests, - _make_beside_tests, - _make_on_tests, - _make_near_training, - _make_near_tests, - _make_far_training, - _make_far_tests, + _make_under_training, +) +from adam.language_specific.chinese.chinese_language_generator import ( + GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, +) +from adam.language_specific.english.english_language_generator import ( + GAILA_PHASE_1_LANGUAGE_GENERATOR, ) from tests.curriculum.phase1_curriculum_test import curriculum_test diff --git a/tests/curriculum/pursuit_curriculum_test.py b/tests/curriculum/pursuit_curriculum_test.py index a1534d48f..a7b9ebf7e 100644 --- a/tests/curriculum/pursuit_curriculum_test.py +++ b/tests/curriculum/pursuit_curriculum_test.py @@ -1,12 +1,13 @@ +import pytest + from adam.curriculum.pursuit_curriculum import make_simple_pursuit_curriculum -from tests.curriculum.phase1_curriculum_test import curriculum_test from adam.language_specific.chinese.chinese_language_generator import ( GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, ) from adam.language_specific.english.english_language_generator import ( GAILA_PHASE_1_LANGUAGE_GENERATOR, ) -import pytest +from tests.curriculum.phase1_curriculum_test import curriculum_test @pytest.mark.parametrize( diff --git a/tests/curriculum/verbs_with_dynamic_prepositions_curriculum_test.py b/tests/curriculum/verbs_with_dynamic_prepositions_curriculum_test.py index 47c43adc0..4f7ca694a 100644 --- a/tests/curriculum/verbs_with_dynamic_prepositions_curriculum_test.py +++ b/tests/curriculum/verbs_with_dynamic_prepositions_curriculum_test.py @@ -1,25 +1,26 @@ +import pytest + from adam.curriculum.verbs_with_dynamic_prepositions_curriculum import ( - _make_push_with_prepositions, + _make_come_with_prepositions, + _make_fall_with_prepositions, + _make_fly_with_prepositions, _make_go_with_prepositions, - _make_throw_with_prepositions, + _make_jump_with_prepositions, + _make_move_with_prepositions, + _make_push_with_prepositions, + _make_put_with_prepositions, _make_roll_with_prepositions, _make_sit_with_prepositions, _make_take_with_prepositions, - _make_fall_with_prepositions, - _make_put_with_prepositions, - _make_move_with_prepositions, - _make_jump_with_prepositions, - _make_fly_with_prepositions, - _make_come_with_prepositions, + _make_throw_with_prepositions, ) -from tests.curriculum.phase1_curriculum_test import curriculum_test from adam.language_specific.chinese.chinese_language_generator import ( GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR, ) from adam.language_specific.english.english_language_generator import ( GAILA_PHASE_1_LANGUAGE_GENERATOR, ) -import pytest +from tests.curriculum.phase1_curriculum_test import curriculum_test @pytest.mark.parametrize( diff --git a/tests/experiment_test.py b/tests/experiment_test.py index 147d50304..493ffe443 100644 --- a/tests/experiment_test.py +++ b/tests/experiment_test.py @@ -1,8 +1,8 @@ from adam.curriculum import GeneratedFromSituationsInstanceGroup from adam.experiment import Experiment, execute_experiment from adam.experiment.observer import ( - TopChoiceExactMatchObserver, CandidateAccuracyObserver, + TopChoiceExactMatchObserver, ) from adam.language.language_generator import SingleObjectLanguageGenerator from adam.language_specific.english.english_phase_1_lexicon import ( diff --git a/tests/language/language_generator/language_generation_test.py b/tests/language/language_generator/language_generation_test.py index d5b672cbc..b716c37c9 100644 --- a/tests/language/language_generator/language_generation_test.py +++ b/tests/language/language_generator/language_generation_test.py @@ -1,5 +1,3 @@ -from immutablecollections import ImmutableSet, immutableset - from adam.language import TokenSequenceLinguisticDescription from adam.language.language_generator import ( ChooseFirstLanguageGenerator, @@ -15,6 +13,7 @@ from adam.random_utils import FixedIndexChooser, RandomChooser, SequenceChooser from adam.situation import LocatedObjectSituation, Situation from adam_test_utils import situation_object +from immutablecollections import ImmutableSet, immutableset def test_single_object_generator(): diff --git a/tests/language_specific/chinese/test_chinese_language_generator.py b/tests/language_specific/chinese/test_chinese_language_generator.py index 6fd2d362a..e6f10155d 100644 --- a/tests/language_specific/chinese/test_chinese_language_generator.py +++ b/tests/language_specific/chinese/test_chinese_language_generator.py @@ -1,116 +1,106 @@ """This file contains test cases for the Chinese Language Generator""" - -from typing import Tuple import pytest from more_itertools import only + from adam.axes import ( - HorizontalAxisOfObject, - FacingAddresseeAxis, AxesInfo, + FacingAddresseeAxis, GRAVITATIONAL_AXIS_FUNCTION, + HorizontalAxisOfObject, ) from adam.language_specific.chinese.chinese_language_generator import ( - PREFER_DITRANSITIVE, - SimpleRuleBasedChineseLanguageGenerator, - USE_ADVERBIAL_PATH_MODIFIER, - IGNORE_HAS_AS_VERB, ATTRIBUTES_AS_X_IS_Y, IGNORE_GOAL, - USE_VERTICAL_MODIFIERS, + IGNORE_HAS_AS_VERB, + PREFER_DITRANSITIVE, + SimpleRuleBasedChineseLanguageGenerator, USE_ABOVE_BELOW, + USE_ADVERBIAL_PATH_MODIFIER, USE_NEAR, + USE_VERTICAL_MODIFIERS, ) from adam.language_specific.chinese.chinese_phase_1_lexicon import ( GAILA_PHASE_1_CHINESE_LEXICON, ) -from adam.axes import GRAVITATIONAL_DOWN_TO_UP_AXIS -from adam.ontology import IN_REGION, IS_SPEAKER, IS_ADDRESSEE +from adam.ontology import IN_REGION, IS_ADDRESSEE, IS_SPEAKER from adam.ontology.during import DuringAction from adam.ontology.phase1_ontology import ( AGENT, - SEMANTIC_ROLE, - HARD_FORCE, - SOFT_FORCE, - COME, BABY, BALL, BIRD, + BOOK, BOX, + CAR, CHAIR, + COME, COOKIE, - CUP, - PASS, DAD, + DOG, + DOOR, DRINK, - DRINK_CONTAINER_AUX, EAT, FALL, + FAST, FLY, GAILA_PHASE_1_ONTOLOGY, GIVE, - PUSH_SURFACE_AUX, - PUSH_GOAL, + GO, GOAL, GREEN, GROUND, + HARD_FORCE, HAS, - JUICE, + HAT, + HOLLOW, + HOUSE, + JUMP, + JUMP_INITIAL_SUPPORTER_AUX, + LEARNER, MOM, - PATIENT, + MOVE, + PASS, PUSH, PUT, + RED, ROLL, + ROLL_SURFACE_AUXILIARY, + SEMANTIC_ROLE, SIT, + SLOW, + SPATIAL_RELATION, TABLE, + TAKE, THEME, THROW, - WATER, - DOOR, - HAT, - on, - strictly_above, - strictly_over, - strictly_under, - strictly_below, - JUMP, - JUMP_INITIAL_SUPPORTER_AUX, - DOG, - HOLLOW, - GO, - BOOK, - LEARNER, - near, - inside, - TAKE, - CAR, - ROLL_SURFACE_AUXILIARY, TRUCK, - HOUSE, - RED, - WATERMELON, - MOVE, - FAST, - SLOW, WALK, WALK_SURFACE_AUXILIARY, + WATER, + WATERMELON, bigger_than, far, - SPATIAL_RELATION, + inside, + near, + on, + strictly_above, + strictly_over, + strictly_under, ) from adam.ontology.phase1_spatial_relations import ( AWAY_FROM, - FROM, - TOWARD, DISTAL, + Direction, EXTERIOR_BUT_IN_CONTACT, + FROM, GRAVITATIONAL_DOWN, GRAVITATIONAL_UP, INTERIOR, + PROXIMAL, Region, SpatialPath, - Direction, - PROXIMAL, + TOWARD, VIA, ) from adam.random_utils import FixedIndexChooser @@ -118,8 +108,6 @@ from adam.situation import Action, SituationObject from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam_test_utils import situation_object -from tests.sample_situations import make_bird_flies_over_a_house -from tests.situation.situation_test import make_mom_put_ball_on_table _SIMPLE_GENERATOR = SimpleRuleBasedChineseLanguageGenerator( ontology_lexicon=GAILA_PHASE_1_CHINESE_LEXICON diff --git a/tests/language_specific/chinese/test_chinese_syntax.py b/tests/language_specific/chinese/test_chinese_syntax.py index 30edd1495..9c52a9a82 100644 --- a/tests/language_specific/chinese/test_chinese_syntax.py +++ b/tests/language_specific/chinese/test_chinese_syntax.py @@ -2,32 +2,30 @@ The structure and vocab have been verified separately by Chinese native speaker.""" from networkx import DiGraph -import pytest + from adam.language.dependency import DependencyTree, DependencyTreeToken from adam.language.dependency.universal_dependencies import ( + ADJECTIVAL_MODIFIER, + ADJECTIVE, ADPOSITION, + ADVERB, ADVERBIAL_CLAUSE_MODIFIER, + ADVERBIAL_MODIFIER, + CASE_POSSESSIVE, CASE_SPATIAL, - DETERMINER, - DETERMINER_ROLE, + CLASSIFIER, + INDIRECT_OBJECT, + NOMINAL_MODIFIER, + NOMINAL_MODIFIER_POSSESSIVE, NOMINAL_SUBJECT, NOUN, + NUMERAL, + NUMERIC_MODIFIER, OBJECT, OBLIQUE_NOMINAL, - VERB, - INDIRECT_OBJECT, - ADVERBIAL_MODIFIER, - ADJECTIVAL_MODIFIER, - ADJECTIVE, - ADVERB, PARTICLE, - CASE_POSSESSIVE, - NOMINAL_MODIFIER_POSSESSIVE, - NOMINAL_MODIFIER, - NUMERAL, - CLASSIFIER, - NUMERIC_MODIFIER, PROPER_NOUN, + VERB, ) from adam.language_specific.chinese.chinese_syntax import ( SIMPLE_CHINESE_DEPENDENCY_TREE_LINEARIZER, diff --git a/tests/language_specific/english/test_english_language_generator.py b/tests/language_specific/english/test_english_language_generator.py index 08af2cd01..e788c632b 100644 --- a/tests/language_specific/english/test_english_language_generator.py +++ b/tests/language_specific/english/test_english_language_generator.py @@ -3,89 +3,89 @@ import pytest from more_itertools import only -from adam.axes import HorizontalAxisOfObject, FacingAddresseeAxis, AxesInfo +from adam.axes import AxesInfo, FacingAddresseeAxis, HorizontalAxisOfObject from adam.language_specific.english.english_language_generator import ( - PREFER_DITRANSITIVE, - SimpleRuleBasedEnglishLanguageGenerator, - USE_ADVERBIAL_PATH_MODIFIER, ATTRIBUTES_AS_X_IS_Y, IGNORE_COLORS, + PREFER_DITRANSITIVE, + SimpleRuleBasedEnglishLanguageGenerator, USE_ABOVE_BELOW, + USE_ADVERBIAL_PATH_MODIFIER, USE_NEAR, USE_VERTICAL_MODIFIERS, ) from adam.language_specific.english.english_phase_1_lexicon import ( GAILA_PHASE_1_ENGLISH_LEXICON, ) -from adam.ontology import IN_REGION, IS_SPEAKER, IS_ADDRESSEE +from adam.ontology import IN_REGION, IS_ADDRESSEE, IS_SPEAKER from adam.ontology.during import DuringAction from adam.ontology.phase1_ontology import ( AGENT, BABY, BALL, BIRD, + BLACK, BOX, + CAR, CHAIR, COOKIE, CUP, DAD, + DOG, DRINK, DRINK_CONTAINER_AUX, EAT, FALL, + FAST, FLY, GAILA_PHASE_1_ONTOLOGY, GIVE, + GO, GOAL, GREEN, GROUND, + HARD_FORCE, HAS, + HOLLOW, JUICE, + JUMP, + JUMP_INITIAL_SUPPORTER_AUX, + LEARNER, MOM, + PASS, PATIENT, PUSH, PUT, + RED, ROLL, + ROLL_SURFACE_AUXILIARY, SIT, + SLOW, TABLE, + TAKE, THEME, THROW, + WALK, + WALK_SURFACE_AUXILIARY, WATER, - on, - strictly_above, - JUMP, - JUMP_INITIAL_SUPPORTER_AUX, - DOG, - HOLLOW, - GO, - LEARNER, - near, - TAKE, - CAR, - ROLL_SURFACE_AUXILIARY, - has, bigger_than, - RED, - BLACK, far, - WALK, - HARD_FORCE, - PASS, - WALK_SURFACE_AUXILIARY, - FAST, - SLOW, + has, + near, + on, + strictly_above, ) from adam.ontology.phase1_spatial_relations import ( AWAY_FROM, DISTAL, + Direction, EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_DOWN, GRAVITATIONAL_UP, INTERIOR, + PROXIMAL, Region, SpatialPath, - Direction, - PROXIMAL, VIA, ) from adam.random_utils import FixedIndexChooser diff --git a/tests/learner/__init__.py b/tests/learner/__init__.py index 44ab34e03..75b90bf3c 100644 --- a/tests/learner/__init__.py +++ b/tests/learner/__init__.py @@ -1,16 +1,15 @@ from typing import Mapping -from immutablecollections import immutabledict from adam.language_specific.english import ENGLISH_DETERMINERS from adam.learner.language_mode import LanguageMode from adam.learner.object_recognizer import ObjectRecognizer from adam.learner.objects import ObjectRecognizerAsTemplateLearner - from adam.ontology.phase1_ontology import ( GAILA_PHASE_1_ONTOLOGY, - PHASE_1_CURRICULUM_OBJECTS, GROUND, + PHASE_1_CURRICULUM_OBJECTS, ) +from immutablecollections import immutabledict PHASE_1_CURRICULUM_OBJECTS_INCLUDE_GROUND = list(PHASE_1_CURRICULUM_OBJECTS) PHASE_1_CURRICULUM_OBJECTS_INCLUDE_GROUND.append(GROUND) diff --git a/tests/learner/object_learner_test.py b/tests/learner/object_learner_test.py index f92d8b8d9..88ce8ad74 100644 --- a/tests/learner/object_learner_test.py +++ b/tests/learner/object_learner_test.py @@ -3,7 +3,6 @@ from typing import Iterable import pytest -from immutablecollections import immutableset from more_itertools import flatten from adam.curriculum.curriculum_utils import PHASE1_TEST_CHOOSER_FACTORY @@ -24,8 +23,12 @@ from adam.learner.alignments import LanguageConceptAlignment from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode -from adam.learner.objects import PursuitObjectLearnerNew, SubsetObjectLearnerNew -from adam.learner.objects import SubsetObjectLearner +from adam.learner.objects import ( + PursuitObjectLearnerNew, + SubsetObjectLearner, + SubsetObjectLearnerNew, +) +from adam.learner.quantifers import QuantifierTemplateLearner from adam.ontology import OntologyNode from adam.ontology.phase1_ontology import ( BALL, @@ -56,6 +59,7 @@ object_variable, sampled, ) +from immutablecollections import immutableset def subset_object_learner_factory(language_mode: LanguageMode): @@ -68,7 +72,11 @@ def integrated_learner_factory(language_mode: LanguageMode): return IntegratedTemplateLearner( object_learner=SubsetObjectLearnerNew( ontology=GAILA_PHASE_1_ONTOLOGY, beam_size=10, language_mode=language_mode - ) + ), + language_mode=language_mode, + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode + ), ) @@ -328,7 +336,11 @@ def test_pursuit_object_learner(language_mode): smoothing_parameter=0.002, ontology=GAILA_PHASE_1_ONTOLOGY, language_mode=language_mode, - ) + ), + language_mode=language_mode, + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode + ), ) for training_stage in [train_curriculum]: for ( diff --git a/tests/learner/pursuit_preposition_learner_test.py b/tests/learner/pursuit_preposition_learner_test.py index fd0edf516..4d1486c59 100644 --- a/tests/learner/pursuit_preposition_learner_test.py +++ b/tests/learner/pursuit_preposition_learner_test.py @@ -1,21 +1,21 @@ import random + import pytest -from adam.curriculum.phase1_curriculum import _x_has_y_template -from immutablecollections import immutableset from adam.curriculum.curriculum_utils import ( - standard_object, - phase1_instances, PHASE1_CHOOSER_FACTORY, + phase1_instances, + standard_object, ) +from adam.curriculum.phase1_curriculum import _x_has_y_template from adam.curriculum.preposition_curriculum import ( - _on_template, - _beside_template, - _under_template, - _over_template, - _in_template, _behind_template, + _beside_template, _in_front_template, + _in_template, + _on_template, + _over_template, + _under_template, ) from adam.language.language_utils import phase1_language_generator from adam.learner import LearningExample @@ -23,16 +23,17 @@ from adam.learner.prepositions import PrepositionPursuitLearner from adam.ontology.phase1_ontology import ( BALL, - TABLE, - GAILA_PHASE_1_ONTOLOGY, - WATER, CUP, + GAILA_PHASE_1_ONTOLOGY, + INANIMATE_OBJECT, MOM, PERSON, - INANIMATE_OBJECT, PERSON_CAN_HAVE, + TABLE, + WATER, ) -from adam.situation.templates.phase1_templates import sampled, object_variable +from adam.situation.templates.phase1_templates import object_variable, sampled +from immutablecollections import immutableset from tests.learner import LANGUAGE_MODE_TO_OBJECT_RECOGNIZER diff --git a/tests/learner/subset_attribute_learner_test.py b/tests/learner/subset_attribute_learner_test.py index f728e27aa..2587d4958 100644 --- a/tests/learner/subset_attribute_learner_test.py +++ b/tests/learner/subset_attribute_learner_test.py @@ -4,10 +4,10 @@ from more_itertools import flatten from adam.curriculum.curriculum_utils import ( - standard_object, - phase1_instances, PHASE1_CHOOSER_FACTORY, PHASE1_TEST_CHOOSER_FACTORY, + phase1_instances, + standard_object, ) from adam.curriculum.phase1_curriculum import ( _object_with_color_template, @@ -19,23 +19,24 @@ from adam.learner.attributes import SubsetAttributeLearner, SubsetAttributeLearnerNew from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode -from adam.ontology import IS_SPEAKER, IS_ADDRESSEE +from adam.learner.quantifers import QuantifierTemplateLearner +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER from adam.ontology.phase1_ontology import ( - RED, - WHITE, + BABY, + BALL, BLACK, - GREEN, BLUE, - BALL, BOOK, - GAILA_PHASE_1_ONTOLOGY, CAR, - PERSON, + DAD, + GAILA_PHASE_1_ONTOLOGY, + GREEN, INANIMATE_OBJECT, - PERSON_CAN_HAVE, MOM, - DAD, - BABY, + PERSON, + PERSON_CAN_HAVE, + RED, + WHITE, ) from adam.situation.templates.phase1_templates import property_variable, sampled from tests.learner import ( @@ -58,6 +59,10 @@ def integrated_learner_factory(language_mode: LanguageMode): attribute_learner=SubsetAttributeLearnerNew( ontology=GAILA_PHASE_1_ONTOLOGY, beam_size=5, language_mode=language_mode ), + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode + ), + language_mode=language_mode, ) @@ -75,10 +80,7 @@ def integrated_learner_factory(language_mode: LanguageMode): ], ) @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_attribute_leaner_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_subset_color_attribute( color_node, object_0_node, object_1_node, language_mode, learner ): diff --git a/tests/learner/subset_preposition_learner_test.py b/tests/learner/subset_preposition_learner_test.py index e5a60ab9e..403c59b22 100644 --- a/tests/learner/subset_preposition_learner_test.py +++ b/tests/learner/subset_preposition_learner_test.py @@ -1,9 +1,10 @@ import pytest + from adam.curriculum.curriculum_utils import ( PHASE1_CHOOSER_FACTORY, + PHASE1_TEST_CHOOSER_FACTORY, phase1_instances, standard_object, - PHASE1_TEST_CHOOSER_FACTORY, ) from adam.curriculum.phase1_curriculum import _x_has_y_template from adam.curriculum.preposition_curriculum import ( @@ -20,6 +21,7 @@ from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode from adam.learner.prepositions import SubsetPrepositionLearner +from adam.learner.quantifers import QuantifierTemplateLearner from adam.learner.relations import SubsetRelationLearnerNew from adam.ontology.phase1_ontology import ( BALL, @@ -55,6 +57,10 @@ def integrated_learner_factory(language_mode: LanguageMode): relation_learner=SubsetRelationLearnerNew( ontology=GAILA_PHASE_1_ONTOLOGY, beam_size=5, language_mode=language_mode ), + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode + ), + language_mode=language_mode, ) diff --git a/tests/learner/subset_verb_learner_test.py b/tests/learner/subset_verb_learner_test.py index e98b19290..a31b2ecc9 100644 --- a/tests/learner/subset_verb_learner_test.py +++ b/tests/learner/subset_verb_learner_test.py @@ -1,6 +1,7 @@ from itertools import chain import pytest + from adam.curriculum.curriculum_utils import ( PHASE1_CHOOSER_FACTORY, PHASE1_TEST_CHOOSER_FACTORY, @@ -9,7 +10,6 @@ ) from adam.curriculum.phase1_curriculum import ( _make_come_down_template, - make_push_templates, make_drink_template, make_eat_template, make_fall_templates, @@ -18,35 +18,37 @@ make_go_templates, make_jump_templates, make_move_templates, + make_push_templates, make_put_templates, make_roll_templates, make_sit_templates, make_spin_templates, make_take_template, - make_throw_templates, make_throw_animacy_templates, + make_throw_templates, ) from adam.language.language_utils import phase1_language_generator from adam.learner import LearningExample from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode +from adam.learner.quantifers import QuantifierTemplateLearner from adam.learner.verbs import SubsetVerbLearner, SubsetVerbLearnerNew -from adam.ontology import IS_SPEAKER, THING, IS_ADDRESSEE +from adam.ontology import IS_ADDRESSEE, IS_SPEAKER, THING from adam.ontology.phase1_ontology import ( - INANIMATE_OBJECT, - CAN_HAVE_THINGS_RESTING_ON_THEM, - INANIMATE, AGENT, ANIMATE, + CAN_HAVE_THINGS_RESTING_ON_THEM, + CAN_JUMP, + COME, + EDIBLE, GAILA_PHASE_1_ONTOLOGY, GOAL, + GROUND, HAS_SPACE_UNDER, + INANIMATE, + INANIMATE_OBJECT, LEARNER, PERSON, - GROUND, - COME, - CAN_JUMP, - EDIBLE, SELF_MOVING, ) from adam.situation import Action @@ -76,6 +78,10 @@ def integrated_learner_factory(language_mode: LanguageMode): action_learner=SubsetVerbLearnerNew( ontology=GAILA_PHASE_1_ONTOLOGY, beam_size=5, language_mode=language_mode ), + number_learner=QuantifierTemplateLearner.pretrained_for_language_mode( + language_mode + ), + language_mode=language_mode, ) @@ -140,10 +146,7 @@ def run_verb_test(learner, situation_template, language_generator): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_eat_simple(language_mode, learner): object_to_eat = standard_object("object_0", required_properties=[EDIBLE]) eater = standard_object( @@ -160,10 +163,7 @@ def test_eat_simple(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_drink(language_mode, learner): run_verb_test( learner(language_mode), @@ -173,10 +173,7 @@ def test_drink(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_sit(language_mode, learner): for situation_template in make_sit_templates(None): run_verb_test( @@ -187,10 +184,7 @@ def test_sit(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_put(language_mode, learner): for situation_template in make_put_templates(None): run_verb_test( @@ -201,10 +195,7 @@ def test_put(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_push(language_mode, learner): for situation_template in make_push_templates( agent=standard_object( @@ -228,10 +219,7 @@ def test_push(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_go(language_mode, learner): goer = standard_object("goer", THING, required_properties=[ANIMATE]) under_goal_reference = standard_object( @@ -259,10 +247,7 @@ def test_go(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_come(language_mode, learner): movee = standard_object( "movee", @@ -316,10 +301,7 @@ def test_come(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_take(language_mode, learner): run_verb_test( learner(language_mode), @@ -333,10 +315,7 @@ def test_take(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_give(language_mode, learner): for situation_template in make_give_templates(immutableset()): run_verb_test( @@ -347,10 +326,7 @@ def test_give(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_spin(language_mode, learner): for situation_template in make_spin_templates(None): run_verb_test( @@ -361,10 +337,7 @@ def test_spin(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_fall(language_mode, learner): for situation_template in make_fall_templates(immutableset()): run_verb_test( @@ -375,10 +348,7 @@ def test_fall(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_throw(language_mode, learner): for situation_template in make_throw_templates(None): run_verb_test( @@ -392,10 +362,7 @@ def test_throw(language_mode, learner): "language_mode", [LanguageMode.CHINESE, pytest.param(LanguageMode.ENGLISH, marks=pytest.mark.xfail)], ) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) # this tests gei vs. dau X shang for Chinese throw to # TODO: fix English implementation https://github.com/isi-vista/adam/issues/870 def test_throw_animacy(language_mode, learner): @@ -454,10 +421,7 @@ def test_throw_animacy(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_move(language_mode, learner): for situation_template in make_move_templates(None): run_verb_test( @@ -468,10 +432,7 @@ def test_move(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_jump(language_mode, learner): jumper = standard_object( @@ -500,10 +461,7 @@ def test_jump(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_roll(language_mode, learner): for situation_template in make_roll_templates(None): run_verb_test( @@ -514,10 +472,7 @@ def test_roll(language_mode, learner): @pytest.mark.parametrize("language_mode", [LanguageMode.ENGLISH, LanguageMode.CHINESE]) -@pytest.mark.parametrize( - "learner", - [pytest.mark.skip(subset_verb_language_factory), integrated_learner_factory], -) +@pytest.mark.parametrize("learner", [integrated_learner_factory]) def test_fly(language_mode, learner): for situation_template in make_fly_templates(immutableset()): run_verb_test( diff --git a/tests/learner/test_integrated_learner.py b/tests/learner/test_integrated_learner.py index 37febb41a..2c372d27e 100644 --- a/tests/learner/test_integrated_learner.py +++ b/tests/learner/test_integrated_learner.py @@ -1,5 +1,6 @@ -from more_itertools import one import pytest +from more_itertools import one + from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode from adam.ontology.phase1_ontology import DAD, GAILA_PHASE_1_ONTOLOGY @@ -10,7 +11,6 @@ from adam.random_utils import RandomChooser from adam.situation import SituationObject from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation - from tests.learner import LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER @@ -21,6 +21,7 @@ def test_with_object_recognizer(language_mode): attribute_learner=None, relation_learner=None, action_learner=None, + language_mode=language_mode, ) dad_situation_object = SituationObject.instantiate_ontology_node( diff --git a/tests/learner/test_object_recognizer.py b/tests/learner/test_object_recognizer.py index f24942318..55459fff6 100644 --- a/tests/learner/test_object_recognizer.py +++ b/tests/learner/test_object_recognizer.py @@ -1,9 +1,10 @@ import pytest from more_itertools import first, one + +from adam.curriculum.curriculum_utils import PHASE1_CHOOSER_FACTORY, phase1_instances from adam.language_specific.chinese.chinese_phase_1_lexicon import ( GAILA_PHASE_1_CHINESE_LEXICON, ) -from adam.curriculum.curriculum_utils import PHASE1_CHOOSER_FACTORY, phase1_instances from adam.language_specific.english.english_language_generator import PREFER_DITRANSITIVE from adam.learner import PerceptionSemanticAlignment from adam.learner.integrated_learner import IntegratedTemplateLearner @@ -33,8 +34,8 @@ sampled, ) from tests.learner import ( - LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER, LANGUAGE_MODE_TO_OBJECT_RECOGNIZER, + LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER, ) @@ -56,7 +57,8 @@ def test_recognizes_ontology_objects(object_type, language_mode): situation, chooser=RandomChooser.for_seed(0), include_ground=False ) learner = IntegratedTemplateLearner( - object_learner=LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER[language_mode] + object_learner=LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER[language_mode], + language_mode=language_mode, ) descriptions = learner.describe(perception) assert descriptions diff --git a/tests/ontology/ontology_test.py b/tests/ontology/ontology_test.py index 493200d16..3d31b29f5 100644 --- a/tests/ontology/ontology_test.py +++ b/tests/ontology/ontology_test.py @@ -1,15 +1,14 @@ -from immutablecollections import immutableset - from adam.ontology.phase1_ontology import ( BABY, DAD, GAILA_PHASE_1_ONTOLOGY, - IS_HUMAN, HAT, + IS_HUMAN, MOM, PERSON, THING, ) +from immutablecollections import immutableset def test_descends_from(): diff --git a/tests/ontology/selectors_test.py b/tests/ontology/selectors_test.py index 31bb1a9a7..fbe6e0d71 100644 --- a/tests/ontology/selectors_test.py +++ b/tests/ontology/selectors_test.py @@ -1,5 +1,3 @@ -from immutablecollections import immutableset - from adam.ontology.phase1_ontology import ( AGENT, FALL, @@ -9,6 +7,7 @@ THROW, ) from adam.ontology.selectors import SubcategorizationSelector +from immutablecollections import immutableset def test_subcategorization_selector(): diff --git a/tests/perception/developmental_primitive_perception_test.py b/tests/perception/developmental_primitive_perception_test.py index 8955781f2..678f00db9 100644 --- a/tests/perception/developmental_primitive_perception_test.py +++ b/tests/perception/developmental_primitive_perception_test.py @@ -3,11 +3,11 @@ IS_DAD, IS_MOM, SENTIENT, - above, - _PERSON_SCHEMA, _BALL_SCHEMA, + _PERSON_SCHEMA, _TABLE_SCHEMA, _make_cup_schema, + above, ) from adam.ontology.phase1_spatial_relations import EXTERIOR_BUT_IN_CONTACT, Region from adam.perception import ObjectPerception, PerceptualRepresentation 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 64eddc9fa..3f8905d75 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 @@ -1,14 +1,13 @@ import pytest -from immutablecollections import immutableset from more_itertools import only, quantify from adam.axes import HorizontalAxisOfObject -from adam.ontology import IN_REGION, OntologyNode, IS_SPEAKER +from adam.ontology import IN_REGION, IS_SPEAKER, OntologyNode from adam.ontology.phase1_ontology import ( AGENT, ANIMATE, - BALL, BABY, + BALL, BLACK, BLUE, BOX, @@ -47,13 +46,13 @@ ) from adam.ontology.phase1_spatial_relations import ( DISTAL, + Direction, EXTERIOR_BUT_IN_CONTACT, GRAVITATIONAL_UP, INTERIOR, + PROXIMAL, Region, TOWARD, - PROXIMAL, - Direction, ) from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, @@ -71,6 +70,7 @@ from adam.situation import Action from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation from adam_test_utils import perception_with_handle, situation_object +from immutablecollections import immutableset from sample_situations import make_bird_flies_over_a_house _PERCEPTION_GENERATOR = HighLevelSemanticsSituationToDevelopmentalPrimitivePerceptionGenerator( diff --git a/tests/perception/marr_test.py b/tests/perception/marr_test.py index 12d625b4d..e7509c594 100644 --- a/tests/perception/marr_test.py +++ b/tests/perception/marr_test.py @@ -1,5 +1,3 @@ -from immutablecollections import immutabledict - from adam.perception.marr import ( AdjunctRelation, Cylinder, @@ -7,6 +5,7 @@ feet_to_meters, inches_to_meters, ) +from immutablecollections import immutabledict def make_test_human_object(): diff --git a/tests/perception/perception_graph_test.py b/tests/perception/perception_graph_test.py index 45efdd58c..faf266981 100644 --- a/tests/perception/perception_graph_test.py +++ b/tests/perception/perception_graph_test.py @@ -33,7 +33,7 @@ ) from adam.ontology.phase1_spatial_relations import DISTAL, EXTERIOR_BUT_IN_CONTACT, Region from adam.ontology.structural_schema import ObjectStructuralSchema -from adam.perception import ObjectPerception, PerceptualRepresentation, MatchMode +from adam.perception import MatchMode, ObjectPerception, PerceptualRepresentation from adam.perception.developmental_primitive_perception import ( DevelopmentalPrimitivePerceptionFrame, RgbColorPerception, @@ -42,17 +42,17 @@ GAILA_PHASE_1_PERCEPTION_GENERATOR, ) from adam.perception.perception_graph import ( + AnyEdgePredicate, + AnyObjectPerception, + HoldsAtTemporalScopePredicate, IsColorNodePredicate, PatternMatching, PerceptionGraph, + PerceptionGraphNode, PerceptionGraphPattern, PerceptionGraphPatternMatch, TemporalScope, TemporallyScopedEdgeLabel, - HoldsAtTemporalScopePredicate, - AnyEdgePredicate, - AnyObjectPerception, - PerceptionGraphNode, ) from adam.random_utils import RandomChooser from adam.relation import Relation diff --git a/tests/pipeline_test.py b/tests/pipeline_test.py index a2ed73df4..0ec3d3678 100644 --- a/tests/pipeline_test.py +++ b/tests/pipeline_test.py @@ -1,11 +1,10 @@ -from vistautils.iter_utils import only - from adam.language import TokenSequenceLinguisticDescription from adam.learner import LearningExample, MemorizingLanguageLearner from adam.perception import ( BagOfFeaturesPerceptualRepresentationFrame, PerceptualRepresentation, ) +from vistautils.iter_utils import only def test_pipeline(): diff --git a/tests/situation/high_level_semantics_situation.py b/tests/situation/high_level_semantics_situation.py index 3373909f0..9a8c235ea 100644 --- a/tests/situation/high_level_semantics_situation.py +++ b/tests/situation/high_level_semantics_situation.py @@ -1,12 +1,12 @@ from adam.ontology.phase1_ontology import ( - MOM, + AGENT, BALL, - TABLE, - PUT, + GAILA_PHASE_1_ONTOLOGY, GOAL, + MOM, + PUT, + TABLE, THEME, - AGENT, - GAILA_PHASE_1_ONTOLOGY, ) from adam.ontology.phase1_spatial_relations import ( EXTERIOR_BUT_IN_CONTACT, diff --git a/tests/situation/templates/phase1_template_test.py b/tests/situation/templates/phase1_template_test.py index 8a715b7a9..cb1f56096 100644 --- a/tests/situation/templates/phase1_template_test.py +++ b/tests/situation/templates/phase1_template_test.py @@ -1,35 +1,30 @@ from typing import Iterable -from immutablecollections import ( - ImmutableSetMultiDict, - immutableset, - immutablesetmultidict, -) - +from adam.axes import WORLD_AXES from adam.ontology import ( CAN_FILL_TEMPLATE_SLOT, + IS_ADDRESSEE, OntologyNode, PROPERTY, REQUIRED_ONTOLOGY_NODES, THING, minimal_ontology_graph, - IS_ADDRESSEE, ) from adam.ontology.ontology import Ontology from adam.ontology.phase1_ontology import ( - RECOGNIZED_PARTICULAR_PROPERTY, - LEARNER, + AGENT, BALL, - near, + BOX, GAILA_PHASE_1_ONTOLOGY, - MOM, GROUND, - BOX, + LEARNER, + MOM, + RECOGNIZED_PARTICULAR_PROPERTY, ROLL, - AGENT, ROLL_SURFACE_AUXILIARY, - on, far, + near, + on, ) from adam.ontology.structural_schema import ObjectStructuralSchema from adam.random_utils import RandomChooser @@ -41,7 +36,11 @@ object_variable, sampled, ) -from adam.axes import WORLD_AXES +from immutablecollections import ( + ImmutableSetMultiDict, + immutableset, + immutablesetmultidict, +) _TESTING_ONTOLOGY_GRAPH = minimal_ontology_graph() _TESTING_ONTOLOGY_GRAPH.add_node(RECOGNIZED_PARTICULAR_PROPERTY) diff --git a/tests/visualization/make_scenes_test.py b/tests/visualization/make_scenes_test.py index b0c72ee91..8be59a4e4 100644 --- a/tests/visualization/make_scenes_test.py +++ b/tests/visualization/make_scenes_test.py @@ -1,13 +1,14 @@ +from typing import Tuple + from adam.curriculum.phase1_curriculum import build_gaila_phase_1_curriculum +from adam.geon import CrossSection from adam.language.language_utils import phase2_language_generator from adam.learner import LanguageMode -from adam.visualization.make_scenes import SceneCreator -from adam.geon import CrossSection -from adam.visualization.utils import Shape, cross_section_to_geon from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import ( ObjectPerception, ) -from typing import Tuple +from adam.visualization.make_scenes import SceneCreator +from adam.visualization.utils import Shape, cross_section_to_geon def test_scenes_creation() -> Tuple[ diff --git a/tests/visualization/panda_interface_test.py b/tests/visualization/panda_interface_test.py index f26011c35..dc421e4bf 100644 --- a/tests/visualization/panda_interface_test.py +++ b/tests/visualization/panda_interface_test.py @@ -1,4 +1,5 @@ from math import isclose + from pandac.PandaModules import ConfigVariableString # pylint: disable=no-name-in-module from adam.visualization.panda3d_interface import SituationVisualizer diff --git a/tests/visualization/positioning_test.py b/tests/visualization/positioning_test.py index 7143a4bfd..1caceb69f 100644 --- a/tests/visualization/positioning_test.py +++ b/tests/visualization/positioning_test.py @@ -1,34 +1,33 @@ +from math import isclose, pi +from typing import List, Mapping, Tuple + import numpy as np import torch -from math import isclose, pi -from immutablecollections import immutableset - -from adam.visualization.positioning import ( - AxisAlignedBoundingBox, - CollisionPenalty, - WeakGravityPenalty, - run_model, - angle_between, - InRegionPenalty, -) -from typing import Mapping, List, Tuple -from adam.perception import ObjectPerception, GROUND_PERCEPTION from adam.axes import ( Axes, + HorizontalAxisOfObject, straight_up, - # directed, symmetric, symmetric_vertical, -) +) # directed, from adam.ontology.phase1_spatial_relations import ( - Region, - PROXIMAL, Direction, - GRAVITATIONAL_UP, EXTERIOR_BUT_IN_CONTACT, + GRAVITATIONAL_UP, + PROXIMAL, + Region, +) +from adam.perception import GROUND_PERCEPTION, ObjectPerception +from adam.visualization.positioning import ( + AxisAlignedBoundingBox, + CollisionPenalty, + InRegionPenalty, + WeakGravityPenalty, + angle_between, + run_model, ) -from adam.axes import HorizontalAxisOfObject +from immutablecollections import immutableset def test_running_model() -> None: From 771699fb79ef4d1b008cbfe44b332e6bb3636285 Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Thu, 23 Jul 2020 16:56:54 -0400 Subject: [PATCH 03/11] Test for plural learning --- adam/curriculum/phase1_curriculum.py | 32 +++------ adam/curriculum/phase2_curriculum.py | 4 +- adam/learner/integrated_learner.py | 8 +++ adam/learner/quantifers.py | 9 +++ tests/curriculum/phase1_curriculum_test.py | 2 +- tests/learner/test_quantifier_learner.py | 82 ++++++++++++++++++++++ 6 files changed, 111 insertions(+), 26 deletions(-) create mode 100644 tests/learner/test_quantifier_learner.py diff --git a/adam/curriculum/phase1_curriculum.py b/adam/curriculum/phase1_curriculum.py index 6614c1b15..230b24a1f 100644 --- a/adam/curriculum/phase1_curriculum.py +++ b/adam/curriculum/phase1_curriculum.py @@ -2,7 +2,6 @@ Curricula for DARPA GAILA Phase 1 """ from itertools import chain -from math import ceil from typing import Dict, Iterable, List, Optional, Sequence from more_itertools import first, flatten @@ -327,28 +326,25 @@ def _make_objects_with_colors_is_curriculum( # We ignore any noise objects in this curriculum as pursuit # has its own implementation method def _make_plural_objects_curriculum( # pylint: disable=unused-argument - num_samples: Optional[int], - noise_objects: Optional[int], language_generator: LanguageGenerator[ HighLevelSemanticsSituation, LinearizedDependencyTree ], ) -> Phase1InstanceGroup: def build_object_multiples_situations( - ontology: Ontology, *, samples_per_object: int = 3, chooser: RandomChooser + ontology: Ontology, *, chooser: RandomChooser ) -> Iterable[HighLevelSemanticsSituation]: - for object_type in PHASE_1_CURRICULUM_OBJECTS: - is_liquid = ontology.has_all_properties(object_type, [LIQUID]) - # don't want multiples of named people - if not is_recognized_particular(ontology, object_type) and not is_liquid: - for _ in range(samples_per_object): - num_objects = chooser.choice(range(2, 4)) + for num_objects in range(1, 5): + for object_type in PHASE_1_CURRICULUM_OBJECTS: + is_liquid = ontology.has_all_properties(object_type, [LIQUID]) + # don't want multiples of named people + if not is_recognized_particular(ontology, object_type) and not is_liquid: yield HighLevelSemanticsSituation( - ontology=GAILA_PHASE_1_ONTOLOGY, + ontology=ontology, salient_objects=[ SituationObject.instantiate_ontology_node( ontology_node=object_type, debug_handle=object_type.handle + f"_{idx}", - ontology=GAILA_PHASE_1_ONTOLOGY, + ontology=ontology, ) for idx in range(num_objects) ], @@ -358,11 +354,7 @@ def build_object_multiples_situations( return phase1_instances( "multiples of the same object", build_object_multiples_situations( - ontology=GAILA_PHASE_1_ONTOLOGY, - chooser=PHASE1_CHOOSER_FACTORY(), - samples_per_object=max(ceil(num_samples / len(PHASE_1_CURRICULUM_OBJECTS)), 3) - if num_samples - else 3, + ontology=GAILA_PHASE_1_ONTOLOGY, chooser=PHASE1_CHOOSER_FACTORY() ), language_generator=language_generator, ) @@ -3016,11 +3008,7 @@ def build_gaila_plurals_curriculum( HighLevelSemanticsSituation, LinearizedDependencyTree ], ) -> Sequence[Phase1InstanceGroup]: - return [ - _make_plural_objects_curriculum( - num_samples, num_noise_objects, language_generator - ) - ] + return [_make_plural_objects_curriculum(language_generator)] def build_gaila_generics_curriculum( diff --git a/adam/curriculum/phase2_curriculum.py b/adam/curriculum/phase2_curriculum.py index 8b835dfcb..e7b0d7a45 100644 --- a/adam/curriculum/phase2_curriculum.py +++ b/adam/curriculum/phase2_curriculum.py @@ -309,9 +309,7 @@ def build_gaila_m8_curriculum( return list( chain( [ - _make_plural_objects_curriculum( - num_samples, num_noise_objects, language_generator - ), # plurals + _make_plural_objects_curriculum(language_generator), # plurals _make_sit_on_chair_curriculum( num_samples, num_noise_objects, language_generator ), # functionally defined objects diff --git a/adam/learner/integrated_learner.py b/adam/learner/integrated_learner.py index 141d345eb..81a63f6f6 100644 --- a/adam/learner/integrated_learner.py +++ b/adam/learner/integrated_learner.py @@ -162,6 +162,14 @@ def observe( if learning_example.perception.is_dynamic() and self.action_learner: self.action_learner.learn_from(current_learner_state) + if self.number_learner: + self.number_learner.learn_from( + current_learner_state.language_concept_alignment, + LearnerSemantics.from_nodes( + current_learner_state.perception_semantic_alignment.semantic_nodes + ), + ) + def describe( self, perception: PerceptualRepresentation[DevelopmentalPrimitivePerceptionFrame] ) -> Mapping[LinguisticDescription, float]: diff --git a/adam/learner/quantifers.py b/adam/learner/quantifers.py index 348e641b8..117cb01b3 100644 --- a/adam/learner/quantifers.py +++ b/adam/learner/quantifers.py @@ -245,6 +245,15 @@ def _number_expression_hypotheses( # We currently limit ourselves to cases # where the object + plural marker is the entire utterance. + # Account for English determiner hack + if token_sequence[span_for_object.start] in ("a", "the"): + ret.append( + SurfaceTemplate( + [token_sequence[span_for_object.start], SLOT1], + language_mode=self.language_mode, + ) + ) + # Any tokens immediately before or after the expression of an object # are candidate expressions of pluralization. preceding_token_index = span_for_object.start - 1 diff --git a/tests/curriculum/phase1_curriculum_test.py b/tests/curriculum/phase1_curriculum_test.py index 088610ba5..2378f673e 100644 --- a/tests/curriculum/phase1_curriculum_test.py +++ b/tests/curriculum/phase1_curriculum_test.py @@ -121,7 +121,7 @@ def test_instantiate_fly_curriculum(language_generator): [GAILA_PHASE_1_LANGUAGE_GENERATOR, GAILA_PHASE_1_CHINESE_LANGUAGE_GENERATOR], ) def test_plural_objects_curriculum(language_generator): - curriculum_test(_make_plural_objects_curriculum(None, None, language_generator)) + curriculum_test(_make_plural_objects_curriculum(language_generator)) @pytest.mark.parametrize( diff --git a/tests/learner/test_quantifier_learner.py b/tests/learner/test_quantifier_learner.py new file mode 100644 index 000000000..4cd41a7c5 --- /dev/null +++ b/tests/learner/test_quantifier_learner.py @@ -0,0 +1,82 @@ +from random import Random, shuffle + +from adam.curriculum.curriculum_utils import PHASE1_CHOOSER_FACTORY +from adam.curriculum.phase1_curriculum import _make_plural_objects_curriculum +from adam.language_specific.english.english_language_generator import ( + GAILA_PHASE_1_LANGUAGE_GENERATOR, +) +from adam.learner import LanguageMode, LearningExample +from adam.learner.integrated_learner import IntegratedTemplateLearner +from adam.learner.quantifers import ToleranceRuleQuantifierTemplateLearner +from adam.ontology.phase1_ontology import BALL, GAILA_PHASE_1_ONTOLOGY +from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import ( + GAILA_PHASE_1_PERCEPTION_GENERATOR, +) +from adam.situation.templates.phase1_templates import ( + Phase1SituationTemplate, + all_possible, + object_variable, +) +from learner import LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER + + +def test_english_quantifier_learning(): + plural_curriculum = _make_plural_objects_curriculum(GAILA_PHASE_1_LANGUAGE_GENERATOR) + instances = list(plural_curriculum.instances()) + shuffle(instances, Random(0).random) + + learner = IntegratedTemplateLearner( + object_learner=LANGUAGE_MODE_TO_TEMPLATE_LEARNER_OBJECT_RECOGNIZER[ + LanguageMode.ENGLISH + ], + number_learner=ToleranceRuleQuantifierTemplateLearner( + language_mode=LanguageMode.ENGLISH, min_types_to_lexicalize=4 + ), + language_mode=LanguageMode.ENGLISH, + ) + + for (_, language, perception) in instances: + learner.observe( + LearningExample(perception=perception, linguistic_description=language) + ) + + ball_1 = object_variable("ball_1", BALL) + ball_2 = object_variable("ball_2", BALL) + ball_3 = object_variable("ball_3", BALL) + ball_4 = object_variable("ball_4", BALL) + + one_ball_situation = Phase1SituationTemplate( + "one ball", salient_object_variables=[ball_1] + ) + two_balls_situation = Phase1SituationTemplate( + "two balls", salient_object_variables=[ball_1, ball_2] + ) + three_balls_situation = Phase1SituationTemplate( + "three balls", salient_object_variables=[ball_1, ball_2, ball_3] + ) + four_balls_situation = Phase1SituationTemplate( + "four balls", salient_object_variables=[ball_1, ball_2, ball_3, ball_4] + ) + references = { + one_ball_situation: [("a", "ball")], + two_balls_situation: [("two", "balls"), ("balls")], + three_balls_situation: [("many", "balls"), ("balls")], + four_balls_situation: [("many", "balls"), ("balls")], + } + + for (test_situation_template, references) in references.items(): + for test_situation in all_possible( + test_situation_template, + chooser=PHASE1_CHOOSER_FACTORY(), + ontology=GAILA_PHASE_1_ONTOLOGY, + ): + description = tuple( + x.as_token_sequence() + for x in learner.describe( + GAILA_PHASE_1_PERCEPTION_GENERATOR.generate_perception( + test_situation, chooser=PHASE1_CHOOSER_FACTORY() + ) + ) + ) + for reference in references: + assert reference in description From 6521f553f12225a3cfa5e22f08b2655ebfa8dce7 Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Thu, 23 Jul 2020 17:28:46 -0400 Subject: [PATCH 04/11] Allow X slot Y hypotheses for number expression --- adam/learner/quantifers.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/adam/learner/quantifers.py b/adam/learner/quantifers.py index 117cb01b3..497632b28 100644 --- a/adam/learner/quantifers.py +++ b/adam/learner/quantifers.py @@ -283,6 +283,18 @@ def _number_expression_hypotheses( ) ) + if not object_at_left_edge and not object_at_right_edge: + ret.append( + SurfaceTemplate( + [ + token_sequence[span_for_object.start - 1], + SLOT1, + token_sequence[span_for_object.end], + ], + language_mode=self.language_mode, + ) + ) + # We will consider a no-op hypothesis only if everything on both sides # is aready aligned if object_at_left_edge and object_at_right_edge: From bb95a8342a4bbde038d1dce5057c66997a8a742c Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Thu, 23 Jul 2020 17:29:05 -0400 Subject: [PATCH 05/11] Fix number learning tests to run non-singular tests --- adam/situation/templates/phase1_templates.py | 5 ++++- tests/learner/test_quantifier_learner.py | 11 ++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/adam/situation/templates/phase1_templates.py b/adam/situation/templates/phase1_templates.py index 1cf00d024..7afef1bd2 100644 --- a/adam/situation/templates/phase1_templates.py +++ b/adam/situation/templates/phase1_templates.py @@ -299,13 +299,16 @@ def all_possible( ontology: Ontology, chooser: SequenceChooser, default_addressee_node: OntologyNode = LEARNER, + block_multiple_objects_of_the_same_type: bool = True, ) -> Iterable[HighLevelSemanticsSituation]: """ Generator for all possible instantiations of *situation_template* with *ontology*. """ return list( _Phase1SituationTemplateGenerator( - ontology=ontology, variable_assigner=_CrossProductVariableAssigner() + ontology=ontology, + variable_assigner=_CrossProductVariableAssigner(), + block_multiple_objects_of_the_same_type=block_multiple_objects_of_the_same_type, ).generate_situations( situation_template, chooser=chooser, diff --git a/tests/learner/test_quantifier_learner.py b/tests/learner/test_quantifier_learner.py index 4cd41a7c5..61742ea62 100644 --- a/tests/learner/test_quantifier_learner.py +++ b/tests/learner/test_quantifier_learner.py @@ -57,18 +57,19 @@ def test_english_quantifier_learning(): four_balls_situation = Phase1SituationTemplate( "four balls", salient_object_variables=[ball_1, ball_2, ball_3, ball_4] ) - references = { + situation_to_references = { one_ball_situation: [("a", "ball")], - two_balls_situation: [("two", "balls"), ("balls")], - three_balls_situation: [("many", "balls"), ("balls")], - four_balls_situation: [("many", "balls"), ("balls")], + two_balls_situation: [("two", "ball", "s"), ("ball", "s")], + three_balls_situation: [("many", "ball", "s"), ("ball", "s")], + four_balls_situation: [("many", "ball", "s"), ("ball", "s")], } - for (test_situation_template, references) in references.items(): + for (test_situation_template, references) in situation_to_references.items(): for test_situation in all_possible( test_situation_template, chooser=PHASE1_CHOOSER_FACTORY(), ontology=GAILA_PHASE_1_ONTOLOGY, + block_multiple_objects_of_the_same_type=False, ): description = tuple( x.as_token_sequence() From 4ea187410afc6acc5500efce9fe2db350ec6b97a Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Fri, 24 Jul 2020 10:21:38 -0400 Subject: [PATCH 06/11] Add plurals to log_experiments --- adam/experiment/log_experiment.py | 18 +++++++++++++++++- parameters/experiments/m13/plurals.params | 7 +++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 parameters/experiments/m13/plurals.params diff --git a/adam/experiment/log_experiment.py b/adam/experiment/log_experiment.py index 98dc53dfd..2d5f757f4 100644 --- a/adam/experiment/log_experiment.py +++ b/adam/experiment/log_experiment.py @@ -14,6 +14,7 @@ build_gaila_phase1_relation_curriculum, build_gaila_phase1_verb_curriculum, build_gaila_phase_1_curriculum, + build_gaila_plurals_curriculum, ) from adam.curriculum.phase2_curriculum import ( build_functionally_defined_objects_curriculum, @@ -51,7 +52,10 @@ ) from adam.learner.prepositions import SubsetPrepositionLearner from adam.learner.pursuit import HypothesisLogger -from adam.learner.quantifers import QuantifierTemplateLearner +from adam.learner.quantifers import ( + QuantifierTemplateLearner, + ToleranceRuleQuantifierTemplateLearner, +) from adam.learner.relations import SubsetRelationLearnerNew from adam.learner.verbs import SubsetVerbLearner, SubsetVerbLearnerNew from adam.ontology.phase1_ontology import ( @@ -139,6 +143,7 @@ def learner_factory_from_params( "verb-subset", "integrated-learner", "integrated-learner-recognizer", + "integrated-learner-recognizer-learn-quantifiers", ], ) @@ -240,6 +245,16 @@ def learner_factory_from_params( ), language_mode=language_mode, ) + elif learner_type == "integrated-learner-recognizer-learn-quantifiers": + return lambda: IntegratedTemplateLearner( + object_learner=ObjectRecognizerAsTemplateLearner( + object_recognizer=object_recognizer, language_mode=language_mode + ), + number_learner=ToleranceRuleQuantifierTemplateLearner( + language_mode=language_mode, min_types_to_lexicalize=4 + ), + language_mode=language_mode, + ) else: raise RuntimeError("can't happen") @@ -280,6 +295,7 @@ def curriculum_from_params( make_verb_with_dynamic_prepositions_curriculum, None, ), + "m13-plurals": (build_gaila_plurals_curriculum, None), "m13-shuffled": (build_m13_shuffled_curriculum, build_gaila_m13_curriculum), } diff --git a/parameters/experiments/m13/plurals.params b/parameters/experiments/m13/plurals.params new file mode 100644 index 000000000..c37780db3 --- /dev/null +++ b/parameters/experiments/m13/plurals.params @@ -0,0 +1,7 @@ +_includes: + - "../../root.params" + - "m13.params" + +experiment: 'm13-plurals' +curriculum: 'm13-plurals' +learner: 'integrated-learner-recognizer-learn-quantifiers' \ No newline at end of file From 88a90642ceb785e88887ca54be3d49a3f2858c7e Mon Sep 17 00:00:00 2001 From: Ryan Gabbard Date: Fri, 24 Jul 2020 10:22:01 -0400 Subject: [PATCH 07/11] Fix bugs in plural curriculum --- adam/language_specific/english/__init__.py | 1 + adam/learner/integrated_learner.py | 49 +++++++++++++--------- adam/learner/surface_templates.py | 28 ++++++------- tests/learner/test_quantifier_learner.py | 21 ++++++++-- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/adam/language_specific/english/__init__.py b/adam/language_specific/english/__init__.py index 99dc5b8fe..e939d73f4 100644 --- a/adam/language_specific/english/__init__.py +++ b/adam/language_specific/english/__init__.py @@ -14,3 +14,4 @@ """ ENGLISH_MASS_NOUNS = ["juice", "water", "milk"] ENGLISH_RECOGNIZED_PARTICULARS = immutableset(["me", "you", "Mom", "Dad"]) +ENGLISH_THE_WORDS = ["ground"] diff --git a/adam/learner/integrated_learner.py b/adam/learner/integrated_learner.py index 81a63f6f6..aa6a4ae89 100644 --- a/adam/learner/integrated_learner.py +++ b/adam/learner/integrated_learner.py @@ -11,6 +11,7 @@ ENGLISH_BLOCK_DETERMINERS, ENGLISH_MASS_NOUNS, ENGLISH_RECOGNIZED_PARTICULARS, + ENGLISH_THE_WORDS, ) from adam.learner import LearningExample, TopLevelLanguageLearner from adam.learner.alignments import ( @@ -19,7 +20,7 @@ PerceptionSemanticAlignment, ) from adam.learner.language_mode import LanguageMode -from adam.learner.surface_templates import SLOT1, SLOT2 +from adam.learner.surface_templates import SLOT1, SLOT2, SurfaceTemplate from adam.learner.template_learner import SemanticTemplateLearner, TemplateLearner from adam.perception import PerceptualRepresentation from adam.perception.developmental_primitive_perception import ( @@ -450,25 +451,30 @@ def _handle_quantifiers( block_determiners = True if object_node.concept.debug_string in ENGLISH_RECOGNIZED_PARTICULARS: block_determiners = True - if block_determiners: - return cur_string - - found_a_quantifier = False - for quantifier in semantics.quantifiers: - if quantifier.slot_fillings[SLOT1] == object_node: - found_a_quantifier = True - for quantifier_template in self.number_learner.templates_for_concept( - quantifier.concept - ): - yield quantifier_template.instantiate( - {SLOT1: cur_string} - ).as_token_sequence() - - if not found_a_quantifier: - raise RuntimeError( - f"Every object node should have a quantifier but could not find one " - f"for {object_node}" - ) + if object_node.concept.debug_string in ENGLISH_THE_WORDS: + yield ENGLISH_THE_TEMPLATE.instantiate( + {SLOT1: cur_string} + ).as_token_sequence() + return + if block_determiners: + yield cur_string + else: + found_a_quantifier = False + for quantifier in semantics.quantifiers: + if quantifier.slot_fillings[SLOT1] == object_node: + found_a_quantifier = True + for quantifier_template in self.number_learner.templates_for_concept( + quantifier.concept + ): + yield quantifier_template.instantiate( + {SLOT1: cur_string} + ).as_token_sequence() + + if not found_a_quantifier: + raise RuntimeError( + f"Every object node should have a quantifier but could not find one " + f"for {object_node}" + ) def _instantiate_object( self, object_node: ObjectSemanticNode, learner_semantics: "LearnerSemantics" @@ -594,3 +600,6 @@ def _init_sub_learners(self) -> List[TemplateLearner]: if self.action_learner: valid_sub_learners.append(self.action_learner) return valid_sub_learners + + +ENGLISH_THE_TEMPLATE = SurfaceTemplate(["the", SLOT1], language_mode=LanguageMode.ENGLISH) diff --git a/adam/learner/surface_templates.py b/adam/learner/surface_templates.py index 93931fb79..8aca0e114 100644 --- a/adam/learner/surface_templates.py +++ b/adam/learner/surface_templates.py @@ -52,20 +52,20 @@ def instantiate( for element in self.elements: if isinstance(element, SyntaxSemanticsVariable): filler_words = template_variable_to_filler[element] - # Ground is a specific thing so we special case this to be assigned - if filler_words[0] == "ground": - output_tokens.append("the") - # English-specific hack to deal with us not understanding determiners: - # https://github.com/isi-vista/adam/issues/498 - # The "is lower" check is a hack to block adding a determiner to proper names. - elif ( - self._language_mode == LanguageMode.ENGLISH - and element in self._determiner_prefix_slots - and len(filler_words) == 1 - and filler_words[0][0].islower() - and filler_words[0] not in ENGLISH_MASS_NOUNS - ): - output_tokens.append("a") + # # Ground is a specific thing so we special case this to be assigned + # if filler_words[0] == "ground": + # output_tokens.append("the") + # # English-specific hack to deal with us not understanding determiners: + # # https://github.com/isi-vista/adam/issues/498 + # # The "is lower" check is a hack to block adding a determiner to proper names. + # elif ( + # self._language_mode == LanguageMode.ENGLISH + # and element in self._determiner_prefix_slots + # and len(filler_words) == 1 + # and filler_words[0][0].islower() + # and filler_words[0] not in ENGLISH_MASS_NOUNS + # ): + # output_tokens.append("a") output_tokens.extend(filler_words) else: # element must be a single token str due to object validity checks. diff --git a/tests/learner/test_quantifier_learner.py b/tests/learner/test_quantifier_learner.py index 61742ea62..cd88b2055 100644 --- a/tests/learner/test_quantifier_learner.py +++ b/tests/learner/test_quantifier_learner.py @@ -58,10 +58,23 @@ def test_english_quantifier_learning(): "four balls", salient_object_variables=[ball_1, ball_2, ball_3, ball_4] ) situation_to_references = { - one_ball_situation: [("a", "ball")], - two_balls_situation: [("two", "ball", "s"), ("ball", "s")], - three_balls_situation: [("many", "ball", "s"), ("ball", "s")], - four_balls_situation: [("many", "ball", "s"), ("ball", "s")], + one_ball_situation: [("a", "ball"), ("the", "ground")], + # "a ball" included for plurals because we don't do any pragmatics. + # No Grice's Maxim of Quantity for us! + two_balls_situation: [("two", "ball", "s"), ("a", "ball"), ("the", "ground")], + # "two balls" included for the same reason + three_balls_situation: [ + ("many", "ball", "s"), + ("two", "ball", "s"), + ("a", "ball"), + ("the", "ground"), + ], + four_balls_situation: [ + ("many", "ball", "s"), + ("a", "ball"), + ("two", "ball", "s"), + ("the", "ground"), + ], } for (test_situation_template, references) in situation_to_references.items(): From a3406a093b35bff96b0a9a8241d68444b13bfdc1 Mon Sep 17 00:00:00 2001 From: paynesa Date: Mon, 27 Jul 2020 15:07:48 -0400 Subject: [PATCH 08/11] fix import issues that are causing CI failure --- adam/curriculum/phase1_curriculum.py | 4 ++-- adam/learner/surface_templates.py | 3 ++- adam/visualization/make_scenes.py | 5 +---- adam/visualization/panda3d_interface.py | 7 ++----- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/adam/curriculum/phase1_curriculum.py b/adam/curriculum/phase1_curriculum.py index 230b24a1f..aa7c7cf99 100644 --- a/adam/curriculum/phase1_curriculum.py +++ b/adam/curriculum/phase1_curriculum.py @@ -3002,8 +3002,8 @@ def build_gaila_phase1_object_curriculum( def build_gaila_plurals_curriculum( - num_samples: Optional[int], - num_noise_objects: Optional[int], + num_samples: Optional[int], # pylint: disable=unused-argument + num_noise_objects: Optional[int], # pylint: disable=unused-argument language_generator: LanguageGenerator[ HighLevelSemanticsSituation, LinearizedDependencyTree ], diff --git a/adam/learner/surface_templates.py b/adam/learner/surface_templates.py index 8aca0e114..9d0de3f90 100644 --- a/adam/learner/surface_templates.py +++ b/adam/learner/surface_templates.py @@ -6,7 +6,8 @@ from more_itertools import quantify from adam.language import TokenSequenceLinguisticDescription -from adam.language_specific.english import ENGLISH_MASS_NOUNS + +# from adam.language_specific.english import ENGLISH_MASS_NOUNS from adam.learner.language_mode import LanguageMode from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs diff --git a/adam/visualization/make_scenes.py b/adam/visualization/make_scenes.py index b6269f482..8bb8d3f32 100644 --- a/adam/visualization/make_scenes.py +++ b/adam/visualization/make_scenes.py @@ -29,10 +29,7 @@ import numpy as np # consider refactoring away this dependency -from panda3d.core import ( - LPoint3f, - NodePath, -) # pylint: disable=no-name-in-module; pylint: disable=no-name-in-module +from panda3d.core import LPoint3f, NodePath # pylint: disable=no-name-in-module import attr from adam.curriculum.phase1_curriculum import Phase1InstanceGroup diff --git a/adam/visualization/panda3d_interface.py b/adam/visualization/panda3d_interface.py index e7756928d..b9d9dea4c 100644 --- a/adam/visualization/panda3d_interface.py +++ b/adam/visualization/panda3d_interface.py @@ -18,7 +18,7 @@ from direct.gui.OnscreenText import OnscreenText # pylint: disable=no-name-in-module from direct.showbase.ShowBase import ShowBase # pylint: disable=no-name-in-module -from panda3d.core import ( +from panda3d.core import ( # pylint: disable=no-name-in-module AmbientLight, AntialiasAttrib, DirectionalLight, @@ -28,11 +28,8 @@ NodePath, PointLight, TextNode, -) # pylint: disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: +) -# disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: -# disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: -# disable=no-name-in-module; pylint: disable=no-name-in-module; pylint: disable=no-name-in-module from torch import Tensor from adam.perception.developmental_primitive_perception import RgbColorPerception From 5d7f7fc429eec7a8f36c62aaf7dca6d2624c8d89 Mon Sep 17 00:00:00 2001 From: paynesa Date: Mon, 27 Jul 2020 15:23:31 -0400 Subject: [PATCH 09/11] import fix --- adam/experiment/log_experiment.py | 20 ++------------------ adam/perception/perception_graph.py | 2 +- tests/learner/__init__.py | 1 - 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/adam/experiment/log_experiment.py b/adam/experiment/log_experiment.py index 1c56ebf04..77c987d5b 100644 --- a/adam/experiment/log_experiment.py +++ b/adam/experiment/log_experiment.py @@ -7,15 +7,7 @@ make_imprecise_temporal_descriptions, make_subtle_verb_distinctions_curriculum, ) -from adam.curriculum.m6_curriculum import make_m6_curriculum -from adam.curriculum.phase1_curriculum import ( - build_gaila_phase1_attribute_curriculum, - build_gaila_phase1_object_curriculum, - build_gaila_phase1_relation_curriculum, - build_gaila_phase1_verb_curriculum, - build_gaila_phase_1_curriculum, - build_gaila_plurals_curriculum, -) + from adam.curriculum.phase2_curriculum import ( build_functionally_defined_objects_curriculum, build_gaila_m13_curriculum, @@ -25,7 +17,6 @@ from adam.curriculum.verbs_with_dynamic_prepositions_curriculum import ( make_verb_with_dynamic_prepositions_curriculum, ) -from adam.experiment import Experiment, execute_experiment from adam.experiment.experiment_utils import ( build_debug_curriculum_test, build_debug_curriculum_train, @@ -35,27 +26,20 @@ build_m6_prepositions_curriculum, build_pursuit_curriculum, ) -from adam.experiment.observer import CandidateAccuracyObserver, LearningProgressHtmlLogger from adam.language.dependency import LinearizedDependencyTree from adam.language.language_generator import LanguageGenerator from adam.language.language_utils import phase2_language_generator from adam.language_specific.english import ENGLISH_DETERMINERS -from adam.learner import TopLevelLanguageLearner from adam.learner.attributes import SubsetAttributeLearner, SubsetAttributeLearnerNew from adam.learner.integrated_learner import IntegratedTemplateLearner from adam.learner.language_mode import LanguageMode -from adam.learner.relations import SubsetRelationLearnerNew -from adam.learner.verbs import SubsetVerbLearner, SubsetVerbLearnerNew -from adam.ontology.phase2_ontology import GAILA_PHASE_2_ONTOLOGY from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import ( GAILA_PHASE_1_PERCEPTION_GENERATOR, ) -from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation -from vistautils.parameters import Parameters -from vistautils.parameters_only_entrypoint import parameters_only_entry_point from adam.curriculum.m6_curriculum import make_m6_curriculum from adam.curriculum.phase1_curriculum import ( + build_gaila_plurals_curriculum, build_gaila_phase1_object_curriculum, build_gaila_phase1_attribute_curriculum, build_gaila_phase1_relation_curriculum, diff --git a/adam/perception/perception_graph.py b/adam/perception/perception_graph.py index 475721233..793f8e26f 100644 --- a/adam/perception/perception_graph.py +++ b/adam/perception/perception_graph.py @@ -358,7 +358,7 @@ def from_dynamic_perceptual_representation( def add_temporal_scopes_to_edges( digraph: DiGraph, temporal_scopes: Union[TemporalScope, Iterable[TemporalScope]] ) -> DiGraph: - """ + r""" Modifies the given digraph in place, applying the given `TemporalScope`\ s to all edges. This new graph will be dynamic. diff --git a/tests/learner/__init__.py b/tests/learner/__init__.py index 46a690a8a..e075f70d5 100644 --- a/tests/learner/__init__.py +++ b/tests/learner/__init__.py @@ -2,7 +2,6 @@ from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import ( GAILA_PHASE_1_PERCEPTION_GENERATOR, ) -from immutablecollections import immutabledict from adam.language_specific.english import ENGLISH_DETERMINERS from adam.learner.language_mode import LanguageMode from adam.learner.object_recognizer import ObjectRecognizer From e8cb99b32fc303a261e4afc130d6207868943b52 Mon Sep 17 00:00:00 2001 From: paynesa Date: Mon, 27 Jul 2020 16:15:25 -0400 Subject: [PATCH 10/11] add determiners back to pass some more existing unit tests --- adam/learner/surface_templates.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/adam/learner/surface_templates.py b/adam/learner/surface_templates.py index 9d0de3f90..93931fb79 100644 --- a/adam/learner/surface_templates.py +++ b/adam/learner/surface_templates.py @@ -6,8 +6,7 @@ from more_itertools import quantify from adam.language import TokenSequenceLinguisticDescription - -# from adam.language_specific.english import ENGLISH_MASS_NOUNS +from adam.language_specific.english import ENGLISH_MASS_NOUNS from adam.learner.language_mode import LanguageMode from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs @@ -53,20 +52,20 @@ def instantiate( for element in self.elements: if isinstance(element, SyntaxSemanticsVariable): filler_words = template_variable_to_filler[element] - # # Ground is a specific thing so we special case this to be assigned - # if filler_words[0] == "ground": - # output_tokens.append("the") - # # English-specific hack to deal with us not understanding determiners: - # # https://github.com/isi-vista/adam/issues/498 - # # The "is lower" check is a hack to block adding a determiner to proper names. - # elif ( - # self._language_mode == LanguageMode.ENGLISH - # and element in self._determiner_prefix_slots - # and len(filler_words) == 1 - # and filler_words[0][0].islower() - # and filler_words[0] not in ENGLISH_MASS_NOUNS - # ): - # output_tokens.append("a") + # Ground is a specific thing so we special case this to be assigned + if filler_words[0] == "ground": + output_tokens.append("the") + # English-specific hack to deal with us not understanding determiners: + # https://github.com/isi-vista/adam/issues/498 + # The "is lower" check is a hack to block adding a determiner to proper names. + elif ( + self._language_mode == LanguageMode.ENGLISH + and element in self._determiner_prefix_slots + and len(filler_words) == 1 + and filler_words[0][0].islower() + and filler_words[0] not in ENGLISH_MASS_NOUNS + ): + output_tokens.append("a") output_tokens.extend(filler_words) else: # element must be a single token str due to object validity checks. From 8e2a196e637aae29daa085b87382b55171554441 Mon Sep 17 00:00:00 2001 From: paynesa Date: Mon, 27 Jul 2020 16:37:45 -0400 Subject: [PATCH 11/11] restore Ryan's determiner status --- adam/learner/surface_templates.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/adam/learner/surface_templates.py b/adam/learner/surface_templates.py index 93931fb79..2230e0ec4 100644 --- a/adam/learner/surface_templates.py +++ b/adam/learner/surface_templates.py @@ -6,7 +6,8 @@ from more_itertools import quantify from adam.language import TokenSequenceLinguisticDescription -from adam.language_specific.english import ENGLISH_MASS_NOUNS + +# from adam.language_specific.english import ENGLISH_MASS_NOUNS from adam.learner.language_mode import LanguageMode from adam.semantics import ObjectSemanticNode, SyntaxSemanticsVariable from attr import attrib, attrs @@ -53,19 +54,19 @@ def instantiate( if isinstance(element, SyntaxSemanticsVariable): filler_words = template_variable_to_filler[element] # Ground is a specific thing so we special case this to be assigned - if filler_words[0] == "ground": - output_tokens.append("the") + # if filler_words[0] == "ground": + # output_tokens.append("the") # English-specific hack to deal with us not understanding determiners: # https://github.com/isi-vista/adam/issues/498 # The "is lower" check is a hack to block adding a determiner to proper names. - elif ( - self._language_mode == LanguageMode.ENGLISH - and element in self._determiner_prefix_slots - and len(filler_words) == 1 - and filler_words[0][0].islower() - and filler_words[0] not in ENGLISH_MASS_NOUNS - ): - output_tokens.append("a") + # elif ( + # self._language_mode == LanguageMode.ENGLISH + # and element in self._determiner_prefix_slots + # and len(filler_words) == 1 + # and filler_words[0][0].islower() + # and filler_words[0] not in ENGLISH_MASS_NOUNS + # ): + # output_tokens.append("a") output_tokens.extend(filler_words) else: # element must be a single token str due to object validity checks.