コード例 #1
0
ファイル: text_grammar.py プロジェクト: ronentk/TextLabs
    def __init__(self,
                 options: Union[GrammarOptions, Mapping[str, Any]] = {},
                 rng: Optional[RandomState] = None):
        """
        Arguments:
            options:
                For customizing text generation process (see
                :py:class:`tw_textlabs.generator.GrammarOptions <tw_textlabs.generator.text_grammar.GrammarOptions>`
                for the list of available options).
            rng:
                Random generator used for sampling tag expansions.
        """
        self.options = GrammarOptions(options)
        self.grammar = OrderedDict()
        self.rng = g_rng.next() if rng is None else rng
        self.allowed_variables_numbering = self.options.allowed_variables_numbering
        self.unique_expansion = self.options.unique_expansion
        self.all_expansions = defaultdict(list)

        # The current used symbols
        self.overflow_dict = OrderedDict()
        self.used_names = set(self.options.names_to_exclude)

        # Load the grammar associated to the provided theme.
        self.theme = self.options.theme

        # Load the object names file
        files = glob.glob(
            pjoin(KnowledgeBase.default().text_grammars_path,
                  glob.escape(self.theme) + "_*.twg"))
        for filename in files:
            self._parse(filename)

        for k, v in self.grammar.items():
            self.grammar[k] = tuple(v)
コード例 #2
0
ファイル: quest_generator.py プロジェクト: ronentk/TextLabs
    def nb_mat_ccs(self, node: _Node) -> int:
        """ 
        Return number of connected components in graph spanning base materials.
        Materials are connnected iff they're merged. 
        """

        # get all materials and descendants in game
        all_mats = [
            self.start_state.variables_of_type(t)
            for t in KnowledgeBase.default().types.descendants('m') + ['m']
        ]
        all_mats = set([item for items in all_mats for item in items])

        # get all 'component' propositions to link between the materials
        component_props = [
            p for p in node.state.facts if p.name == "component"
        ]

        # build the graph and return number of ccs (only count ccs with any base materials)
        G = nx.Graph()
        G.add_nodes_from([m for m in all_mats])
        edges = [(p.arguments[0], p.arguments[1]) for p in component_props]
        G.add_edges_from(edges)
        ccs = [
            cc for cc in nx.connected_components(G)
            if len(cc.intersection(self.base_materials)) > 0
        ]
        return len(ccs)
コード例 #3
0
def gen_commands_from_actions(actions: Iterable[Action], kb: Optional[KnowledgeBase] = None, 
    compact_actions=False) -> List[str]:
    kb = kb or KnowledgeBase.default()
    def _get_name_mapping(action, compact_actions=False):
        mapping = kb.rules[action.name].match(action)
        if not compact_actions:
            return {ph.name: var.name for ph, var in mapping.items()}
        else:
            return {ph.name: var for ph, var in mapping.items()}

    commands = []
    for action in actions:
        command = "None"
        if action is not None:
            command = kb.inform7_commands[action.name]
            short_cmd_name = command.split(' ')[0] # assuming action name is first word in command sentence
            name_mapping = _get_name_mapping(action, compact_actions)
            if not compact_actions:
                command = command.format(**name_mapping)
            else:
                cmd_args = [name_mapping[w.strip('{}')] for w in command.split(' ') if (('{' in w) and ('}' in w))]
                command = CompactAction(name=short_cmd_name, vars=cmd_args)

        commands.append(command)

    return commands
コード例 #4
0
ファイル: process_graph.py プロジェクト: ronentk/TextLabs
 def __str__(self):
     if KnowledgeBase.default().types.is_descendant_of(
             self.var.type, ['toe']):
         return type_map[self.var.type]
     elif self.g > 0:
         return '%s@g%d' % (self.var.name, self.g)
     else:
         return '%s' % (self.var.name)
