Example #1
0
 def __init__(self, exprs=(), derivatives=(), sleep=0, dsleep=0):
     super(ExecCompWithDerivatives, self).__init__()
     
     ins = set()
     outs = set()
     allvars = set()
     self.exprs = exprs
     self.codes = [compile(expr,'<string>','exec') for expr in exprs]
     self.sleep = sleep
     self.dsleep = dsleep
     
     for expr in exprs:
         lhs,rhs = expr.split('=')
         lhs = lhs.strip()
         lhs = lhs.split(',')
         outs.update(lhs)
         expreval = ExprEvaluator(expr, scope=self)
         allvars.update(expreval.get_referenced_varpaths(copy=False))
     ins = allvars - outs
     
     for var in allvars:
         if '.' not in var:  # if a varname has dots, it's outside of our scope,
                             # so don't add a trait for it
             if var in outs:
                 iotype = 'out'
             else:
                 iotype = 'in'
             self.add(var, Float(0.0, iotype=iotype))
 
     self.deriv_exprs = derivatives
     self.derivative_codes = \
         [compile(expr,'<string>','exec') for expr in derivatives]
     
     self.derivative_names = []
     regex = re.compile('d(.*)_d(.*)')
     for expr in derivatives:
         expreval = ExprEvaluator(expr, scope=self)
         exvars = expreval.get_referenced_varpaths(copy=False)
         
         lhs, _ = expr.split('=')
         lhs = lhs.strip()
         allvars.add(lhs)
         
         # Check for undefined vars the cool way with sets
         if len(exvars-allvars) > 0:
             self.raise_exception('derivative references a variable '
                                  'that is not defined in exprs',
                                  ValueError)
                 
         names = regex.findall(lhs)
         num = names[0][0]
         wrt = names[0][1]
         self.derivatives.declare_first_derivative(num, wrt)
         
         self.derivative_names.append( (lhs, num, wrt) )
Example #2
0
    def test_scope_transform(self):
        exp = ExprEvaluator('myvar+abs(comp.x)*a.a1d[2]', self.top)
        self.assertEqual(
            new_text(exp),
            "scope.get('myvar')+abs(scope.get('comp.x'))*scope.get('a.a1d',[(0,2)])"
        )
        xformed = exp.scope_transform(self.top, self.top.comp)
        self.assertEqual(xformed, 'parent.myvar+abs(x)*parent.a.a1d[2]')

        exp = ExprEvaluator('parent.var+abs(x)*parent.a.a1d[2]', self.top.comp)
        xformed = exp.scope_transform(self.top.comp, self.top)
        self.assertEqual(xformed, 'var+abs(comp.x)*a.a1d[2]')
Example #3
0
    def execute(self):
        """ Run each parameter set. """

        # Prepare parameters and responses.
        exprs = {}
        case_paths = {}
        inputs = []
        values = []
        for path in self.get_parameters():
            if isinstance(path, tuple):
                for target in path:
                    inputs.append(target)
                    if not is_legal_name(target):
                        exprs[target] = ExprEvaluator(target)
                path = path[0]
            else:
                inputs.append(path)
                if not is_legal_name(path):
                    exprs[path] = ExprEvaluator(path)

            path = make_legal_path(path)
            values.append(self.get('case_inputs.' + path))

        for path in self.get_responses():
            if not is_legal_name(path):
                exprs[path] = ExprEvaluator(path)
            case_paths[path] = make_legal_path(path)

        length = len(values[0]) if values else 0
        self.init_responses(length)

        # Run each parameter set.
        for i in range(length):

            # Set inputs.
            for j, path in enumerate(inputs):
                value = values[j][i]
                expr = exprs.get(path)
                self.set_parameter_by_name(path, value)

            # Run workflow.
            self.workflow.run()

            # Get outputs.
            for path in self.get_responses():
                expr = exprs.get(path)
                if expr:
                    value = expr.evaluate(self.parent)
                else:
                    value = self.parent.get(path)
                path = case_paths[path]
                self.set('case_outputs.%s[%d]' % (path, i), value)
Example #4
0
def _split_expr(text):
    """Take an expression string and return varpath, expr"""
    if text.startswith('@') or is_legal_name(text):
        return text, text
    
    expr = ExprEvaluator(text)
    return expr.get_referenced_varpaths().pop(), text
