Exemple #1
0
    def split_stochastic(self):
        '''
        Split the expression into a stochastic and non-stochastic part.
        
        Splits the expression into a tuple of one `Expression` objects f (the
        non-stochastic part) and a dictionary mapping stochastic variables
        to `Expression` objects. For example, an expression of the form 
        ``f + g * xi_1 + h * xi_2`` would be returned as:
        ``(f, {'xi_1': g, 'xi_2': h})``
        Note that the `Expression` objects for the stochastic parts do not
        include the stochastic variable itself. 
        
        Returns
        -------
        (f, d) : (`Expression`, dict)
            A tuple of an `Expression` object and a dictionary, the first
            expression being the non-stochastic part of the equation and 
            the dictionary mapping stochastic variables (``xi`` or starting
            with ``xi_``) to `Expression` objects. If no stochastic variable
            is present in the code string, a tuple ``(self, None)`` will be
            returned with the unchanged `Expression` object.
        '''
        stochastic_variables = []
        for identifier in self.identifiers:
            if identifier == 'xi' or identifier.startswith('xi_'):
                stochastic_variables.append(identifier)

        # No stochastic variable
        if not len(stochastic_variables):
            return (self, None)

        s_expr = self.sympy_expr.expand()

        stochastic_symbols = [
            sympy.Symbol(variable, real=True)
            for variable in stochastic_variables
        ]

        f = sympy.Wild('f', exclude=stochastic_symbols)  # non-stochastic part
        match_objects = [
            sympy.Wild('w_' + variable, exclude=stochastic_symbols)
            for variable in stochastic_variables
        ]
        match_expression = f
        for symbol, match_object in zip(stochastic_symbols, match_objects):
            match_expression += match_object * symbol
        matches = s_expr.match(match_expression)

        if matches is None:
            raise ValueError(
                ('Expression "%s" cannot be separated into stochastic '
                 'and non-stochastic term') % self.code)

        f_expr = Expression(sympy_to_str(matches[f]))
        stochastic_expressions = dict(
            (variable, Expression(sympy_to_str(matches[match_object])))
            for (variable,
                 match_object) in zip(stochastic_variables, match_objects))

        return (f_expr, stochastic_expressions)
def get_conditionally_linear_system(eqs):
    '''
    Convert equations into a linear system using sympy.
    
    Parameters
    ----------
    eqs : `Equations`
        The model equations.
    
    Returns
    -------
    coefficients : dict of (sympy expression, sympy expression) tuples
        For every variable x, a tuple (M, B) containing the coefficients M and
        B (as sympy expressions) for M * x + B
    
    Raises
    ------
    ValueError
        If one of the equations cannot be converted into a M * x + B form.

    Examples
    --------
    >>> from brian2 import Equations
    >>> eqs = Equations("""
    ... dv/dt = (-v + w**2) / tau : 1
    ... dw/dt = -w / tau : 1
    ... """)
    >>> system = get_conditionally_linear_system(eqs)
    >>> print(system['v'])
    (-1/tau, w**2.0/tau)
    >>> print(system['w'])
    (-1/tau, 0)

    '''
    diff_eqs = eqs.substituted_expressions

    coefficients = {}

    for name, expr in diff_eqs:
        var = sp.Symbol(name, real=True)

        # Coefficients
        wildcard = sp.Wild('_A', exclude=[var])
        #Additive constant
        constant_wildcard = sp.Wild('_B', exclude=[var])
        pattern = wildcard * var + constant_wildcard

        # Factor out the variable
        s_expr = sp.collect(expr.sympy_expr.expand(), var)
        matches = s_expr.match(pattern)

        if matches is None:
            raise ValueError(
                ('The expression "%s", defining the variable %s, '
                 'could not be separated into linear components') %
                (s_expr, name))
        coefficients[name] = (matches[wildcard].simplify(),
                              matches[constant_wildcard].simplify())

    return coefficients