コード例 #5
0
ファイル: process_graph.py プロジェクト: ronentk/TextLabs
 def get_source_op(self, node: EntityNode) -> EntityNode:
     assert (KnowledgeBase.default().types.is_descendant_of(
         node.var.type, ['m', 'sa']))
     # return first operation node producing target node
     for n in self.ent_states_map[node.var]:
         for s, t in self.G.in_edges(n):
             if s.var.type == 'tlq_op':
                 return s
     return None
コード例 #6
0
def test_quest_winning_condition():
    g_rng.set_seed(2018)
    map_ = make_small_map(n_rooms=5, possible_door_states=["open"])
    world = World.from_map(map_)

    def _rule_to_skip(rule):
        # Examine, look and inventory shouldn't be used for chaining.
        if rule.name.startswith("look"):
            return True

        if rule.name.startswith("inventory"):
            return True

        if rule.name.startswith("examine"):
            return True

        return False

    for rule in KnowledgeBase.default().rules.values():
        if _rule_to_skip(rule):
            continue

        options = ChainingOptions()
        options.backward = True
        options.max_depth = 1
        options.create_variables = True
        options.rules_per_depth = [[rule]]
        options.restricted_types = {"r"}
        chain = sample_quest(world.state, options)
        assert len(chain.actions) > 0, rule.name
        event = Event(chain.actions)
        quest = Quest(win_events=[event])

        # Set the initial state required for the quest.
        tmp_world = World.from_facts(chain.initial_state.facts)
        game = make_game_with(tmp_world, [quest], make_grammar({}))

        if tmp_world.player_room is None:
            # Randomly place the player in the world since
            # the action doesn't care about where the player is.
            tmp_world.set_player_room()

        game_name = "test_quest_winning_condition_" + rule.name.replace(
            "/", "_")
        with make_temp_directory(prefix=game_name) as tmpdir:
            game_file = _compile_game(game, path=tmpdir)

            env = tw_textlabs.start(game_file)
            env.reset()
            game_state, _, done = env.step("look")
            assert not done
            assert not game_state.has_won

            game_state, _, done = env.step(event.commands[0])
            assert done
            assert game_state.has_won
コード例 #7
0
ファイル: test_chaining.py プロジェクト: ronentk/TextLabs
def test_parallel_quests():
    logic = GameLogic.parse("""
        type foo {
            rules {
                do_a :: not_a(foo) & $not_c(foo) -> a(foo);
                do_b :: not_b(foo) & $not_c(foo) -> b(foo);
                do_c :: $a(foo) & $b(foo) & not_c(foo) -> c(foo);
            }

            constraints {
                a_or_not_a :: a(foo) & not_a(foo) -> fail();
                b_or_not_b :: b(foo) & not_b(foo) -> fail();
                c_or_not_c :: c(foo) & not_c(foo) -> fail();
            }
        }
    """)
    kb = KnowledgeBase(logic, "")

    state = State([
        Proposition.parse("a(foo)"),
        Proposition.parse("b(foo)"),
        Proposition.parse("c(foo)"),
    ])

    options = ChainingOptions()
    options.backward = True
    options.kb = kb

    options.max_depth = 3
    options.max_breadth = 1
    chains = list(get_chains(state, options))
    assert len(chains) == 2

    options.max_breadth = 2
    chains = list(get_chains(state, options))
    assert len(chains) == 3

    options.min_breadth = 2
    chains = list(get_chains(state, options))
    assert len(chains) == 1
    assert len(chains[0].actions) == 3
    assert chains[0].nodes[0].depth == 2
    assert chains[0].nodes[0].breadth == 2
    assert chains[0].nodes[0].parent == chains[0].nodes[2]
    assert chains[0].nodes[1].depth == 2
    assert chains[0].nodes[1].breadth == 1
    assert chains[0].nodes[1].parent == chains[0].nodes[2]
    assert chains[0].nodes[2].depth == 1
    assert chains[0].nodes[2].breadth == 1
    assert chains[0].nodes[2].parent == None

    options.min_breadth = 1
    options.create_variables = True
    chains = list(get_chains(State(), options))
    assert len(chains) == 5