Example #5
0
    def test_reparse_on_scope_change(self):
        self.top.comp.x = 99.5
        self.top.comp.y = -3.14

        ex = ExprEvaluator('comp.x', self.top)
        self.assertEqual(99.5, ex.evaluate())
        self.assertEqual(new_text(ex), "scope.get('comp.x')")

        ex.scope = self.top.a
        try:
            ex.set(0.5)
        except AttributeError as err:
            self.assertEqual(str(err), "a: object has no attribute 'comp.x'")
        else:
            self.fail("AttributeError expected")
        self.assertEqual(new_text(ex), "scope.get('comp.x')")
        self.assertEqual(99.5,
                         ex.evaluate(self.top))  # set scope back to self.top
        self.assertEqual(new_text(ex), "scope.get('comp.x')")

        ex.text = 'comp.y'
        try:
            ex.evaluate(self.top.a)
        except AttributeError as err:
            self.assertEqual(
                str(err), "can't evaluate expression 'comp.y':"
                " a: 'A' object has no attribute 'comp'")
        else:
            self.fail("AttributeError expected")
        ex.scope = self.top
        ex.set(11.1)
        self.assertEqual(11.1, self.top.comp.y)
        self.assertEqual(new_text(ex), "scope.get('comp.y')")
    def _create(self, target, low, high, scaler, adder, start, fd_step,
                key, scope):
        """ Create one Parameter or ArrayParameter. """
        try:
            expreval = ExprEvaluator(target, scope)
        except Exception as err:
            raise err.__class__("Can't add parameter: %s" % err)
        if not expreval.is_valid_assignee():
            raise ValueError("Can't add parameter: '%s' is not a"
                             " valid parameter expression"
                             % expreval.text)
        try:
            val = expreval.evaluate()
        except Exception as err:
            val = None  # Let Parameter code sort out why.

        name = key[0] if isinstance(key, tuple) else key

        if isinstance(val, ndarray):
            return ArrayParameter(target, low=low, high=high,
                                  scaler=scaler, adder=adder,
                                  start=start, fd_step=fd_step,
                                  name=name, scope=scope,
                                  _expreval=expreval, _val=val,
                                  _allowed_types=self._allowed_types)
        else:
            return Parameter(target, low=low, high=high,
                             scaler=scaler, adder=adder,
                             start=start, fd_step=fd_step,
                             name=name, scope=scope,
                             _expreval=expreval, _val=val,
                             _allowed_types=self._allowed_types)
Example #7
0
    def _translate_up(self, text, node):
        """Upscoping"""
        if is_legal_name(text):
            return '.'.join([node, text])

        expr = ExprEvaluator(text)
        varpath = expr.get_referenced_varpaths().pop()
        return transform_expression(text, { varpath: '.'.join([node, varpath]) })
Example #8
0
    def test_eval_gradient_lots_of_vars(self):
        top = set_as_top(Assembly())
        top.add('comp1', B())
        #build expr
        expr = "2*comp1.in1 + 3*comp1.in11"

        exp = ExprEvaluator(expr, top.driver)
        grad = exp.evaluate_gradient(scope=top)

        assert_rel_error(self, grad['comp1.in1'], 2.0, 0.00001)
        assert_rel_error(self, grad['comp1.in11'], 3.0, 0.00001)

        expr = "asin(comp1.in1)"
        exp = ExprEvaluator(expr, top.driver)
        grad = exp.evaluate_gradient(scope=top)

        assert_rel_error(self, grad['comp1.in1'], 1.0, 0.00001)