Exemple #3
0
def trig_substitution_rule(integral):
    integrand, symbol = integral
    A = sympy.Wild('a', exclude=[0, symbol])
    B = sympy.Wild('b', exclude=[0, symbol])
    theta = sympy.Dummy("theta")
    target_pattern = A + B*symbol**2

    matches = integrand.find(target_pattern)
    for expr in matches:
        match = expr.match(target_pattern)
        a = match.get(A, ZERO)
        b = match.get(B, ZERO)

        a_positive = ((a.is_number and a > 0) or a.is_positive)
        b_positive = ((b.is_number and b > 0) or b.is_positive)
        a_negative = ((a.is_number and a < 0) or a.is_negative)
        b_negative = ((b.is_number and b < 0) or b.is_negative)
        x_func = None
        if a_positive and b_positive:
            # a**2 + b*x**2. Assume sec(theta) > 0, -pi/2 < theta < pi/2
            x_func = (sympy.sqrt(a)/sympy.sqrt(b)) * sympy.tan(theta)
            # Do not restrict the domain: tan(theta) takes on any real
            # value on the interval -pi/2 < theta < pi/2 so x takes on
            # any value
            restriction = True
        elif a_positive and b_negative:
            # a**2 - b*x**2. Assume cos(theta) > 0, -pi/2 < theta < pi/2
            constant = sympy.sqrt(a)/sympy.sqrt(-b)
            x_func = constant * sympy.sin(theta)
            restriction = sympy.And(symbol > -constant, symbol < constant)
        elif a_negative and b_positive:
            # b*x**2 - a**2. Assume sin(theta) > 0, 0 < theta < pi
            constant = sympy.sqrt(-a)/sympy.sqrt(b)
            x_func = constant * sympy.sec(theta)
            restriction = sympy.And(symbol > -constant, symbol < constant)
        if x_func:
            # Manually simplify sqrt(trig(theta)**2) to trig(theta)
            # Valid due to assumed domain restriction
            substitutions = {}
            for f in [sympy.sin, sympy.cos, sympy.tan,
                      sympy.sec, sympy.csc, sympy.cot]:
                substitutions[sympy.sqrt(f(theta)**2)] = f(theta)
                substitutions[sympy.sqrt(f(theta)**(-2))] = 1/f(theta)

            replaced = integrand.subs(symbol, x_func).trigsimp()
            replaced = replaced.subs(substitutions)
            if not replaced.has(symbol):
                replaced *= manual_diff(x_func, theta)
                replaced = replaced.trigsimp()
                secants = replaced.find(1/sympy.cos(theta))
                if secants:
                    replaced = replaced.xreplace({
                        1/sympy.cos(theta): sympy.sec(theta)
                    })

                substep = integral_steps(replaced, theta)
                if not contains_dont_know(substep):
                    return TrigSubstitutionRule(
                        theta, x_func, replaced, substep, restriction,
                        integrand, symbol)
Exemple #4
0
def coeff(expr, term):
    expr = sp.collect(expr, term)
    symbols = list(term.atoms(sp.Symbol))
    w = sp.Wild("coeff", exclude=symbols)
    m = expr.match(w * term + sp.Wild("rest"))
    if m:
        return m[w]
Exemple #5
0
def holstein(Hdef):
    S = sympy.Symbol('S', real=True)
    print 'holstein'
    #print Hdef.atoms(sympy.Symbol)
    Hdef = Hdef.expand()
    #Hdef=Hdef.as_poly(S)
    p = sympy.Wild('p', exclude='S')
    q = sympy.Wild('q', exclude='S')
    r = sympy.Wild('r', exclude='S')
    l = sympy.Wild('l', exclude='S')
    #Hlin=Hdef.coeffs[0]*S**2+Hdef.coeffs[1]*S
    S2coeff = coeff(Hdef, S**2)
    Scoeff = coeff(Hdef, S)
    Hlin = None
    #Hlin=coeff(Hdef,S**2)*S**2+coeff(Hdef,S)*S
    #print 'S2Coeff', S2coeff
    #print 'Scoeff',Scoeff
    if Scoeff != None and S2coeff != None:
        Hlin = coeff(Hdef, S**2) * S**2 + coeff(Hdef, S) * S
    elif Scoeff == None and S2coeff != None:
        Hlin = coeff(Hdef, S**2) * S**2
    elif Scoeff != None and S2coeff == None:
        #print 'S'
        Hlin = coeff(Hdef, S) * S
    return Hlin