コード例 #8
0
ファイル: test_game.py プロジェクト: ronentk/TextLabs
    def test_generating_quests(self):
        g_rng.set_seed(2018)
        map_ = make_small_map(n_rooms=5, possible_door_states=["open"])
        world = World.from_map(map_)

        def _rule_to_skip(rule):
            # Examine, look and inventory shouldn't be used for chaining.
            if rule.name.startswith("look"):
                return True

            if rule.name.startswith("inventory"):
                return True

            if rule.name.startswith("examine"):
                return True

            return False

        for max_depth in range(1, 3):
            for rule in KnowledgeBase.default().rules.values():
                if _rule_to_skip(rule):
                    continue

                options = ChainingOptions()
                options.backward = True
                options.max_depth = max_depth
                options.create_variables = True
                options.rules_per_depth = [[rule]]
                options.restricted_types = {"r"}
                chain = sample_quest(world.state, options)

                # Build the quest by providing the actions.
                actions = chain.actions
                assert len(actions) == max_depth, rule.name
                quest = Quest(win_events=[Event(actions)])
                tmp_world = World.from_facts(chain.initial_state.facts)

                state = tmp_world.state
                for action in actions:
                    assert not quest.is_winning(state)
                    state.apply(action)

                assert quest.is_winning(state)

                # Build the quest by only providing the winning conditions.
                quest = Quest(
                    win_events=[Event(conditions=actions[-1].postconditions)])
                tmp_world = World.from_facts(chain.initial_state.facts)

                state = tmp_world.state
                for action in actions:
                    assert not quest.is_winning(state)
                    state.apply(action)

                assert quest.is_winning(state)
コード例 #9
0
ファイル: text_generation.py プロジェクト: ronentk/TextLabs
def is_seq(chain, game_infos):
    """ Check if we have a theoretical chain in actions. """
    seq = MergeAction()

    room_placeholder = Placeholder('r')

    action_mapping = KnowledgeBase.default().rules[chain[0].name].match(
        chain[0])
    for ph, var in action_mapping.items():
        if ph.type not in ["P", "I"]:
            seq.mapping[ph] = var
            seq.const.append(var)

    for c in chain:
        c_action_mapping = KnowledgeBase.default().rules[c.name].match(c)

        # Update our action name
        seq.name += "_{}".format(c.name.split("/")[0])

        # We break a chain if we move rooms
        if c_action_mapping[room_placeholder] != seq.mapping[room_placeholder]:
            return False, seq

        # Update the mapping
        for ph, var in c_action_mapping.items():
            if ph.type not in ["P", "I"]:
                if ph in seq.mapping and var != seq.mapping[ph]:
                    return False, seq
                else:
                    seq.mapping[ph] = var

        # Remove any objects that we no longer use
        tmp = list(filter(lambda x: x in c_action_mapping.values(), seq.const))

        # If all original objects are gone, the seq is broken
        if len(tmp) == 0:
            return False, seq

        # Update our obj list
        seq.const = tmp

    return True, seq
コード例 #10
0
ファイル: process_graph.py プロジェクト: ronentk/TextLabs
def node_to_color(node: EntityNode) -> str:
    """ Return node's color string as per the entity type. """
    color = 'gray'  # default
    for node_type in color_map.keys():
        if node.var.type == GENERATOR_DUMMY_TYPE:  # handle separately since not in type tree
            return color
        elif KnowledgeBase.default().types.is_descendant_of(
                node.var.type, node_type):
            color = color_map[node_type]

    return color
コード例 #11
0
ファイル: process_graph.py プロジェクト: ronentk/TextLabs
 def add_new_state(self, e: Variable):
     """ 
     Add new state for a given entity variable (except Operation entities). 
     This creates a new EntityNode with g increased by 1. 
     """
     if KnowledgeBase.default().types.is_descendant_of(e.type, ['op']):
         return self.ent_states_map[e]
     else:
         new_state_node = EntityNode(var=e, g=(self.curr_state(e).g + 1))
         self.ent_states_map[e].append(new_state_node)
         return new_state_node