Example #9
0
    def __init__(self, target, high=None, low=None,
                 scaler=None, adder=None, start=None,
                 fd_step=None, scope=None, name=None,
                 _expreval=None):
        """If scaler and/or adder are not None, then high, low, and start, if
        not None, are assumed to be expressed in unscaled form. If high and low
        are not supplied, then their values will be pulled from the target
        variable (along with a start value), and are assumed to be in scaled
        form, so their values will be unscaled prior to being stored in the
        Parameter.
        """

        if scaler is None and adder is None:
            self._transform = self._do_nothing
            self._untransform = self._do_nothing
        if scaler is None:
            scaler = 1.0
        if adder is None:
            adder = 0.0

        self.low = low
        self.high = high
        self.scaler = scaler
        self.adder = adder
        self.start = start
        self.fd_step = fd_step

        self.name = name or target

        if _expreval is None:
            try:
                _expreval = ExprEvaluator(target, scope)
            except Exception as err:
                raise err.__class__("Can't add parameter: %s" % str(err))
            if not _expreval.is_valid_assignee():
                raise ValueError("Can't add parameter: '%s' is not a valid"
                                 " parameter expression" % _expreval.text)
        self._expreval = _expreval

        try:
            self._metadata = self._expreval.get_metadata()
        except AttributeError:
            raise AttributeError("Can't add parameter '%s' because it doesn't"
                                 " exist." % target)

        # 'raw' metadata is in the form [(varname, metadata)],
        # so use [0][1] to get the actual metadata dict
        metadata = self._metadata[0][1]

        if 'iotype' in metadata and metadata['iotype'] == 'out':
            raise RuntimeError("Can't add parameter '%s' because '%s' is an"
                               " output." % (target, target))
        try:
            # So, our traits might not have a vartypename?
            self.vartypename = metadata['vartypename']
        except KeyError:
            self.vartypename = None
Example #10
0
 def _register_expr(self, s):
     """If the given string contains an expression, create an ExprEvaluator
     and store it in self._exprs.
     """
     if not is_legal_name(s):
         expr = ExprEvaluator(s)
         if self._exprs is None:
             self._exprs = {}
         self._exprs[s] = expr
    def test_bogus(self):
        # now try some bogus expressions
        try:
            ex = ExprEvaluator('abcd.efg', self.top)
            ex.evaluate()
        except AttributeError, err:

            self.assertEqual(str(err), "can't evaluate expression 'abcd.efg':"
                                       " : 'Assembly' object has no attribute 'abcd'")
