Exemple #1
0
def _eval_eq_bounded(e, subs, error_bound, under_approx, split_dim=0):
    '''do bounded interval evaluation
    error_bound is the desired error bound
    under_approx is an array of size 1, which is an under-approximation  on the result 
                of the interval evaluation, and may be updated as we go
    split_dim is the next dimension to split (this gets cycled)
    '''
    rv = _eval_eq_direct(e, subs)
    variables = subs.keys()

    # adjust the under approximation
    if rv.b < under_approx[0].a:
        under_approx[0] = interval(rv.b, under_approx[0].b)

    if rv.a > under_approx[0].b:
        under_approx[0] = interval(under_approx[0].a, rv.a)

    if rv.a < (under_approx[0].a - error_bound) or rv.b > (under_approx[0].b + error_bound):
        # split along split_dim
        var = variables[split_dim]
        i = subs[var]
        next_split_dim = (split_dim + 1) % len(subs)
        
        bound_left = copy.deepcopy(subs)
        bound_left[var] = (i[0], (i[0] + i[1]) / 2.0)
        
        bound_right = copy.deepcopy(subs)
        bound_right[var] = ((i[0] + i[1])/2.0, i[1])        

        rv_left = _eval_eq_bounded(e, bound_left, error_bound, under_approx, next_split_dim)
        rv_right = _eval_eq_bounded(e, bound_right, error_bound, under_approx, next_split_dim)

        rv = interval(min(rv_left.a, rv_right.a), max(rv_left.b, rv_right.b))

    return rv
Exemple #2
0
def _eval_at_corners(e, subs):
    '''evaluate an expression in the middle of an interval range'''
    rv = None

    max_iterator = 1

    for _ in xrange(len(subs)):
        max_iterator *= 2

    for i in xrange(max_iterator):
        new_subs = {}

        for var, item in subs.items():
            new_subs[var] = item[i % 2]
            i /= 2

        val = _eval_eq_direct(e, new_subs)

        if rv is None:
            rv = val

        if val.a < rv.a:
            rv = interval(val.a, rv.b)
        
        if val.b > rv.b:
            rv = interval(rv.a, val.b)

    return rv
Exemple #3
0
def _test():
    '''runs module unit tests'''

    # Test below - tries every supported subexpression - takes a few seconds
    x = symbols('x')
    eq = sin(x + 0.01)
    #eq = 1*x*x + (0.2-x) / x + sin(x+0.01) + sqrt(x + 1) + cos(x + 0.01) + tan(x + 0.01) - (x+0.1)**(x+0.1)

    print eval_eq(eq, {'x':interval(0.20, 0.21)})

########################################################################
# Test below - makes sure evalEqMulti works as expected
    x = symbols('x')
    eq = x + interval(0.1)
    range1 = {'x':interval(0, 1)}
    range2 = {'x':interval(1, 2)}

    for i in eval_eq_multi(eq, [range1, range2]):
        print i

########################################################################
# Test below - makes sure eval_eq_multi_branch_bound works as expected
    x = symbols('x')
    eq = x*x - 2*x
    range1 = {'x':interval(0, 2)}

    for i in eval_eq_multi_branch_bound(eq, [range1], 0.1):
        print i
Exemple #4
0
def _eval_eq_direct(e, subs=None):
    '''do the actual interval evaluation'''
    rv = None

    if not isinstance(e, Expr):
        raise RuntimeError("Expected sympy Expr: " + repr(e))

    if isinstance(e, Symbol):
        if subs == None:
            raise RuntimeError("Symbol '" + str(e) + "' found but no substitutions were provided")

        val = subs.get(str(e))

        if val == None:
            raise RuntimeError("No substitution was provided for symbol '" + str(e) + "'")

        rv = val
    elif isinstance(e, Number):
        rv = interval(Float(e))
    elif isinstance(e, Mul):
        rv = interval(1)

        for child in e.args:
            rv *= _eval_eq_direct(child, subs)
    elif isinstance(e, Add):
        rv = interval(0)

        for child in e.args:
            rv += _eval_eq_direct(child, subs)
    elif isinstance(e, Pow):
        term = _eval_eq_direct(e.args[0], subs)
        exponent = _eval_eq_direct(e.args[1], subs)

        rv = term**exponent
    else:
        # interval function evaluation (like sin)
        func_map = [(sin, iv.sin), (cos, iv.cos), (tan, iv.tan)]

        for entry in func_map:
            t = entry[0] # type
            f = entry[1] # function to call

            if isinstance(e, t):
                inner_arg = _eval_eq_direct(e.args[0], subs) 
                rv = f(inner_arg)
                break

    if rv == None:
        raise RuntimeError("Type '" + str(type(e)) + "' is not yet implemented for interval evaluation. " + \
                            "Subexpression was '" + str(e) + "'.")

    return rv
Exemple #5
0
def _basinhopping(e, subs):
    '''use scipy basinhopping to get an underestimate
    e is a sympy expression
    subs is the substitution map
    '''

    symbol_list = []
    limits = []

    for var, lim in subs.items():
        symbol_list.append(symbols(var))
        limits.append(lim)

    def eval_func(var_list):
        '''eval func used for optimization'''

        sub_list = {}
        for i in xrange(len(var_list)):
            sub_list[symbol_list[i]] = var_list[i]

        return float(e.evalf(subs=sub_list))

    i = scipy_optimize.opt(eval_func, limits, niter=10)

    return interval(i[0], i[1])
Exemple #6
0
def _eval_eq_branch_bound(e, subs, bound):
    '''do branch and bound interval evaluation'''
    rv = None

    for var, i in subs.iteritems():
        if i.delta > bound:
            # recursive cases, use smaller bounds
            bound_left = copy.deepcopy(subs)
            bound_left[var] = interval(i.a, (i.a + i.b) / 2)
            rv_left = _eval_eq_branch_bound(e, bound_left, bound)

            bound_right = copy.deepcopy(subs)
            bound_right[var] = interval((i.a + i.b)/2, i.b)
            rv_right = _eval_eq_branch_bound(e, bound_right, bound)

            rv = interval(min(rv_left.a, rv_right.a), max(rv_left.b, rv_right.b))
            break

    if rv == None:
        # base case, interval was small enough
        rv = _eval_eq_direct(e, subs)

    return rv