コード例 #12
0
ファイル: maker.py プロジェクト: ronentk/TextLabs
    def add(self,
            *entities: List["WorldEntity"],
            input_slot: str = 'a') -> None:
        """ Add children to this entity. """
        if KnowledgeBase.default().types.is_descendant_of(self.type, "r"):
            name = "at"
        # adding a child entity to an operation means setting one of its input slots
        elif KnowledgeBase.default().types.is_descendant_of(self.type, ["op"]):
            assert input_slot in ['a', 'b']
            name = "pot_multi_{}".format(input_slot)
        elif KnowledgeBase.default().types.is_descendant_of(
                self.type, ["c", "I"]):
            name = "in"
        elif KnowledgeBase.default().types.is_descendant_of(self.type, "s"):
            name = "on"
        else:
            raise ValueError("Unexpected type {}".format(self.type))

        for entity in entities:
            self.add_fact(name, entity, self)
            self.content.append(entity)
コード例 #13
0
ファイル: lab_game_maker.py プロジェクト: ronentk/TextLabs
 def __init__(self, surface_generator: SurfaceGenerator) -> None:
     """
     Creates an empty world, with a player and an empty inventory.
     """
     self._entities = {}
     self.quests = []
     self.rooms = []
     self.paths = []
     self._types_counts = KnowledgeBase.default().types.count(State())
     self.player = self.new(type='P')
     self.inventory = self.new(type='I')
     self.sg = surface_generator
     self._game = None
     self._quests_str = []
     self._distractors_facts = []
     # define global op types
     self.globals = {}
     for t in KnowledgeBase.default().types.descendants('toe'):
         op_type = self.new(type=t)
         op_type.add_property('initialized')
         self.globals[t] = op_type
コード例 #14
0
ファイル: test_chaining.py プロジェクト: ronentk/TextLabs
def test_chaining():
    # The following test depends on the available rules,
    # so instead of depending on what is in rules.txt,
    # we define the allowed_rules to used.
    allowed_rules = KnowledgeBase.default().rules.get_matching("take/.*")
    allowed_rules += KnowledgeBase.default().rules.get_matching("go.*")
    allowed_rules += KnowledgeBase.default().rules.get_matching("insert.*", "put.*")
    allowed_rules += KnowledgeBase.default().rules.get_matching("open.*", "close.*")
    allowed_rules += KnowledgeBase.default().rules.get_matching("lock.*", "unlock.*")
    allowed_rules += KnowledgeBase.default().rules.get_matching("eat.*")

    class Options(ChainingOptions):
        def get_rules(self, depth):
            return allowed_rules

    options = Options()
    options.max_depth = 5

    # No possible action since the wooden door is locked and
    # the player doesn't have the key.
    state = build_state(locked_door=True)
    chains = list(get_chains(state, options))
    assert len(chains) == 0

    # The door is now closed instead of locked.
    state = build_state(locked_door=False)
    chains = list(get_chains(state, options))
    assert len(chains) == 5

    # With more depth.
    state = build_state(locked_door=False)
    options.max_depth = 20
    chains = list(get_chains(state, options))
    assert len(chains) == 9
コード例 #15
0
ファイル: test_grammar.py プロジェクト: ronentk/TextLabs
def maybe_instantiate_variables(rule, mapping, state, max_types_counts=None):
    types_counts = KnowledgeBase.default().types.count(state)

    # Instantiate variables if needed
    try:
        for ph in rule.placeholders:
            if mapping.get(ph) is None:
                name = get_new(ph.type, types_counts, max_types_counts)
                mapping[ph] = Variable(name, ph.type)
    except NotEnoughNounsError:
        return None

    return rule.instantiate(mapping)
