Exemplo n.º 1
0
    def test_nan_checking(self):
        A = Symbol('a', ['A'], ['A'], units='dimensionless', shape=1)
        B = Symbol('b', ['B'], ['B'], units='dimensionless', shape=[2, 2])
        C = Symbol('c', ['C'], ['C'], units='dimensionless', shape=1)
        D = Symbol('d', ['D'], ['D'], units='dimensionless', shape=[2, 2])
        E = Symbol('e', ['E'], ['E'], category='object', shape=1)

        scalar_quantity = Quantity(A, float('nan'))
        non_scalar_quantity = Quantity(
            B, [[1.0, float('nan')], [float('nan'), 1.0]])
        complex_scalar_quantity = Quantity(C, complex('nan+nanj'))
        complex_non_scalar_quantity = Quantity(
            D, [[complex(1.0), complex('nanj')],
                [complex('nan'), complex(1.0)]])

        self.assertTrue(scalar_quantity.contains_nan_value())
        self.assertTrue(non_scalar_quantity.contains_nan_value())
        self.assertTrue(complex_scalar_quantity.contains_nan_value())
        self.assertTrue(complex_non_scalar_quantity.contains_nan_value())

        scalar_quantity = Quantity(A, 1.0)
        non_scalar_quantity = Quantity(B, [[1.0, 2.0], [2.0, 1.0]])
        complex_scalar_quantity = Quantity(C, complex('1+1j'))
        complex_non_scalar_quantity = Quantity(
            D, [[complex(1.0), complex('5j')], [complex('5'),
                                                complex(1.0)]])

        self.assertFalse(scalar_quantity.contains_nan_value())
        self.assertFalse(non_scalar_quantity.contains_nan_value())
        self.assertFalse(complex_scalar_quantity.contains_nan_value())
        self.assertFalse(complex_non_scalar_quantity.contains_nan_value())

        non_numerical = Quantity(E, 'test')
        self.assertFalse(non_numerical.contains_nan_value())
Exemplo n.º 2
0
    def evaluate(self, symbol_quantity_dict, allow_failure=True):
        """
        Given a set of property_values, performs error checking to see
        if the corresponding input symbol_values represents a valid
        input set based on the self.connections() method. If so, returns
        a dictionary representing the value of plug_in applied to the
        input_symbols. The dictionary contains a "successful" key
        representing if plug_in was successful.

        The key distinction between evaluate and plug_in is properties
        in properties out vs. symbols in symbols out.  In addition,
        evaluate also handles any requisite unit_mapping

        Args:
            symbol_quantity_dict ({property_name: Quantity}): a mapping of
                symbol names to quantities to be substituted
            allow_failure (bool): whether or not to catch
                errors in model evaluation

        Returns:
            dictionary of output properties with associated values
            generated from the input, along with "successful" if the
            substitution succeeds
        """
        # Remap symbols and units if symbol map isn't none
        symbol_quantity_dict = self.map_properties_to_symbols(
            symbol_quantity_dict)

        # TODO: Is it really necessary to strip these?
        # TODO: maybe this only applies to pymodels or things with objects?
        # strip units from input and keep for reassignment
        symbol_value_dict = {}
        for symbol, quantity in symbol_quantity_dict.items():
            # If unit map convert and then scrub units
            if self.unit_map.get(symbol):
                quantity = quantity.to(self.unit_map[symbol])
                symbol_value_dict[symbol] = quantity.magnitude
            # Otherwise use values
            else:
                symbol_value_dict[symbol] = quantity.value
        # Plug in and check constraints
        try:
            out = self.plug_in(symbol_value_dict)
        except Exception as err:
            if allow_failure:
                return {
                    "successful": False,
                    "message": "{} evaluation failed: {}".format(self, err)
                }
            else:
                raise err
        if not self.check_constraints({**symbol_value_dict, **out}):
            return {
                "successful": False,
                "message": "Constraints not satisfied"
            }

        provenance = ProvenanceElement(model=self.name,
                                       inputs=list(
                                           symbol_quantity_dict.values()))
        out = self.map_symbols_to_properties(out)
        for symbol, value in out.items():
            try:
                quantity = Quantity(symbol,
                                    value,
                                    self.unit_map.get(symbol),
                                    provenance=provenance)
            except SymbolConstraintError as err:
                if allow_failure:
                    errmsg = "{} symbol constraint failed: {}".format(
                        self, err)
                    return {"successful": False, "message": errmsg}
                else:
                    raise err

            if quantity.contains_nan_value():
                return {
                    "successful": False,
                    "message": "Evaluation returned invalid values (NaN)"
                }
            out[symbol] = quantity

        out['successful'] = True
        return out