Example #12
0
 def test_multi_object(self):
     # verify that expressions with multiple objects raise a reasonable error message
     # when a set is attempted.
     try:
         ex = ExprEvaluator('comp.x+comp.x', self.top)
         ex.set(1)
     except ValueError, err:
         self.assertEqual(
             str(err), "expression 'comp.x+comp.x' can't be set to a value")
    def test_no_scope(self):
        ex = ExprEvaluator('abs(-3)+int(2.3)+math.floor(5.4)')
        self.assertEqual(ex.evaluate(), 10.0)

        ex.text = 'comp.x'
        try:
            ex.evaluate()
        except Exception, err:
            self.assertEqual(str(err), "can't evaluate expression 'comp.x':"
                                       " 'NoneType' object has no attribute 'get'")
    def test_eval_gradient_array(self):
        top = set_as_top(Assembly())
        top.add('comp1', A())
        top.run()

        # Uncomment these when arrays work
        exp = ExprEvaluator('4.0*comp1.b2d[0][1]*comp1.b2d[1][1]', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp1.b2d[0][1]'], 12.0, 0.00001)
        assert_rel_error(self, grad['comp1.b2d[1][1]'], 4.0, 0.00001)
 def test_get_referenced_varpaths(self):
     ex = ExprEvaluator('comp.x[0] = 10*(3.2+ a.a1d[3]* 1.1*a.a1d[2 ])',
                        self.top.a)
     self.assertEqual(ex.get_referenced_varpaths(), set(['comp.x',
                                                         'a.a1d']))
     ex.text = 'comp.contlist[1].a2d[2][1]'
     self.assertEqual(ex.get_referenced_varpaths(), set(['comp.contlist']))
     ex.scope = self.top.comp
     ex.text = 'comp.contlist[1]'
     self.assertEqual(ex.get_referenced_varpaths(), set(['comp.contlist']))
Example #16
0
 def _register_expr(self, s):
     """If the given string contains an expression, create an ExprEvaluator and
     store it in self._exprs
     """
     match = _namecheck_rgx.match(s)
     if match is None or match.group() != s:
         expr =  ExprEvaluator(s)
         if self._exprs is None:
             self._exprs = {}
         self._exprs[s] = expr
 def test_resolve(self):
     ex = ExprEvaluator('comp.x[0] = 10*(3.2+ a.a1d[3]* 1.1*a.a1d[2 ])', self.top)
     self.assertEqual(ex.check_resolve(), True)
     ex.text = 'comp.contlist[1].a2d[2][1]'
     self.assertEqual(ex.check_resolve(), True)
     ex.scope = self.top.comp
     ex.text = 'contlist[1]'
     self.assertEqual(ex.check_resolve(), True)
     ex.text = 'contlist[1]-foo.flambe'
     self.assertEqual(ex.check_resolve(), False)
    def test_bogus(self):
        # now try some bogus expressions
        try:
            ex = ExprEvaluator('abcd.efg', self.top)
            ex.evaluate()
        except AttributeError, err:

            self.assertEqual(
                str(err), "can't evaluate expression 'abcd.efg':"
                " : name 'abcd' is not defined")
 def test_slice(self):
     ex = ExprEvaluator('a1d[1::2]', self.top.a)
     self.assertTrue(all(array([2., 4., 6.]) == ex.evaluate()))
     ex.text = 'a1d[2:4]'
     self.assertTrue(all(array([3., 4.]) == ex.evaluate()))
     ex.text = 'a1d[2:]'
     self.assertTrue(all(array([3., 4., 5., 6.]) == ex.evaluate()))
     ex.text = 'a1d[::-1]'
     self.assertTrue(all(array([6., 5., 4., 3., 2., 1.]) == ex.evaluate()))
     ex.text = 'a1d[:2]'
     self.assertTrue(all(array([1., 2.]) == ex.evaluate()))
    def test_no_scope(self):
        ex = ExprEvaluator('abs(-3)+int(2.3)+math.floor(5.4)')
        self.assertEqual(ex.evaluate(), 10.0)

        ex.text = 'comp.x'
        try:
            ex.evaluate()
        except Exception, err:
            self.assertEqual(
                str(err),
                "can't evaluate expression 'comp.x': expression has no scope")
    def test_get_required_comps(self):
        top = set_as_top(Assembly())
        top.add('comp1', Simple())
        top.add('comp2', Simple())
        top.add('comp3', Simple())
        top.add('comp4', Simple())
        top.add('comp5', Simple())
        top.add('comp6', Simple())
        top.add('comp7', Simple())
        top.add('comp8', Simple())
        top.add('comp9', Simple())

        top.connect('comp1.c', 'comp3.a')
        top.connect('comp2.c', 'comp3.b')
        top.connect('comp3.c', 'comp5.a')
        top.connect('comp3.d', 'comp9.a')
        top.connect('comp3.d', 'comp4.a')
        top.connect('comp4.c', 'comp7.a')
        top.connect('comp3.c', 'comp6.a')
        top.connect('comp6.c', 'comp7.b')
        top.connect('comp8.c', 'comp9.b')

        exp = ExprEvaluator('comp9.c+comp5.d', top.driver)
        self.assertEqual(
            exp.get_required_compnames(top),
            set(['comp1', 'comp2', 'comp3', 'comp5', 'comp8', 'comp9']))
        exp = ExprEvaluator('comp7.a', top.driver)
        self.assertEqual(
            exp.get_required_compnames(top),
            set(['comp1', 'comp2', 'comp3', 'comp4', 'comp6', 'comp7']))
        exp = ExprEvaluator('comp8.a', top.driver)
        self.assertEqual(exp.get_required_compnames(top), set(['comp8']))
        exp = ExprEvaluator('comp9.c+comp7.d', top.driver)
        self.assertEqual(
            exp.get_required_compnames(top),
            set([
                'comp1', 'comp2', 'comp3', 'comp4', 'comp6', 'comp7', 'comp8',
                'comp9'
            ]))
        exp = ExprEvaluator('sin(0.3)', top.driver)
        self.assertEqual(exp.get_required_compnames(top), set())
Example #22
0
    def __init__(self, lhs, comparator, rhs, scaler, adder, scope=None):
        self.lhs = ExprEvaluator(lhs, scope=scope)
        if not self.lhs.check_resolve():
            raise ValueError("Constraint '%s' has an invalid left-hand-side." \
                              % ' '.join([lhs, comparator, rhs]))
        self.comparator = comparator
        self.rhs = ExprEvaluator(rhs, scope=scope)
        if not self.rhs.check_resolve():
            raise ValueError("Constraint '%s' has an invalid right-hand-side." \
                              % ' '.join([lhs, comparator, rhs]))

        if not isinstance(scaler, float):
            raise ValueError("Scaler parameter should be a float")
        self.scaler = scaler

        if scaler <= 0.0:
            raise ValueError("Scaler parameter should be a float > 0")

        if not isinstance(adder, float):
            raise ValueError("Adder parameter should be a float")
        self.adder = adder
Example #23
0
    def test_ext_slice(self):
        #Convoluted mess to test all cases of 3 x 3 x 3 array
        #where inner arrays are 2D identity matrices
        #Should cover all cases
        for k in xrange(3):
            expr = 'ext1[{0}, :, :]'.format(k)
            expr = ExprEvaluator(expr, self.top.a)
            comp = (eye(3) == expr.evaluate()).all()
            self.assertTrue(comp)

            expr = 'ext1[:, {0}, :]'.format(k)
            expr = ExprEvaluator(expr, self.top.a)
            comp = (tile(roll(array([1., 0., 0.]), k),
                         (3, 1)) == expr.evaluate()).all()
            self.assertTrue(comp)

            expr = 'ext1[:, :, {0}]'.format(k)
            expr = ExprEvaluator(expr, self.top.a)
            comp = (tile(roll(array([1., 0., 0.]), k),
                         (3, 1)) == expr.evaluate()).all()
            self.assertTrue(comp)

            for j in xrange(3):
                expr = 'ext1[:, {0}, {1}]'.format(j, k)
                expr = ExprEvaluator(expr, self.top.a)

                if j == k:
                    comp = all(array([1., 1., 1.]) == expr.evaluate())
                    self.assertTrue(comp)
                else:
                    comp = all(array([0., 0., 0.]) == expr.evaluate())
                    self.assertTrue(comp)

                expr = 'ext1[{0}, :, {1}]'.format(j, k)
                expr = ExprEvaluator(expr, self.top.a)
                arr = array([1., 0., 0.])
                comp = all(roll(arr, k) == expr.evaluate())
                self.assertTrue(comp)

                expr = 'ext1[{0}, {1}, :]'.format(j, k)
                expr = ExprEvaluator(expr, self.top.a)
                arr = array([1., 0., 0.])
                comp = all(roll(arr, k) == expr.evaluate())
                self.assertTrue(comp)

                for i in xrange(3):
                    expr = 'ext1[{0}, {1}, {2}]'.format(i, j, k)
                    expr = ExprEvaluator(expr, self.top.a)

                    if j == k:
                        comp = all(array([1.]) == expr.evaluate())
                        self.assertTrue(comp)
                    else:
                        comp = all(array([0.]) == expr.evaluate())
                        self.assertTrue(comp)
    def __init__(self, lhs, center, rhs, comparator, scope):
        self.lhs = ExprEvaluator(lhs, scope=scope)
        unresolved_vars = self.lhs.get_unresolved()

        if unresolved_vars:
            msg = "Left hand side of constraint '{0}' has invalid variables {1}"
            expression = ' '.join((lhs, comparator, center, comparator, rhs))

            raise ExprEvaluator._invalid_expression_error(unresolved_vars,
                                                          expr=expression,
                                                          msg=msg)
        self.center = ExprEvaluator(center, scope=scope)
        unresolved_vars = self.center.get_unresolved()

        if unresolved_vars:
            msg = "Center of constraint '{0}' has invalid variables {1}"
            expression = ' '.join((lhs, comparator, center, comparator, rhs))

            raise ExprEvaluator._invalid_expression_error(unresolved_vars,
                                                          expr=expression,
                                                          msg=msg)
        self.rhs = ExprEvaluator(rhs, scope=scope)
        unresolved_vars = self.rhs.get_unresolved()

        if unresolved_vars:
            msg = "Right hand side of constraint '{0}' has invalid variables {1}"
            expression = ' '.join((lhs, comparator, center, comparator, rhs))

            raise ExprEvaluator._invalid_expression_error(unresolved_vars,
                                                          expr=expression,
                                                          msg=msg)
        self.comparator = comparator
        self.pcomp_name = None
        self._size = None

        # Linear flag: constraints are nonlinear by default
        self.linear = False

        self.low = self.lhs.evaluate()
        self.high = self.rhs.evaluate()
Example #25
0
    def ensure_init(self):
        """Make sure our inputs and outputs have been
        initialized.
        """
        # set the current value of the connected variable
        # into our input
        for ref, in_name in self._inmap.items():
            setattr(self, in_name, ExprEvaluator(ref).evaluate(self.parent))
            if has_interface(getattr(self, in_name), IContainer):
                getattr(self, in_name).name = in_name

        # set the initial value of the output
        outval = self._srcexpr.evaluate()
        setattr(self, 'out0', outval)
 def test_get_referenced_compnames(self):
     ex = ExprEvaluator('comp.x[0] = 10*(3.2+ a.a1d[3]* 1.1*a.a1d[2 ].foobar)', self.top.a)
     self.assertEqual(ex.get_referenced_compnames(), set(['comp', 'a']))
     ex.text = 'comp.contlist[1].a2d[2][1]'
     self.assertEqual(ex.get_referenced_compnames(), set(['comp']))
     ex.scope = self.top.comp
     ex.text = 'comp.contlist[1]'
     self.assertEqual(ex.get_referenced_compnames(), set(['comp']))
     ex.text = 'comp.contlist[1].foo'
     self.assertEqual(ex.get_referenced_compnames(), set(['comp']))
     ex.text = 'contlist[1].foo'
     self.assertEqual(ex.get_referenced_compnames(), set())
     ex.text = 'asm2.comp3.contlist[1].foo'
     self.assertEqual(ex.get_referenced_compnames(), set(['asm2']))
Example #27
0
    def test_eval_gradient_array(self):
        top = set_as_top(Assembly())
        top.add('comp1', A())
        top.run()

        # Uncomment these when arrays work
        exp = ExprEvaluator('4.0*comp1.b2d[0][1]*comp1.b2d[1][1]', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp1.b2d[0][1]'], 12.0, 0.00001)
        assert_rel_error(self, grad['comp1.b2d[1][1]'], 4.0, 0.00001)

        exp = ExprEvaluator('comp1.c2d**2', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp1.c2d'][0, 0], 0.0, 0.00001)
        assert_rel_error(self, grad['comp1.c2d'][1, 1], 2.0, 0.00001)
        assert_rel_error(self, grad['comp1.c2d'][2, 2], 4.0, 0.00001)
        assert_rel_error(self, grad['comp1.c2d'][3, 3], 6.0, 0.00001)

        exp = ExprEvaluator('comp1.c1d**2', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp1.c1d'][0, 0], 0.0, 0.00001)
        assert_rel_error(self, grad['comp1.c1d'][1, 1], 2.0, 0.00001)
        assert_rel_error(self, grad['comp1.c1d'][2, 2], 4.0, 0.00001)
        assert_rel_error(self, grad['comp1.c1d'][3, 3], 6.0, 0.00001)

        exp = ExprEvaluator('comp1.a2d + comp1.c2d**2', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        a2d_grad, c2d_grad = grad['comp1.a2d'], grad['comp1.c2d']
        assert_rel_error(self, a2d_grad[0, 0], 1.0, 0.00001)
        assert_rel_error(self, a2d_grad[1, 1], 1.0, 0.00001)
        assert_rel_error(self, a2d_grad[2, 2], 1.0, 0.00001)
        assert_rel_error(self, a2d_grad[3, 3], 1.0, 0.00001)

        assert_rel_error(self, c2d_grad[0, 0], 0.0, 0.00001)
        assert_rel_error(self, c2d_grad[1, 1], 2.0, 0.00001)
        assert_rel_error(self, c2d_grad[2, 2], 4.0, 0.00001)
        assert_rel_error(self, c2d_grad[3, 3], 6.0, 0.00001)
    def test_eval_gradient(self):
        top = set_as_top(Assembly())
        top.add('comp1', Simple())
        top.run()

        exp = ExprEvaluator('3.0*comp1.c', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        self.assertEqual(top.comp1.c, 7.0)
        assert_rel_error(self, grad['comp1.c'], 3.0, 0.00001)

        # Commented out this test, until we find a case that can't be
        # handled analytically
        # interface test: step size
        # (for linear slope, larger stepsize more accurate because of
        # python's rounding)
        #grad2 = exp.evaluate_gradient(scope=top, stepsize=0.1)
        #assert( abs(grad['comp1.c'] - 3.0) > abs(grad2['comp1.c'] - 3.0) )

        # More complicated, multiple comps
        top.add('comp2', Simple())

        exp = ExprEvaluator('comp2.b*comp1.c**2', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        self.assertEqual(len(grad), 2)
        assert_rel_error(self, grad['comp1.c'], 70.0, 0.00001)
        assert_rel_error(self, grad['comp2.b'], 49.0, 0.00001)

        # test limited varset
        grad = exp.evaluate_gradient(scope=top, wrt=['comp2.b'])
        self.assertEqual(len(grad), 1)

        exp = ExprEvaluator('pow(comp2.b,2)', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp2.b'], 10.0, 0.00001)

        exp = ExprEvaluator('pow(comp2.b,3)', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp2.b'], 75.0, 0.00001)

        exp = ExprEvaluator('log(comp2.a)', top.driver)
        grad = exp.evaluate_gradient(scope=top)
        assert_rel_error(self, grad['comp2.a'], 1. / top.comp2.a, 0.00001)

        exp = ExprEvaluator('sin(cos(comp2.b))+sqrt(comp2.a)/comp1.c',
                            top.driver)
        grad = exp.evaluate_gradient(scope=top)
        g1 = -sin(top.comp2.b) * cos(cos(
            top.comp2.b))  #true gradient components
        g2 = (2 * sqrt(top.comp2.a) * top.comp1.c)**-1
        g3 = -sqrt(top.comp2.a) / top.comp1.c**2

        assert_rel_error(self, grad['comp2.b'], g1, 0.00001)
        assert_rel_error(self, grad['comp2.a'], g2, 0.00001)
        assert_rel_error(self, grad['comp1.c'], g3, 0.00001)
    def _combined_expr(self):
        """Given a constraint object, take the lhs, operator, and
        rhs and combine them into a single expression by moving rhs
        terms over to the lhs.  For example,
        for the constraint 'C1.x < C2.y + 7', return the expression
        'C1.x - C2.y - 7'.  Depending on the direction of the operator,
        the sign of the expression may be flipped.  The final form of
        the constraint, when evaluated, will be considered to be satisfied
        if it evaluates to a value <= 0.
        """
        scope = self.lhs.scope

        if self.comparator.startswith('>'):
            first = self.rhs.text
            second = self.lhs.text
        else:
            first = self.lhs.text
            second = self.rhs.text

        first_zero = False
        try:
            f = float(first)
        except Exception:
            pass
        else:
            if f == 0:
                first_zero = True

        second_zero = False
        try:
            f = float(second)
        except Exception:
            pass
        else:
            if f == 0:
                second_zero = True

        if first_zero:
            newexpr = "-(%s)" % second
        elif second_zero:
            newexpr = "%s" % first
        else:
            newexpr = '%s-(%s)' % (first, second)

        return ExprEvaluator(newexpr, scope)
 def test_builtins(self):
     comp = self.top.comp
     comp.x = 1.
     comp.y = -3.
     self.assertEqual(3., ExprEvaluator('abs(comp.y)', self.top).evaluate())
     self.assertAlmostEqual(0., ExprEvaluator('sin(pi)', self.top).evaluate())
     comp.x = 1.35
     self.assertEqual(1., ExprEvaluator('floor(comp.x)', self.top).evaluate())
     self.assertEqual(2., ExprEvaluator('ceil(comp.x)', self.top).evaluate())
     comp.x = 0.
     self.assertEqual(True, ExprEvaluator('sin(comp.x)<math.cos(comp.x)', self.top).evaluate())
     comp.x = math.pi / 2.
     self.assertEqual(False, ExprEvaluator('sin(comp.x)<cos(comp.x)', self.top).evaluate())