コード例 #16
0
ファイル: chaining.py プロジェクト: ronentk/TextLabs
 def __init__(self):
     self.backward = False
     self.min_depth = 1
     self.max_depth = 1
     self.min_breadth = 1
     self.max_breadth = 1
     self.subquests = False
     self.independent_chains = False
     self.create_variables = False
     self.kb = KnowledgeBase.default()
     self.rng = None
     self.rules_per_depth = []
     self.restricted_types = frozenset()
コード例 #17
0
ファイル: test_constraints.py プロジェクト: ronentk/TextLabs
def check_state(state):
    fail = Proposition("fail", [])
    debug = Proposition("debug", [])

    constraints = state.all_applicable_actions(
        KnowledgeBase.default().constraints.values())
    for constraint in constraints:
        if state.is_applicable(constraint):
            # Optimistically delay copying the state
            copy = state.copy()
            copy.apply(constraint)

            if copy.is_fact(fail):
                return False

    return True
コード例 #18
0
ファイル: test_game.py プロジェクト: ronentk/TextLabs
    def test_untriggerable(self):
        event = EventProgression(self.event, KnowledgeBase.default())

        state = self.game.world.state.copy()
        for action in self.eating_carrot.actions:
            assert event.triggering_policy != ()
            assert not event.done
            assert not event.triggered
            assert not event.untriggerable
            state.apply(action)
            event.update(action=action, state=state)

        assert event.triggering_policy == ()
        assert event.done
        assert not event.triggered
        assert event.untriggerable
コード例 #19
0
ファイル: maker.py プロジェクト: ronentk/TextLabs
 def __init__(self) -> None:
     """
     Creates an empty world, with a player and an empty inventory.
     """
     self._entities = {}
     self.quests = []
     self.rooms = []
     self.paths = []
     self.globals = {
     }  # global variables hack for entities that must be accessible from anywhere
     self._types_counts = KnowledgeBase.default().types.count(State())
     self.player = self.new(type='P')
     self.inventory = self.new(type='I')
     self.grammar = tw_textlabs.generator.make_grammar()
     self._game = None
     self._distractors_facts = []
コード例 #20
0
ファイル: maker.py プロジェクト: ronentk/TextLabs
def get_failing_constraints(state):
    fail = Proposition("fail", [])

    failed_constraints = []
    constraints = state.all_applicable_actions(
        KnowledgeBase.default().constraints.values())
    for constraint in constraints:
        if state.is_applicable(constraint):
            # Optimistically delay copying the state
            copy = state.copy()
            copy.apply(constraint)

            if copy.is_fact(fail):
                failed_constraints.append(constraint)

    return failed_constraints
コード例 #21
0
 def __init__(self, world: World, grammar: Optional[Grammar] = None,
              quests: Iterable[Quest] = (),
              kb: Optional[KnowledgeBase] = None) -> None:
     """
     Args:
         world: The world to use for the game.
         quests: The quests to be done in the game.
         grammar: The grammar to control the text generation.
     """
     self.world = world
     self.quests = tuple(quests)
     self.metadata = {}
     self._objective = None
     self._infos = self._build_infos()
     self.kb = kb or KnowledgeBase.default()
     self.extras = {}
     self._main_quest = None
コード例 #22
0
ファイル: text_generation.py プロジェクト: ronentk/TextLabs
def assign_description_to_object(obj, grammar, game_infos):
    """
    Assign a descripton to an object.
    """
    if game_infos[obj.id].desc is not None:
        return  # Already have a description.

    # Update the object description
    desc_tag = "#({})_desc#".format(obj.type)
    game_infos[obj.id].desc = ""
    if grammar.has_tag(desc_tag):
        game_infos[obj.id].desc = expand_clean_replace(desc_tag, grammar, obj,
                                                       game_infos)

    # If we have an openable object, append an additional description
    if KnowledgeBase.default().types.is_descendant_of(obj.type, ["c", "d"]):
        game_infos[obj.id].desc += grammar.expand(" #openable_desc#")