Exemple #6
0
def make_wilds(symbol):
    a = sympy.Wild('a', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    m = sympy.Wild('m', exclude=[symbol], properties=[lambda n: isinstance(n, sympy.Integer)])
    n = sympy.Wild('n', exclude=[symbol], properties=[lambda n: isinstance(n, sympy.Integer)])

    return a, b, m, n
Exemple #7
0
    def can_be_applied(self, dim_exprs, variable_context, node_range,
                       orig_edges, dim_index, total_dims):
        # Pattern does not support unions of expressions
        if len(dim_exprs) > 1: return False
        dexpr = dim_exprs[0]
        # Pattern does not support ranges
        if not isinstance(dexpr, sympy.Basic): return False

        # Create wildcards
        val = sympy.Wild('val')
        mod = sympy.Wild('mod', exclude=variable_context[-1])

        # Try to match an affine expression
        matches = dexpr.match(val % mod)
        if matches is None or len(matches) != 2:
            return False

        self.subexpr = matches[val]
        self.modulo = matches[mod]

        self.subpattern = None
        for pattern_class in SeparableMemletPattern.s_smpatterns:
            smpattern = pattern_class()
            if smpattern.can_be_applied([self.subexpr], variable_context,
                                        node_range, orig_edges, dim_index,
                                        total_dims):
                self.subpattern = smpattern

        return self.subpattern is not None
def test_match_for_assignment_collection():

    x, y = pystencils.fields('x, y:  float32[3d]')
    a, b, c, d = sp.symbols('a, b, c, d')

    assignments = pystencils.AssignmentCollection({
        a: sp.floor(1),
        b: 2,
        c: a + c,
        y.center(): sp.ceiling(x.center()) + sp.floor(x.center())
    })

    w1 = sp.Wild('w1')
    w2 = sp.Wild('w2')
    w3 = sp.Wild('w3')

    wild_ceiling = sp.ceiling(w1)
    wild_addition = w1 + w2

    assert assignments.match(pystencils.Assignment(w3, wild_ceiling + w2))[w1] == x.center()
    assert assignments.match(pystencils.Assignment(w3, wild_ceiling + w2)) == {
        w3: y.center(),
        w2: sp.floor(x.center()),
        w1: x.center()
    }
    assert assignments.find(wild_ceiling) == {sp.ceiling(x.center())}
    assert len([a for a in assignments.find(wild_addition) if isinstance(a, sp.Add)]) == 2
Exemple #9
0
    def tick(self, tick):
       Tm = tick.blackboard.get('Tm')   # the current matrix equation  
       unknowns = tick.blackboard.get('unknowns')
       R = tick.blackboard.get('Robot')
       
       u = tick.blackboard.get('curr_unk')
          
       if u.readytosolve:
           if(self.BHdebug):
                        print "I'm trying to solve: ", u.symbol
                        print "  Using: ", 
                        print u.eqntosolve  
           if u.solvemethod == "algebra":

               Aw = sp.Wild("Aw")
               Bw = sp.Wild("Bw")
               d = u.eqntosolve.RHS.match(Aw*u.symbol+Bw)
               A = d[Aw]
               B = d[Bw]
               u.solutions.append( (u.eqntosolve.LHS-B)/A  )       # one soluntion 
               u.nsolutions = 1   # or 1
               u.set_solved(R,unknowns)  # flag that this is solved 
       tick.blackboard.set('curr_unk', u)
       tick.blackboard.set('unknowns', unknowns)
       return b3.SUCCESS
def Max_Stress(stress,graph,dir=[],num_list=[],Number_Average=5):
	a = syp.Wild('a')
	b = syp.Wild('b')
	c = syp.Wild('c')
	x = syp.symbols('x')
	y = syp.symbols('y')
	
	ccc = syp.collect(stress,[x,y],evaluate=False)
	try:
		a1 = float(ccc[x])
	except:
		a1 = 0

	try:
		b1 = float(ccc[y])
	except:
		b1 = 0

	try:
		c1 = float(ccc[S(1)])
	except:
		c1 = 0

	xdir = [float(dir[i][0]) for i in range(0,len(dir))]
	ydir = [float(dir[i][1]) for i in range(0,len(dir))]

	max_stress = 0
	min_stress = 0
	if num_list == []:
		for v in graph:
			for e in v.getConnections():
				thick_ij = v.getWeight(e)
				if thick_ij != 0:
					xx = np.linspace(xdir[v.id],xdir[e.id],Number)
					yy = np.linspace(ydir[v.id],ydir[e.id],Number)
					zz = a1*xx + b1*yy + c1

					a = max(zz)
					if a > max_stress:
						max_stress = a
					b = min(zz)
					if b < min_stress:
						min_stress = b
	if num_list:
		for i in range(len(num_list)):
			m = num_list[i][0]
			n = num_list[i][1]

			xx = np.linspace(xdir[m],xdir[n],Number_Average)
			yy = np.linspace(ydir[m],ydir[n],Number_Average)
			zz = a1*xx + b1*yy + c1

			a = max(zz)
			if a > max_stress:
				max_stress = a
			b = min(zz)
			if b < min_stress:
				min_stress = b

	return [max_stress,min_stress]
Exemple #11
0
def heaviside_pattern(symbol):
    m = sympy.Wild('m', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    g = sympy.Wild('g')
    pattern = sympy.Heaviside(m * symbol + b) * g

    return pattern, m, b, g
Exemple #12
0
    def tick(self, tick):
        unknowns = tick.blackboard.get("unknowns")
        R = tick.blackboard.get('Robot')
        Tm = tick.blackboard.get('Tm')
        solvedtag = False

        thx = sp.Wild('thx')
        thy = sp.Wild('thy')
        sgn = sp.Wild('sgn')

        #for unk in unknowns:
        #if unk.n == 0 and unk.solved: #joint varible has order of 0

        if len(Tm.auxeqns) > 0:
            for e in Tm.auxeqns:
                #d = unk.joint_eq.match(thx + sgn * thy)
                print e
                d = e.RHS.match(thx + sgn * thy)

                unka = find_obj(d[thx], unknowns)
                #print unka
                unkb = find_obj(d[thy], unknowns)
                #print unkb
                if unka == None:
                    print "variable %s doesn't exist" % (d[thx])
                elif unkb == None:
                    print "variable %s doesn't exist" % (d[thy])
                else:

                    if unka.solved and (not unkb.solved):
                        sol = (e.LHS - unka.symbol) / d[sgn]
                        unkb.solutions.append(sol)
                        unkb.nsolutions = 1
                        unkb.set_solved(R, unknowns)
                        solvedtag = True

                        if self.BHdebug:
                            print "I'm solving %s from joint variable %s" % (
                                unkb.symbol, e.LHS)
                            print "solution: %s" % sol

                    elif unkb.solved and (not unka.solved):
                        sol = e.LHS - d[sgn] * unkb.symbol
                        unka.solutions.append(sol)
                        unka.nsolutions = 1
                        unka.set_solved(R, unknowns)
                        solvedtag = True

                        if self.BHdebug:
                            print "I'm solving %s from joint variable %s" % (
                                unka.symbol, e.LHS)
                            print "solution: %s" % sol
        #tick.blackboard.set('test_id', test_id)
        tick.blackboard.set('unknowns', unknowns)
        tick.blackboard.set('Robot', R)
        if solvedtag:
            return b3.SUCCESS

        return b3.FAILURE
Exemple #13
0
 def flip_variant(expr):
     """ Change every momentum in expr from contravariant to
         covariant or vice versa and returns the new expression.
     """
     a = sy.Wild("a")
     b = sy.Wild("b")
     c = sy.Wild("c")
     return expr.replace(Momentum(a, b, c), Momentum(a, b, 1 - c))
    def tick(self, tick):
        unknowns = tick.blackboard.get(
            'unknowns')  # the current list of unknowns
        R = tick.blackboard.get('Robot')

        one_unk = tick.blackboard.get('eqns_1u')
        two_unk = tick.blackboard.get('eqns_2u')

        u = tick.blackboard.get('curr_unk')
        # identify unknowns in T where one equation can be solved by
        #        arcsin() or arccos()

        Aw = sp.Wild("Aw")
        Bw = sp.Wild("Bw")
        Cw = sp.Wild('Cw')
        Dw = sp.Wild('Dw')
        found = False

        if (not u.solved):  # only if not already solved!
            for e in one_unk:  # only look at the eqns with one unknowns
                print "Looking for unknown: ", u.symbol, " in equation: ",
                print e

                tmp = e.RHS - e.LHS
                lhs = l_1 - l_1
                if (tmp.has(sp.sin(u.symbol)) and tmp.has(sp.cos(u.symbol))):

                    es = tmp.expand()
                    # collect terms in sin(x) and cos(x)
                    es = es.collect(sp.sin(u.symbol))
                    es = es.collect(sp.cos(u.symbol))

                    d = {}
                    d[Aw] = es.coeff(sp.sin(u.symbol))
                    d[Bw] = es.coeff(sp.cos(u.symbol))
                    d[Cw] = es - d[Aw] * sp.sin(u.symbol) - d[Bw] * sp.cos(
                        u.symbol)

                    if (self.BHdebug):
                        print 'Sin AND Cos identifying: ', es
                        print 'Aw: ', d[Aw], ' Bw: ', d[Bw], ' Cw: ', d[Cw]

                    if not d[Cw].has(u.symbol):
                        u.readytosolve = True
                        u.eqntosolve = kc.kequation(lhs, es)
                        u.solvemethod = "sinANDcos"
                        found = True
                        break

        tick.blackboard.set('curr_unk', u)
        tick.blackboard.set('Robot', R)
        tick.blackboard.set('unknowns',
                            unknowns)  # the current list of unknowns

        if found:
            return b3.SUCCESS
        else:
            return b3.FAILURE
def test_wild_typed_symbol():
    x = pystencils.fields('x:  float32[3d]')
    typed_symbol = pystencils.data_types.TypedSymbol('a', create_type('float64'))

    assert x.center().match(sp.Wild('w1'))
    assert typed_symbol.match(sp.Wild('w1'))

    wild_ceiling = sp.ceiling(sp.Wild('w1'))
    assert sp.ceiling(x.center()).match(wild_ceiling)
    assert sp.ceiling(typed_symbol).match(wild_ceiling)
Exemple #16
0
def _check_map_conflicts(map, edge):
    for itervar, (_, _, mapskip) in zip(map.params, map.range):
        itersym = symbolic.pystr_to_symbolic(itervar)
        a = sp.Wild('a', exclude=[itersym])
        b = sp.Wild('b', exclude=[itersym])
        if not _check_range_conflicts(edge.data.subset, a, itersym, b,
                                      mapskip):
            return False
    # If matches all map params, good to go
    return True
Exemple #17
0
def generate_cross_section(N, arg, atom_list):
    """Generates the Cross-Section Formula for the one magnon case"""
    S = sp.Symbol('S', commutative=True)
    gam = sp.Symbol('gamma', commutative=True)
    r = sp.Symbol('r0', commutative=True)
    h = sp.Symbol('hbar', commutative=True)
    k = sp.Symbol('k', commutative=True)
    kp = sp.Symbol('kp', commutative=True)
    g = sp.Symbol('g', commutative=True)
    F = sp.Function('F')
    kap = sp.Symbol('kappa', commutative=True)
    kapx = sp.Symbol('kappax', commutative=True)
    kapy = sp.Symbol('kappay', commutative=True)
    w = sp.Symbol('w', commutative=True)
    W = sp.Symbol('W', commutative=False)
    t = sp.Symbol('t', commutative=True)
    dif = sp.Symbol('diff', commutative=False)

    A = sp.Wild('A', exclude=[0])
    B = sp.Wild('B', exclude=[0])
    C = sp.Wild('C', exclude=[0])
    D = sp.Wild('D', exclude=[0])

    front_constant = (gam * r)**2 / (2 * pi * h) * (kp / k) * N
    front_func = (1. / 2.) * g * F(kap) * exp(-2 * W)

    temp2 = []
    temp3 = []
    temp4 = []

    # This is were the heart of the calculation comes in.
    # First the exponentials are turned into delta functions:
    #   exp(I(wq*t - w*t)) ---> delta(wq-w)
    #   exp(I(wq*t - w*t)+I*(q-qp)*l) ---> delta(wq*t-w*t+q*l-qp*l) ---> delta(wq-w)*delta(q*l-qp*l)        # NEEDS REVIEW
    for i in range(len(arg)):  # _
        for j in range(N):  # ^
            arg[i][j] = (arg[i][j] * exp(-I * w * t)).expand()  # |
            arg[i][j] = sub_in(arg[i][j], exp(A * I * t + B * I * t),
                               sp.DiracDelta(A + B))  # |
            arg[i][j] = sub_in(arg[i][j],
                               exp(I * t * A + I * t * B + I * C + I * D),
                               sp.DiracDelta(A * t + B * t + C + D))  # |
            arg[i][j] = sub_in(arg[i][j], sp.DiracDelta(A * t + B * t + C + D),
                               sp.DiracDelta(A + B) *
                               sp.DiracDelta(C + D))  # |
            temp2.append(exp(I * kap * atom_list[j]) * arg[i][j])  # |
        temp3.append(sum(temp2))  # |
    print "Converted to Delta Functions!"  # |
    for i in range(len(temp3)):  # |
        temp4.append((1 - kapx**2) * temp3[i])  # V
    dif = front_constant * front_func**2 * (sum(temp4))  # _

    print "Cross-section calculated!"
    return dif
Exemple #18
0
def write_conflicted_map_params(map, edge):
    result = []
    for itervar, (_, _, mapskip) in zip(map.params, map.range):
        itersym = symbolic.pystr_to_symbolic(itervar)
        a = sp.Wild('a', exclude=[itersym])
        b = sp.Wild('b', exclude=[itersym])
        if not _check_range_conflicts(edge.data.subset, a, itersym, b,
                                      mapskip):
            result.append(itervar)

    return result
Exemple #19
0
def _cases_from_branches(
    edges: List[Edge[InterstateEdge]],
    cblocks: Dict[Edge[InterstateEdge], GeneralBlock],
) -> Tuple[str, Dict[str, GeneralBlock]]:
    """ 
    If the input list of edges correspond to a switch/case scope (with all
    conditions being "x == y" for a unique symbolic x and integers y),
    returns the switch/case scope parameters.
    :param edges: List of inter-state edges.
    :return: Tuple of (case variable C++ expression, mapping from case to 
             control flow block). If not a valid switch/case scope, 
             returns None.
    """
    cond = edges[0].data.condition_sympy()
    if not isinstance(cond, sp.Basic):
        return None
    a = sp.Wild('a')
    b = sp.Wild('b', properties=[lambda k: k.is_Integer])
    m = cond.match(sp.Eq(a, b))
    if m:
        # Obtain original code for variable
        call_or_compare = edges[0].data.condition.code[0].value
        if isinstance(call_or_compare, ast.Call):
            astvar = call_or_compare.args[0]
        else:  # Binary comparison
            astvar = call_or_compare.left
    else:
        # Try integer == symbol
        m = cond.match(sp.Eq(b, a))
        if m:
            call_or_compare = edges[0].data.condition.code[0].value
            if isinstance(call_or_compare, ast.Call):
                astvar = call_or_compare.args[1]
            else:  # Binary comparison
                astvar = call_or_compare.right
        else:
            return None

    # Get C++ expression from AST
    switchvar = cppunparse.pyexpr2cpp(astvar)

    # Check that all edges match criteria
    result = {}
    for e in edges:
        ematch = e.data.condition_sympy().match(sp.Eq(m[a], b))
        if not ematch:
            ematch = e.data.condition_sympy().match(sp.Eq(b, m[a]))
            if not ematch:
                return None
        # Create mapping to codeblocks
        result[cpp.sym2cpp(ematch[b])] = cblocks[e]

    return switchvar, result
Exemple #20
0
def sympy_ceiling_fix(expr):
    """ Fix for SymPy printing out reciprocal values when they should be
        integral in "ceiling/floor" sympy functions.
    """
    nexpr = expr
    if not isinstance(expr, sympy.Basic):
        return expr

    # The properties avoid matching the silly case "ceiling(N/32)" as
    # ceiling of 1/N and 1/32
    a = sympy.Wild('a', properties=[lambda k: k.is_Symbol or k.is_Integer])
    b = sympy.Wild('b', properties=[lambda k: k.is_Symbol or k.is_Integer])
    c = sympy.Wild('c')
    d = sympy.Wild('d')
    int_ceil = sympy.Function('int_ceil')
    int_floor = sympy.Function('int_floor')

    processed = 1
    while processed > 0:
        processed = 0
        for ceil in nexpr.find(sympy.ceiling):
            # Simple ceiling
            m = ceil.match(sympy.ceiling(a / b))
            if m is not None:
                nexpr = nexpr.subs(ceil, int_ceil(m[a], m[b]))
                processed += 1
                continue
            # Ceiling of ceiling: "ceil(ceil(c/d) / b)"
            m = ceil.match(sympy.ceiling(int_ceil(c, d) / b))
            if m is not None:
                nexpr = nexpr.subs(ceil, int_ceil(int_ceil(m[c], m[d]), m[b]))
                processed += 1
                continue
            # Ceiling of ceiling: "ceil(a / ceil(c/d))"
            m = ceil.match(sympy.ceiling(a / int_ceil(c, d)))
            if m is not None:
                nexpr = nexpr.subs(ceil, int_ceil(m[a], int_ceil(m[c], m[d])))
                processed += 1
                continue
            # Match ceiling of multiplication with our custom integer functions
            m = ceil.match(sympy.ceiling(a * int_floor(c, d)))
            if m is not None:
                nexpr = nexpr.subs(ceil, m[a] * int_floor(m[c], m[d]))
                processed += 1
                continue
            m = ceil.match(sympy.ceiling(a * int_ceil(c, d)))
            if m is not None:
                nexpr = nexpr.subs(ceil, m[a] * int_ceil(m[c], m[d]))
                processed += 1
                continue

    return nexpr
def arctan_rule(integral):
    integrand, symbol = integral
    base, exp = integrand.as_base_exp()

    if sympy.simplify(exp + 1) == 0:
        a = sympy.Wild('a', exclude=[symbol])
        b = sympy.Wild('b', exclude=[symbol])
        match = base.match(a + b * symbol**2)
        if match:
            a, b = match[a], match[b]

            if ((isinstance(a, sympy.Number) and a < 0)
                    or (isinstance(b, sympy.Number) and b < 0)):
                return
            if (sympy.ask(
                    sympy.Q.negative(a) | sympy.Q.negative(b)
                    | sympy.Q.is_true(a <= 0) | sympy.Q.is_true(b <= 0))):
                return

            if a != 1 or b != 1:
                b_condition = b >= 0
                u_var = sympy.Dummy("u")
                rewritten = (sympy.Integer(1) / a) * (base / a)**(-1)
                u_func = sympy.sqrt(sympy.sympify(b) / a) * symbol
                constant = 1 / sympy.sqrt(sympy.sympify(b) / a)
                substituted = rewritten.subs(u_func, u_var)

                if a == b:
                    substep = ArctanRule(integrand, symbol)
                else:
                    subrule = ArctanRule(substituted, u_var)
                    if constant != 1:
                        b_condition = b > 0
                        subrule = ConstantTimesRule(constant, substituted,
                                                    subrule, substituted,
                                                    symbol)

                    substep = URule(u_var, u_func, constant, subrule,
                                    integrand, symbol)

                if a != 1:
                    other = (base / a)**(-1)
                    substep = ConstantTimesRule(
                        sympy.Integer(1) / a, other, substep, integrand,
                        symbol)

                return PiecewiseRule(
                    [(substep, sympy.And(a > 0, b_condition))], integrand,
                    symbol)

            return ArctanRule(integrand, symbol)
Exemple #22
0
def canonise_log(equation):
    expanded_log = sympy.expand_log(equation, force=True)

    terms = expanded_log.as_ordered_terms()

    a, b = sympy.Wild('a'), sympy.Wild('b')

    total_interior = 1
    for term in terms:

        if sympy.ask(sympy.Q.complex(term)):
            term_interior *= -1
        else:
            term_interior = term.match(sympy.log(a) / b)[a]

            if term.could_extract_minus_sign():
                total_interior /= term_interior
            else:
                total_interior *= term_interior

    if isinstance(total_interior, sympy.Add):
        invert = False
    elif isinstance(total_interior, sympy.Mul):

        match = total_interior.together().match(x / b)  # for some reason, (x/3).match(a/b) gives {a: 1/3, b: 1/x} so we have to use a workaround
        if match is not None:
            invert = False
        else:
            match = total_interior.together().match(a / b)

            degree_numerator = 0 if isinstance(match[a], sympy.Rational) else match[a].as_poly().degree()
            degree_denominator = 0 if isinstance(match[b], sympy.Rational) else match[b].as_poly().degree()

            if degree_numerator < degree_denominator:
                invert = True
            else:
                invert = False
    elif isinstance(total_interior, sympy.Pow):
        index = total_interior.as_base_exp()[1]
        if index < 0:
            invert = True
        else:
            invert = False

    else:  # for debugging - wtf kind of c-c-c-class is it???
        print(total_interior, type(total_interior))

    if invert:
        return -sympy.log((1 / total_interior).together(), evaluate=False) / terms[0].as_coeff_Mul()[0].q
    else:
        return sympy.log(total_interior.together(), evaluate=False) / terms[0].as_coeff_Mul()[0].q
Exemple #23
0
    def _set_axis_and_point(self, cond_eq: sympy.Equality, coords: cs.CoordinateSystem):
        coord_vars = coords.axises()
        self.axis, self.axis_point = None, None

        U = sympy.Function("u")
        u_entrances = list(cond_eq.find(U))
        if len(u_entrances) != 1:
            raise ValueError(
                "Cannot contain different args in U for derivative and u function"
            )

        a1 = sympy.Wild("a1", properties=[lambda x: x.is_constant])
        a2 = sympy.Wild("a2", properties=[lambda x: x.is_constant])
        u_pow = sympy.Wild("u_pow", properties=[lambda x: x.is_constant])
        axis = sympy.Wild("axis", properties=[lambda x: x.is_symbol])
        U_pattern = sympy.WildFunction("U_pattern", nargs=len(coords.axises()))

        res = cond_eq.lhs.match(
            a1 * U_pattern ** u_pow + a2 * sympy.Derivative(U_pattern, axis)
        )
        if res is None:
            raise ValueError(f"Cannot parse {cond_eq}")
        self.a1 = res[a1]
        self.a2 = res[a2]
        u_with_args = res[U_pattern]

        if self.a1 != 0 and self.a2 == 0:
            self.kind = ConditionKind.First.name
        elif self.a1 == 0 and self.a2 != 0:
            self.kind = ConditionKind.Second.name
        elif self.a1 != 0 and self.a2 != 0:
            self.kind = ConditionKind.Third.name
        else:
            raise ValueError(
                f"Left side of boundary condition: {cond_eq} does"
                "not contain u function"
            )

        for i, arg in enumerate(u_with_args.args):
            if arg.is_constant():
                self.axis = coord_vars[i]
                self.axis_point = sympy.fcode(arg.evalf())
                self._axis_point = arg
                break

        if self.axis is None:
            raise ValueError(
                "Bondary condition cannot be parsed"
                "Probably you did not specified U arguments or"
                "there is no constant in arguments"
            )
Exemple #24
0
def quadratic_denom_rule(integral):
    integrand, symbol = integral
    a = sympy.Wild('a', exclude=[symbol])
    b = sympy.Wild('b', exclude=[symbol])
    c = sympy.Wild('c', exclude=[symbol])
    match = integrand.match(a / (b * symbol ** 2 + c))

    if not match:
        return

    a, b, c = match[a], match[b], match[c]
    return PiecewiseRule([(ArctanRule(a, b, c, integrand, symbol), sympy.Gt(c / b, 0)),
                          (ArccothRule(a, b, c, integrand, symbol), sympy.And(sympy.Gt(symbol ** 2, -c / b), sympy.Lt(c / b, 0))),
                          (ArctanhRule(a, b, c, integrand, symbol), sympy.And(sympy.Lt(symbol ** 2, -c / b), sympy.Lt(c / b, 0))),
    ], integrand, symbol)
Exemple #25
0
def pinv(A_expr):

    a_wild_expr = sympy.Wild("a_wild")
    assert A_expr == A_expr.replace(sympy.conjugate(a_wild_expr),a_wild_expr)
    A_pinv_expr = A_expr.pinv()
    A_pinv_expr = A_pinv_expr.replace(sympy.conjugate(a_wild_expr),a_wild_expr)
    return A_pinv_expr
Exemple #26
0
    def can_be_applied(self, dim_exprs, variable_context, node_range,
                       orig_edges, dim_index, total_dims):
        # Pattern does not support unions of expressions. TODO: Support
        if len(dim_exprs) > 1: return False
        dexpr = dim_exprs[0]

        # Create a wildcard that excludes current map's parameters
        cst = sympy.Wild('cst', exclude=variable_context[-1])

        # Range case
        if isinstance(dexpr, tuple) and len(dexpr) == 3:
            # Try to match a constant expression for the range
            for rngelem in dexpr:
                if dtypes.isconstant(rngelem):
                    continue

                matches = rngelem.match(cst)
                if matches is None or len(matches) != 1:
                    return False
                if not matches[cst].is_constant():
                    return False

        else:  # Single element case
            # Try to match a constant expression
            if not dtypes.isconstant(dexpr):
                matches = dexpr.match(cst)
                if matches is None or len(matches) != 1:
                    return False
                if not matches[cst].is_constant():
                    return False

        return True
Exemple #27
0
def test_floor_ceil_float_no_optimization():
    x, y = pystencils.fields('x,y: float32[2d]')
    a, b, c = sp.symbols('a, b, c')
    int_symbol = sp.Symbol('int_symbol', integer=True)
    typed_symbol = pystencils.TypedSymbol('typed_symbol',
                                          create_type('float32'))

    assignments = pystencils.AssignmentCollection({
        a:
        sp.floor(1),
        b:
        sp.ceiling(typed_symbol),
        c:
        sp.floor(int_symbol),
        y.center():
        sp.ceiling(x.center()) + sp.floor(x.center())
    })

    assert not typed_symbol.is_integer
    print(sp.simplify(sp.ceiling(typed_symbol)))

    print(assignments)

    wild_floor = sp.floor(sp.Wild('w1'))

    assert not sp.floor(int_symbol).match(wild_floor)
    assert sp.floor(a).match(wild_floor)

    assert assignments.find(wild_floor)
Exemple #28
0
def trig_sindouble_rule(integral):
    integrand, symbol = integral
    a = sympy.Wild('a', exclude=[sympy.sin(2*symbol)])
    match = integrand.match(sympy.sin(2*symbol)*a)
    if match:
        sin_double = 2*sympy.sin(symbol)*sympy.cos(symbol)/sympy.sin(2*symbol)
        return integral_steps(integrand * sin_double, symbol)
Exemple #29
0
    def _modify_cond(self, condition, var, step):
        condition = pystr_to_symbolic(condition.as_string)
        itersym = pystr_to_symbolic(var)
        # Find condition by matching expressions
        end: Optional[sp.Expr] = None
        a = sp.Wild('a')
        op = ''
        match = condition.match(itersym < a)
        if match:
            op = '<'
            end = match[a] - self.count * step
        if end is None:
            match = condition.match(itersym <= a)
            if match:
                op = '<='
                end = match[a] - self.count * step
        if end is None:
            match = condition.match(itersym > a)
            if match:
                op = '>'
                end = match[a] - self.count * step
        if end is None:
            match = condition.match(itersym >= a)
            if match:
                op = '>='
                end = match[a] - self.count * step
        if len(op) == 0:
            raise ValueError('Cannot match loop condition for peeling')

        res = str(itersym) + op + str(end)
        return res
Exemple #30
0
def expr_to_code(expr, symbols_replace, function_replace, display=None):
    import re

    if display is not None:
        print("+ expression to code {}".format(display), end="\r")

    # sympy function to replace into STL C++ functions
    math_to_stl = [(f, sp.Function("std::" + str(f), nargs=1))
                   for f in (sp.sin, sp.cos, sp.exp)]
    math_to_stl.append((sp.sqrt, sp.Function("std::sqrt", nargs=1)))

    # first step: replace symbols
    tmp = expr.subs(symbols_replace)

    # second step: use STL functions
    for old, new in math_to_stl:
        tmp = tmp.subs(old, new)

    # next step: use user-defined functions
    for old, new in function_replace:
        tmp = tmp.replace(old, new)

    # last step: convert all division by 2 by multiplication by 0.5
    a = sp.Wild('a')
    tmp = tmp.replace(a / 2, 0.5 * a, exact=True).evalf()

    # and return a string (where remove every `1.0*` pattern where there is not a number before)
    return re.sub(r"([^0-9])1\.0\*", r"\1", str(tmp))