Example #1
0
    def _tree_builder(self, to_expand):
        """
        Recursive helper method to build a SymbolTree.  Fills in
        the children of to_expand by all possible model
        substitutions.

        Args:
            to_expand: (TreeElement) element that will be expanded

        Returns:
            None
        """
        # Get set of symbols that no longer need to be replaced and
        # symbols that are candidates for replacement.
        replaced_symbols = set()  # set of all symbols already replaced.
        # equal to all parents' minus expand's symbols.
        parent = to_expand.parent
        while parent is not None:
            replaced_symbols.update(parent.inputs)
            parent = parent.parent
        replaced_symbols -= to_expand.inputs
        candidate_symbols = to_expand.inputs - replaced_symbols

        # Attempt to replace candidate_symbols
        # Replace them with inputs to models that output the candidate_symbols.
        # Store replacements.
        outputs = []
        prev = defaultdict(list)
        # TODO: this also might be too complicated, marking for refactor
        for symbol in candidate_symbols:
            c_models = self._output_to_model[symbol]
            for model in c_models:
                for input_set, output_set in zip(model.input_sets,
                                                 model.output_sets):
                    can_continue = True
                    for input_symbol in input_set:
                        if input_symbol in replaced_symbols:
                            can_continue = False
                            break
                    if not can_continue:
                        continue
                    input_set = input_set | model.constraint_properties
                    new_types = (to_expand.inputs - output_set)
                    new_types.update(input_set)
                    new_types = {self._symbol_types[x] for x in new_types}
                    if new_types in prev[model]:
                        continue
                    prev[model].append(new_types)
                    new_element = TreeElement(model, new_types, to_expand,
                                              None)
                    self._tree_builder(new_element)
                    outputs.append(new_element)

        # Add outputs to children and fill in their elements.
        to_expand.children = outputs
Example #2
0
    def required_inputs_for_property(self, property):
        """
        Determines all potential paths leading to a given symbol
        object. Answers the question: What sets of properties are
        required to calculate this given property?

        Paths are represented as a series of models and required
        input Symbol objects. Paths can be searched to determine
        specifically how to get from one property to another.

        Warning: Method indicates sets of Symbol objects required
            to calculate the property.  It does not indicate how
            many of each Symbol is required. It does not guarantee
            that supplying Quantities of these types will result
            in a new Symbol output as conditions / assumptions may
            not be met.

        Returns:
            propnet.core.utils.SymbolTree
        """
        head = TreeElement(None, {property}, None, None)
        self._tree_builder(head)
        return SymbolTree(head)