コード例 #23
0
ファイル: test_game.py プロジェクト: ronentk/TextLabs
    def test_triggering_policy(self):
        event = EventProgression(self.event, KnowledgeBase.default())

        state = self.game.world.state.copy()
        expected_actions = self.event.actions
        for i, action in enumerate(expected_actions):
            assert event.triggering_policy == expected_actions[i:]
            assert not event.done
            assert not event.triggered
            assert not event.untriggerable
            state.apply(action)
            event.update(action=action, state=state)

        assert event.triggering_policy == ()
        assert event.done
        assert event.triggered
        assert not event.untriggerable
コード例 #24
0
    def assign_actions_to_ops(self, pg: ProcessGraph) -> ProcessGraph:
        """
        For each operation node, replace incoming "assign" edges with the action name.
        """
        op_nodes = [n for n in pg.G.nodes() if n.var.type == 'tlq_op']
        for op in op_nodes:
            if self.surface_gen_options.preset_ops:
                op_type = self.surface_gen_options.op_type_map[op.var.name]
            else:
                op_type = pg.get_op_type(op)
            action_with_id = '{} ({})'.format(templatize_text(op_type),
                                              templatize_text(op.var.name))
            pg.rename_edges(op, 'op_ia_assign', action_with_id)

        dsc_nodes = [n for n in pg.G.nodes() if \
                     KnowledgeBase.default().types.is_descendant_of(n.var.type, 'dsc')]
        for node in dsc_nodes:
            pg.rename_edges(node, 'dlink', 'describe', incoming=False)
コード例 #25
0
 def get_serial_actions(self,
                        pg: ProcessGraph) -> Mapping[str, CommandSurface]:
     """
     Get all serial actions in action graph. Specifically, all chains of at
     least 2 consecutive actions on a single material. This is to allow 
     merging of multiple identical commands to one. For example, this would
     change the sequence "grind X. melt X." to "grind and melt X"
     
     Parameters
     ----------
     pg: Process Graph representing a material synthesis procedure.
     
     Returns
     -------
     mapping:
         mapping between the string ids of the serial actions and their
         corresponding CommandSurface.
     """
     serial_act_to_surface_map = {}
     for var, state_nodes in pg.ent_states_map.items():
         if KnowledgeBase.default().types.is_descendant_of(var.type, 'm'):
             if len(state_nodes) > 2:  # >2 state changes, we can merge them
                 ap = pg.get_actions_path(state_nodes[0], state_nodes[-1])
                 actions = [
                     ae.action for ae in ap if ae.action not in
                     SKIP_ACTIONS_BY_MODE[self.difficulty_mode]
                 ]
                 if len(actions) > 1:
                     cmd = '%s %s' % (list_to_contents_str(actions),
                                      templatize_text(var.name))
                 elif len(actions) == 1:
                     cmd = '%s %s' % (templatize_text(actions[0]), var.name)
                 else:
                     cmd = IGNORE_CMD
                 # if there are commands with an identical surface
                 # representation, differentiate between them using cnt
                 cnt = get_cmd_count(
                     cmd, list(serial_act_to_surface_map.values()))
                 for ae in ap:
                     serial_act_to_surface_map[str(ae)] = CommandSurface(
                         cmd, cnt)
     return serial_act_to_surface_map
コード例 #26
0
    def deserialize(cls, data: Mapping) -> "Game":
        """ Creates a `Game` from serialized data.

        Args:
            data: Serialized data with the needed information to build a
                  `Game` object.
        """
        world = World.deserialize(data["world"])
        game = cls(world)
#        game.grammar = Grammar(data["grammar"])
        game.quests = tuple([Quest.deserialize(d) for d in data["quests"]])
        game._infos = {k: EntityInfo.deserialize(v) for k, v in data["infos"]}
        game.kb = KnowledgeBase.deserialize(data["KB"])
        game.metadata = data.get("metadata", {})
        game._objective = data.get("objective", None)
        game.extras = data.get("extras", {})
        if "main_quest" in data:
            game._main_quest = Quest.deserialize(data["main_quest"])

        return game
コード例 #27
0
ファイル: text_generation.py プロジェクト: ronentk/TextLabs
def expand_clean_replace(symbol, grammar, obj, game_infos):
    """ Return a cleaned/keyword replaced symbol. """
    obj_infos = game_infos[obj.id]
    phrase = grammar.expand(symbol)
    phrase = phrase.replace("(obj)", obj_infos.id)
    phrase = phrase.replace("(name)", obj_infos.name)
    phrase = phrase.replace(
        "(name-n)",
        obj_infos.noun if obj_infos.adj is not None else obj_infos.name)
    phrase = phrase.replace(
        "(name-adj)", obj_infos.adj
        if obj_infos.adj is not None else grammar.expand("#ordinary_adj#"))
    if obj.type != "":
        phrase = phrase.replace(
            "(name-t)",
            KnowledgeBase.default().types.get_description(obj.type))
    else:
        assert False, "Does this even happen?"

    return fix_determinant(phrase)
コード例 #28
0
    def _process_objects(self) -> None:
        for fact in self.facts:
            if KnowledgeBase.default().types.is_descendant_of(
                    fact.arguments[0].type, 'r'):
                continue  # Skip room facts.

            obj = self._get_entity(fact.arguments[0])
            obj.add_related_fact(fact)

            if fact.name == "match":
                other_obj = self._get_entity(fact.arguments[1])
                obj.matching_entity_id = fact.arguments[1].name
                other_obj.matching_entity_id = fact.arguments[0].name

            if fact.name in [
                    "in", "on", "at", "potential", "pot_multi_a", "pot_multi_b"
            ]:
                holder = self._get_entity(fact.arguments[1])
                holder.content.append(obj)

                if fact.arguments[0].type == "P":
                    self._player_room = holder
コード例 #29
0
    def __init__(self, event: Event, kb: KnowledgeBase) -> None:
        """
        Args:
            quest: The quest to keep track of its completion.
        """
        self._kb = kb or KnowledgeBase.default()
        self.event = event
        self._triggered = False
        self._untriggerable = False
        self._policy = ()

        # Build a tree representation of the quest.
        self._tree = ActionDependencyTree(kb=self._kb,
                                          element_type=ActionDependencyTreeElement)

        if len(event.actions) > 0:
            self._tree.push(event.condition)

            for action in event.actions[::-1]:
                self._tree.push(action)

            self._policy = event.actions + (event.condition,)
コード例 #30
0
ファイル: quest_generator.py プロジェクト: ronentk/TextLabs
    def __init__(self, **kwargs):
        super(LabQuestGenerator, self).__init__(**kwargs)
        #        self.max_nb_op_use = 2
        self.base_materials = self.get_base_materials()
        self.states = {}
        self.descs_per_ent = None
        # types and actions we want to ignore (for example to set later independently, like descriptors)
        self.ignore_act_list = ['locate', 'drop']
        self.ignore_types_list = KnowledgeBase.default().types.descendants(
            'dsc') + ['dsc']
        self.ignore_sigs = [Signature('in', ['tlq_op', 'I'])]
        self.q.set_scorer(self.lab_quest_scorer)

        # validity checks for every search state
        self.node_checks = {
            'check_depth': self.check_depth,
            'check_node_state': self.check_node_state,
            # 'ignore_types': self.check_ignore_type,
            'ignore_acts': self.check_ignore_act,
            'ignore_sigs': self.check_ignore_sigs
        }

        # goal node checks
        self.goal_check_fns = {
            'all_ops_used': self.all_ops_used,
            'all_mats_merged': self.all_mats_merged,
            'end_after_op': self.is_after_op_state,
        }

        # feature extractor functions for a given state w/ their weight
        self.feature_extractor_fns = {
            'is_new_state':
            (self.check_existing_state, 2),  # 1 if state is new, 0 if not
            'nb_ops_used': (self.nb_ops_used, 1),  # number of ops already used
            'nb_mat_ccs':
            (self.nb_mat_ccs, -1
             )  # 1 if all precursor/solvent materials used in synthesis route
        }