def genEval(self):
     text = "        bool evaluate(\n"
     args=[]
     for name,v in self.variables:
         if v.is_Matrix:
             args.append("           const Eigen::MatrixXd & %s" % name)
         else:
             args.append("           double %s" % name)
     args.append("           bool evalF=true,bool evalJ=true")
     text += ",\n".join(args) + ") {\n"
     text += "           if (evalF) {\n"
     (interm, expr) = cse(self.function,numbered_symbols("__x"));
     for dummy,exp in interm:
         text += "               double %s = %s;\n" % (str(dummy),ccode(exp))
     for i in range(self.function.rows):
         text += "               F(%d) = %s;\n" % (i,ccode(expr[0][i]))
     text += "           }\n"
     text += "           if (evalJ) {\n"
     (interm, expr) = cse(self.J,numbered_symbols("__x"));
     for dummy,exp in interm:
         text += "               double %s = %s;\n" % (str(dummy),ccode(exp))
     for i in range(self.J.rows):
         for j in range(self.J.cols):
             text += "               J(%d,%d) = %s;\n" % (i,j,ccode(expr[0][i,j]))
     text += "           }\n"
     text += "           return true;\n"
     text += "       }\n"
     return text
示例#2
0
def generate_avx(ex, vnames, idx):

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i] + repr(j) + idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i] + midx[j] + idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i] + idx)

    cse = construct_cse(ex, vnames, idx)
    _v = cse[0]

    print('// Dendro: {{{ ')
    print("// Dendro: original ops: %d " % (cse[1]))

    ee_name = 'DENDRO_'
    ee_syms = numbered_symbols(prefix=ee_name)

    print('// Dendro vectorized code: {{{')
    oper = {'mul': 'dmul', 'add': 'dadd', 'load': '*'}
    prevdefvars = set()
    for (v1, v2) in _v[0]:
        vv = numbered_symbols('v')
        vlist = []
        gen_vector_code(v2, vv, vlist, oper, prevdefvars, idx)
        print('  double ' + repr(v1) + ' = ' + repr(vlist[0]) + ';')
    for i, e in enumerate(_v[1]):
        print("//--")
        vv = numbered_symbols('v')
        vlist = []
        gen_vector_code(e, vv, vlist, oper, prevdefvars, idx)
        #st = '  ' + repr(lname[i]) + '[idx] = ' + repr(vlist[0]) + ';'
        st = '  ' + repr(lname[i]) + " = " + repr(vlist[0]) + ';'
        print(st.replace("'", ""))

    print('// Dendro vectorized code: }}} ')
示例#3
0
def construct_cse(ex, vnames, idx):
    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i] + repr(j) + idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i] + midx[j] + idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i] + idx)

    ee_name = 'DENDRO_'  #''.join(random.choice(string.ascii_uppercase) for _ in range(5))
    ee_syms = numbered_symbols(prefix=ee_name)
    _v = cse(lexp, symbols=ee_syms, optimizations='basic')

    return [_v, count_ops(lexp)]
示例#4
0
文件: systems.py 项目: xushiwei/sympy
def _linear_neq_order1_type3(match_):
    r"""
    System of n first-order nonconstant-coefficient linear homogeneous differential equations

    .. math::
        X' = A(t) X

    where $X$ is the vector of $n$ dependent variables, $t$ is the dependent variable, $X'$
    is the first order differential of $X$ with respect to $t$ and $A(t)$ is a $n \times n$
    coefficient matrix.

    Let us define $B$ as antiderivative of coefficient matrix $A$:

    .. math::
        B(t) = \int A(t) dt

    If the system of ODEs defined above is such that its antiderivative $B(t)$ commutes with
    $A(t)$ itself, then, the solution of the above system is given as:

    .. math::
        X = \exp(B(t)) C

    where $C$ is the vector of constants.

    """
    # Some parts of code is repeated, this needs to be taken care of
    # The constant vector obtained here can be done so in the match
    # function itself.
    eq = match_['eq']
    func = match_['func']
    fc = match_['func_coeff']
    n = len(eq)
    t = list(list(eq[0].atoms(Derivative))[0].atoms(Symbol))[0]
    constants = numbered_symbols(prefix='C', cls=Symbol, start=1)

    # This needs to be modified in future so that fc is only of type Matrix
    M = -fc if type(fc) is Matrix else Matrix(n, n, lambda i,j:-fc[i,func[j],0])

    Cvect = Matrix(list(next(constants) for _ in range(n)))

    # The code in if block will be removed when it is made sure
    # that the code works without the statements in if block.
    if "commutative_antiderivative" not in match_:
        B, is_commuting = _is_commutative_anti_derivative(M, t)

        # This course is subject to change
        if not is_commuting:
            return None

    else:
        B = match_['commutative_antiderivative']

    sol_vector = B.exp() * Cvect

    # The expand_mul is added to handle the solutions so that
    # the exponential terms are collected properly.
    sol_vector = [collect(expand_mul(s), ordered(s.atoms(exp)), exact=True) for s in sol_vector]

    sol_dict = [Eq(func[i], sol_vector[i]) for i in range(n)]
    return sol_dict
示例#5
0
def generate_cuda_code(ex,vname, arrIdx, idx):
    """
    Generate the Cuda code by simplifying the expressions.
    """

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['0', '1','2', '3', '4', '5']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vname+idx[:1]+arrIdx[i]+repr(j)+idx[1:])
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vname+idx[:1]+arrIdx[i]+midx[j]+idx[1:])
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vname+idx[:1]+arrIdx[i]+idx[1:])


    with open("bssneq.cu", 'w') as output_file:
        
        print_n_write('// Dendro: {{{ ', output_file)
        print_n_write('// Dendro: original ops: ' + str(count_ops(lexp)), output_file)


        ee_name = 'DENDRO_' 
        ee_syms = numbered_symbols(prefix=ee_name)
        _v = cse(lexp, symbols=ee_syms, optimizations='basic')
        custom_functions = {'grad': 'grad', 'grad2': 'grad2', 'agrad': 'agrad', 'kograd': 'kograd'}

        rops=0
        print_n_write('// Dendro: printing temp variables', output_file)
        for (v1, v2) in _v[0]:
            print_n_write('double ', output_file, isNewLineEnd=False)
            print_n_write(v2, output_file, assign_to=v1, user_functions=custom_functions, isCExp=True)
            rops = rops + count_ops(v2)

        print_n_write('\n// Dendro: printing variables', output_file)
        for i, e in enumerate(_v[1]):
            print_n_write("//--", output_file)
            print_n_write(e, output_file, assign_to=lname[i], user_functions=custom_functions, isCExp=True)
            rops = rops + count_ops(e)

        print_n_write('// Dendro: reduced ops: ' + str(rops), output_file)
        print_n_write('// Dendro: }}} ', output_file)
示例#6
0
 def iter_numbered_constants(self, start=1, prefix='C') -> Iterable[Symbol]:
     """
     Returns an iterator of constants that do not occur
     in eq already.
     """
     atom_set = self.eq.free_symbols
     func_set = self.eq.atoms(Function)
     if func_set:
         atom_set |= {Symbol(str(f.func)) for f in func_set}
     return numbered_symbols(start=start, prefix=prefix, exclude=atom_set)
示例#7
0
def viete(f, roots=None, *gens, **args):
    """
    Generate Viete's formulas for ``f``.

    Examples
    ========

    >>> from sympy.polys.polyfuncs import viete
    >>> from sympy import symbols

    >>> x, a, b, c, r1, r2 = symbols('x,a:c,r1:3')

    >>> viete(a*x**2 + b*x + c, [r1, r2], x)
    [(r1 + r2, -b/a), (r1*r2, c/a)]

    """
    allowed_flags(args, [])

    if isinstance(roots, Basic):
        gens, roots = (roots, ) + gens, None

    try:
        f, opt = poly_from_expr(f, *gens, **args)
    except PolificationFailed as exc:
        raise ComputationFailed('viete', 1, exc)

    if f.is_multivariate:
        raise MultivariatePolynomialError(
            "multivariate polynomials are not allowed")

    n = f.degree()

    if n < 1:
        raise ValueError(
            "can't derive Viete's formulas for a constant polynomial")

    if roots is None:
        roots = numbered_symbols('r', start=1)

    roots = take(roots, n)

    if n != len(roots):
        raise ValueError("required %s roots, got %s" % (n, len(roots)))

    lc, coeffs = f.LC(), f.all_coeffs()
    result, sign = [], -1

    for i, coeff in enumerate(coeffs[1:]):
        poly = symmetric_poly(i + 1, roots)
        coeff = sign * (coeff / lc)
        result.append((poly, coeff))
        sign = -sign

    return result
示例#8
0
文件: polyfuncs.py 项目: AALEKH/sympy
def viete(f, roots=None, *gens, **args):
    """
    Generate Viete's formulas for ``f``.

    Examples
    ========

    >>> from sympy.polys.polyfuncs import viete
    >>> from sympy import symbols

    >>> x, a, b, c, r1, r2 = symbols('x,a:c,r1:3')

    >>> viete(a*x**2 + b*x + c, [r1, r2], x)
    [(r1 + r2, -b/a), (r1*r2, c/a)]

    """
    allowed_flags(args, [])

    if isinstance(roots, Basic):
        gens, roots = (roots,) + gens, None

    try:
        f, opt = poly_from_expr(f, *gens, **args)
    except PolificationFailed as exc:
        raise ComputationFailed('viete', 1, exc)

    if f.is_multivariate:
        raise MultivariatePolynomialError(
            "multivariate polynomials are not allowed")

    n = f.degree()

    if n < 1:
        raise ValueError(
            "can't derive Viete's formulas for a constant polynomial")

    if roots is None:
        roots = numbered_symbols('r', start=1)

    roots = take(roots, n)

    if n != len(roots):
        raise ValueError("required %s roots, got %s" % (n, len(roots)))

    lc, coeffs = f.LC(), f.all_coeffs()
    result, sign = [], -1

    for i, coeff in enumerate(coeffs[1:]):
        poly = symmetric_poly(i + 1, roots)
        coeff = sign*(coeff/lc)
        result.append((poly, coeff))
        sign = -sign

    return result
示例#9
0
def _linear_neq_order1_type2(match_):
    r"""
    System of n first-order coefficient linear non-homogeneous differential equations

    .. math::
        X' = A X + b(t)

    where $X$ is the vector of $n$ dependent variables, $t$ is the dependent variable, $X'$
    is the first order differential of $X$ with respect to $t$, $A$ is a $n \times n$
    constant coefficient matrix and $b(t)$ is the non-homogeneous term.

    The solution of the above system is:

    .. math::
        X = e^{A t} ( \int e^{- A t} b \,dt + C)

    where $C$ is the vector of constants.

    """
    eq = match_['eq']
    func = match_['func']
    fc = match_['func_coeff']
    b = match_['rhs']

    n = len(eq)
    t = list(list(eq[0].atoms(Derivative))[0].atoms(Symbol))[0]
    constants = numbered_symbols(prefix='C', cls=Symbol, start=1)

    # This needs to be modified in future so that fc is only of type Matrix
    M = -fc if type(fc) is Matrix else Matrix(n, n,
                                              lambda i, j: -fc[i, func[j], 0])

    P, J = matrix_exp_jordan_form(M, t)
    P = simplify(P)
    Cvect = Matrix(list(next(constants) for _ in range(n)))
    sol_vector = P * J * (
        (J.inv() * P.inv() * b).applyfunc(lambda x: Integral(x, t)) + Cvect)

    # sol_vector = sol_vector.applyfunc(_solsimp)

    # Removing the expand_mul can simplify the solutions of the ODEs
    # with symbolic coeffs. To be addressed in the future.
    sol_vector = [
        collect(expand_mul(s), sol_vector.atoms(exp), exact=True)
        for s in sol_vector
    ]

    sol_dict = [Eq(func[i], sol_vector[i]) for i in range(n)]

    # sol_dict = [simpsol(eq) for eq in sol_dict]

    return sol_dict
示例#10
0
 def genEval(self):
     text = "        bool evaluate(\n"
     args=[]
     for name,v,lD in self.variables:
         if isinstance(v, Matrix):
             args.append("           const Eigen::Matrix<double, %d, 1> & %s" % (v.rows, name))
         else:
             args.append("           double %s" % name)
             
     args.append("           Eigen::Matrix<double, %d, 1> * F" % self.function.rows)
     
     for name,v,localDim in self.variables:
         if isinstance(v, Matrix):
             args.append("           Eigen::Matrix<double, %d, %d> * J%s" % (self.J.rows, localDim, name))
         else:
             args.append("           Eigen::Matrix<double, %d, 1> * J%s" % (self.J.rows, name))
     text += ",\n".join(args) + ") {\n"
     text += "           if (F) {\n"
     (interm, expr) = cse(self.function,numbered_symbols("__x"));
     for dummy,exp in interm:
         text += "               double %s = %s;\n" % (str(dummy),ccode(exp))
     for i in range(self.function.rows):
         text += "               (*F)(%d) = %s;\n" % (i,ccode(expr[0][i]))
     text += "           }\n"
     text += "           if (%s) {\n" % " && ".join([ "J" + name for name,v,lD in self.variables ])
     (interm, expr) = cse(self.J,numbered_symbols("__x"));
     for dummy,exp in interm:
         text += "               double %s = %s;\n" % (str(dummy),ccode(exp))
     colBase = 0;
     for name,v,localDim in self.variables:
         for i in range(self.J.rows):
             for j in range(0, localDim):
                 text += "               (*J%s)(%d,%d) = %s;\n" % (name, i,j,ccode(expr[0][i,colBase + j]))
         colBase+=localDim
     text += "           }\n"
     text += "           return true;\n"
     text += "       }\n"
     return text
示例#11
0
def _linear_neq_order1_type1(match_):
    r"""
    System of n first-order constant-coefficient linear homogeneous differential equations

    .. math:: y'_k = a_{k1} y_1 + a_{k2} y_2 +...+ a_{kn} y_n; k = 1,2,...,n

    or that can be written as `\vec{y'} = A . \vec{y}`
    where `\vec{y}` is matrix of `y_k` for `k = 1,2,...n` and `A` is a `n \times n` matrix.

    These equations are equivalent to a first order homogeneous linear
    differential equation.

    The system of ODEs described above has a unique solution, namely:

    .. math ::
        \vec{y} = \exp(A t) C

    where $t$ is the independent variable and $C$ is a vector of n constants. These are constants
    from the integration.

    """
    eq = match_['eq']
    func = match_['func']
    fc = match_['func_coeff']
    n = len(eq)
    t = list(list(eq[0].atoms(Derivative))[0].atoms(Symbol))[0]
    constants = numbered_symbols(prefix='C', cls=Symbol, start=1)

    # This needs to be modified in future so that fc is only of type Matrix
    M = -fc if type(fc) is Matrix else Matrix(n, n,
                                              lambda i, j: -fc[i, func[j], 0])

    P, J = matrix_exp_jordan_form(M, t)
    P = simplify(P)
    Cvect = Matrix(list(next(constants) for _ in range(n)))
    sol_vector = P * (J * Cvect)

    gens = sol_vector.atoms(exp)
    sol_vector = [collect(s, ordered(gens), exact=True) for s in sol_vector]

    sol_dict = [Eq(func[i], sol_vector[i]) for i in range(n)]
    return sol_dict
示例#12
0
    def _get_roots(cls, method, poly, radicals):
        """Return postprocessed roots of specified kind. """
        if not poly.is_univariate:
            raise PolynomialError("only univariate polynomials are allowed")
        # get rid of gen and it's free symbol
        d = Dummy()
        poly = poly.subs(poly.gen, d)
        x = symbols('x')
        # see what others are left and select x or a numbered x
        # that doesn't clash
        free_names = {str(i) for i in poly.free_symbols}
        for x in chain((symbols('x'),), numbered_symbols('x')):
            if x.name not in free_names:
                poly = poly.xreplace({d: x})
                break
        coeff, poly = cls._preprocess_roots(poly)
        roots = []

        for root in getattr(cls, method)(poly):
            roots.append(coeff*cls._postprocess_root(root, radicals))
        return roots
示例#13
0
文件: partfrac.py 项目: msgoff/sympy
def apart_undetermined_coeffs(P, Q):
    """Partial fractions via method of undetermined coefficients. """
    X = numbered_symbols(cls=Dummy)
    partial, symbols = [], []

    _, factors = Q.factor_list()

    for f, k in factors:
        n, q = f.degree(), Q

        for i in range(1, k + 1):
            coeffs, q = take(X, n), q.quo(f)
            partial.append((coeffs, q, f, i))
            symbols.extend(coeffs)

    dom = Q.get_domain().inject(*symbols)
    F = Poly(0, Q.gen, domain=dom)

    for i, (coeffs, q, f, k) in enumerate(partial):
        h = Poly(coeffs, Q.gen, domain=dom)
        partial[i] = (h, f, k)
        q = q.set_domain(dom)
        F += h * q

    system, result = [], S.Zero

    for (k,), coeff in F.terms():
        system.append(coeff - P.nth(k))

    from sympy.solvers import solve

    solution = solve(system, symbols)

    for h, f, k in partial:
        h = h.as_expr().subs(solution)
        result += h / f.as_expr() ** k

    return result
示例#14
0
文件: partfrac.py 项目: mattpap/sympy
def apart_undetermined_coeffs(P, Q):
    """Partial fractions via method of undetermined coefficients. """
    X = numbered_symbols(cls=Dummy)
    partial, symbols = [], []

    _, factors = Q.factor_list()

    for f, k in factors:
        n, q = f.degree(), Q

        for i in xrange(1, k + 1):
            coeffs, q = take(X, n), q.quo(f)
            partial.append((coeffs, q, f, i))
            symbols.extend(coeffs)

    dom = Q.get_domain().inject(*symbols)
    F = Poly(0, Q.gen, domain=dom)

    for i, (coeffs, q, f, k) in enumerate(partial):
        h = Poly(coeffs, Q.gen, domain=dom)
        partial[i] = (h, f, k)
        q = q.set_domain(dom)
        F += h * q

    system, result = [], S(0)

    for (k,), coeff in F.terms():
        system.append(coeff - P.nth(k))

    from sympy.solvers import solve

    solution = solve(system, symbols)

    for h, f, k in partial:
        h = h.as_expr().subs(solution)
        result += h / f.as_expr() ** k

    return result
示例#15
0
def generate_cpu(ex, vnames, idx):
    """
    Generate the C++ code by simplifying the expressions.
    """
    # print(ex)

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i] + repr(j) + idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i] + midx[j] + idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i] + idx)

    cse = construct_cse(ex, vnames, idx)
    _v = cse[0]

    print("// Dendro: {{{ ")
    print("// Dendro: original ops: %d " % (cse[1]))

    ee_name = 'DENDRO_'
    ee_syms = numbered_symbols(prefix=ee_name)

    custom_functions = {
        'grad': 'grad',
        'grad2': 'grad2',
        'agrad': 'agrad',
        'kograd': 'kograd'
    }
    rops = 0
    print('// Dendro: printing temp variables')
    for (v1, v2) in _v[0]:
        print('double ', end='')
        print(
            change_deriv_names(
                ccode(v2, assign_to=v1, user_functions=custom_functions)))
        rops = rops + count_ops(v2)

    print()
    print('// Dendro: printing variables')
    for i, e in enumerate(_v[1]):
        print("//--")
        print(
            change_deriv_names(
                ccode(e, assign_to=lname[i], user_functions=custom_functions)))
        rops = rops + count_ops(e)

    print('// Dendro: reduced ops: %d' % (rops))
    print('// Dendro: }}} ')
示例#16
0
def minimal_polynomial(ex, x=None, **args):
    """
    Computes the minimal polynomial of an algebraic number.

    Parameters
    ==========

    ex : algebraic number expression

    x : indipendent variable of the minimal polynomial

    Options
    =======

    compose : if ``True`` _minpoly1`` is used, else the ``groebner`` algorithm

    polys : if ``True`` returns a ``Poly`` object

    Notes
    =====

    By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex``
    are computed, then the arithmetic operations on them are performed using the resultant
    and factorization.
    If ``compose=False``, a bottom-up algorithm is used with ``groebner``.
    The default algorithm stalls less frequently.

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, solve
    >>> from sympy.abc import x

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1
    >>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
    x**3 + x + 3

    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_multinomial
    from sympy.core.basic import preorder_traversal

    compose = args.get('compose', True)
    polys = args.get('polys', False)
    ex = sympify(ex)
    for expr in preorder_traversal(ex):
        if expr.is_AlgebraicNumber:
            compose = False
            break

    if ex.is_AlgebraicNumber:
        compose = False

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly

    if compose:
        result = _minpoly1(ex, x)
        result = result.primitive()[1]
        c = result.coeff(x**degree(result, x))
        if c < 0:
            result = expand_mul(-result)
            c = -c
        return cls(result, x, field=True) if polys else result

    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    def update_mapping(ex, exp, base=None):
        a = generator.next()
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[ bottom_up_scan(g) for g in ex.args ])
        elif ex.is_Mul:
            return Mul(*[ bottom_up_scan(g) for g in ex.args ])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base**(-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (
                        ex.base**ex.exp.p).expand(), Rational(1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1/exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1/ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            a = []
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    inverted = False
    ex = expand_multinomial(ex)
    if ex.is_AlgebraicNumber:
        if not polys:
            return ex.minpoly.as_expr(x)
        else:
            return ex.minpoly.replace(x)
    elif ex.is_Rational:
        result = ex.q*x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex**-1
        res = None
        if ex.is_Pow and (1/ex.exp).is_Integer:
            n = 1/ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + mapping.values()
            G = groebner(F, symbols.values() + [x], order='lex')

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex)
    if inverted:
        result = _invertx(result, x)
        if result.coeff(x**degree(result, x)) < 0:
            result = expand_mul(-result)
    if polys:
        return cls(result, x, field=True)
    else:
        return result
示例#17
0
def primitive_element(extension, x=None, **args):
    """Construct a common number field for all extensions. """
    if not extension:
        raise ValueError("can't compute primitive element for empty extension")

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly
    if not args.get('ex', False):
        extension = [ AlgebraicNumber(ext, gen=x) for ext in extension ]

        g, coeffs = extension[0].minpoly.replace(x), [1]

        for ext in extension[1:]:
            s, _, g = sqf_norm(g, x, extension=ext)
            coeffs = [ s*c for c in coeffs ] + [1]

        if not args.get('polys', False):
            return g.as_expr(), coeffs
        else:
            return cls(g), coeffs

    generator = numbered_symbols('y', cls=Dummy)

    F, Y = [], []

    for ext in extension:
        y = next(generator)

        if ext.is_Poly:
            if ext.is_univariate:
                f = ext.as_expr(y)
            else:
                raise ValueError("expected minimal polynomial, got %s" % ext)
        else:
            f = minpoly(ext, y)

        F.append(f)
        Y.append(y)

    coeffs_generator = args.get('coeffs', _coeffs_generator)

    for coeffs in coeffs_generator(len(Y)):
        f = x - sum([ c*y for c, y in zip(coeffs, Y)])
        G = groebner(F + [f], Y + [x], order='lex', field=True)

        H, g = G[:-1], cls(G[-1], x, domain='QQ')

        for i, (h, y) in enumerate(zip(H, Y)):
            try:
                H[i] = Poly(y - h, x,
                            domain='QQ').all_coeffs()  # XXX: composite=False
            except CoercionFailed:  # pragma: no cover
                break  # G is not a triangular set
        else:
            break
    else:  # pragma: no cover
        raise RuntimeError("run out of coefficient configurations")

    _, g = g.clear_denoms()

    if not args.get('polys', False):
        return g.as_expr(), coeffs, H
    else:
        return g, coeffs, H
示例#18
0
def _minpoly_groebner(ex, x, cls):
    """
    Computes the minimal polynomial of an algebraic number
    using Groebner bases

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, Rational
    >>> from sympy.abc import x
    >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=False)
    x**2 - 2*x - 1

    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_multinomial

    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    def update_mapping(ex, exp, base=None):
        a = next(generator)
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[ bottom_up_scan(g) for g in ex.args ])
        elif ex.is_Mul:
            return Mul(*[ bottom_up_scan(g) for g in ex.args ])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base**(-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (
                        ex.base**ex.exp.p).expand(), Rational(1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1/exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1/ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            a = []
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    inverted = False
    ex = expand_multinomial(ex)
    if ex.is_AlgebraicNumber:
        return ex.minpoly.as_expr(x)
    elif ex.is_Rational:
        result = ex.q*x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex**-1
        res = None
        if ex.is_Pow and (1/ex.exp).is_Integer:
            n = 1/ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + list(mapping.values())
            G = groebner(F, list(symbols.values()) + [x], order='lex')

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex)
    if inverted:
        result = _invertx(result, x)
        if result.coeff(x**degree(result, x)) < 0:
            result = expand_mul(-result)

    return result
示例#19
0
def primitive_element(extension, x=None, **args):
    """Construct a common number field for all extensions. """
    if not extension:
        raise ValueError("can't compute primitive element for empty extension")

    if x is not None:
        x = sympify(x)
    else:
        x = Dummy('x')

    if not args.get('ex', False):
        extension = [AlgebraicNumber(ext, gen=x) for ext in extension]

        g, coeffs = extension[0].minpoly, [1]

        for ext in extension[1:]:
            s, _, g = sqf_norm(g, x, extension=ext)
            coeffs = [s * c for c in coeffs] + [1]

        if not args.get('polys', False):
            return g.as_basic(), coeffs
        else:
            return g, coeffs

    generator = numbered_symbols('y', cls=Dummy)

    F, Y = [], []

    for ext in extension:
        y = generator.next()

        if ext.is_Poly:
            if ext.is_univariate:
                f = ext.as_basic(y)
            else:
                raise ValueError("expected minimal polynomial, got %s" % ext)
        else:
            f = minpoly(ext, y)

        F.append(f)
        Y.append(y)

    coeffs_generator = args.get('coeffs', _coeffs_generator)

    for coeffs in coeffs_generator(len(Y)):
        f = x - sum([c * y for c, y in zip(coeffs, Y)])
        G = groebner(F + [f], Y + [x], order='lex')

        H, g = G[:-1], Poly(G[-1], x, domain='QQ')

        for i, (h, y) in enumerate(zip(H, Y)):
            try:
                H[i] = Poly(y - h, x, domain='QQ').all_coeffs()
            except CoercionFailed:  # pragma: no cover
                break  # G is not a triangular set
        else:
            break
    else:  # pragma: no cover
        raise RuntimeError("run out of coefficient configurations")

    _, g = g.ground_to_ring()

    if not args.get('polys', False):
        return g.as_basic(), coeffs, H
    else:
        return g, coeffs, H
示例#20
0
def _minpoly_groebner(ex, x, cls):
    """
    Computes the minimal polynomial of an algebraic number
    using Groebner bases

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, Rational
    >>> from sympy.abc import x
    >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=False)
    x**2 - 2*x - 1

    """

    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols = {}, {}

    def update_mapping(ex, exp, base=None):
        a = next(generator)
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        """
        Transform a given algebraic expression *ex* into a multivariate
        polynomial, by introducing fresh variables with defining equations.

        Explanation
        ===========

        The critical elements of the algebraic expression *ex* are root
        extractions, instances of :py:class:`~.AlgebraicNumber`, and negative
        powers.

        When we encounter a root extraction or an :py:class:`~.AlgebraicNumber`
        we replace this expression with a fresh variable ``a_i``, and record
        the defining polynomial for ``a_i``. For example, if ``a_0**(1/3)``
        occurs, we will replace it with ``a_1``, and record the new defining
        polynomial ``a_1**3 - a_0``.

        When we encounter a negative power we transform it into a positive
        power by algebraically inverting the base. This means computing the
        minimal polynomial in ``x`` for the base, inverting ``x`` modulo this
        poly (which generates a new polynomial) and then substituting the
        original base expression for ``x`` in this last polynomial.

        We return the transformed expression, and we record the defining
        equations for new symbols using the ``update_mapping()`` function.

        """
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0:
                    minpoly_base = _minpoly_groebner(ex.base, x, cls)
                    inverse = invert(x, minpoly_base).as_expr()
                    base_inv = inverse.subs(x, ex.base).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base_inv)
                    else:
                        ex = base_inv**(-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (ex.base**ex.exp.p).expand(), Rational(
                        1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    if exp.is_Integer:
                        return expr.expand()
                    else:
                        return update_mapping(expr, 1 / exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex not in mapping:
                return update_mapping(ex, ex.minpoly_of_element())
            else:
                return symbols[ex]

        raise NotAlgebraic("%s does not seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1 / ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    inverted = False
    ex = expand_multinomial(ex)
    if ex.is_AlgebraicNumber:
        return ex.minpoly_of_element().as_expr(x)
    elif ex.is_Rational:
        result = ex.q * x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex**-1
        res = None
        if ex.is_Pow and (1 / ex.exp).is_Integer:
            n = 1 / ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + list(mapping.values())
            G = groebner(F, list(symbols.values()) + [x], order='lex')

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex)
    if inverted:
        result = _invertx(result, x)
        if result.coeff(x**degree(result, x)) < 0:
            result = expand_mul(-result)

    return result
示例#21
0
def _solve_undetermined_coefficients(eq, func, order, match, trialset):
    r"""
    Helper function for the method of undetermined coefficients.

    See the
    :py:meth:`~sympy.solvers.ode.single.NthLinearConstantCoeffUndeterminedCoefficients`
    docstring for more information on this method.

    The parameter ``trialset`` is the set of trial functions as returned by
    ``_undetermined_coefficients_match()['trialset']``.

    The parameter ``match`` should be a dictionary that has the following
    keys:

    ``list``
    A list of solutions to the homogeneous equation.

    ``sol``
    The general solution.

    """
    r = match
    coeffs = numbered_symbols('a', cls=Dummy)
    coefflist = []
    gensols = r['list']
    gsol = r['sol']
    f = func.func
    x = func.args[0]

    if len(gensols) != order:
        raise NotImplementedError(
            "Cannot find " + str(order) +
            " solutions to the homogeneous equation necessary to apply" +
            " undetermined coefficients to " + str(eq) +
            " (number of terms != order)")

    trialfunc = 0
    for i in trialset:
        c = next(coeffs)
        coefflist.append(c)
        trialfunc += c * i

    eqs = sub_func_doit(eq, f(x), trialfunc)

    coeffsdict = dict(list(zip(trialset, [0] * (len(trialset) + 1))))

    eqs = _mexpand(eqs)

    for i in Add.make_args(eqs):
        s = separatevars(i, dict=True, symbols=[x])
        if coeffsdict.get(s[x]):
            coeffsdict[s[x]] += s['coeff']
        else:
            coeffsdict[s[x]] = s['coeff']

    coeffvals = solve(list(coeffsdict.values()), coefflist)

    if not coeffvals:
        raise NotImplementedError("Could not solve `%s` using the "
                                  "method of undetermined coefficients "
                                  "(unable to solve for coefficients)." % eq)

    psol = trialfunc.subs(coeffvals)

    return Eq(f(x), gsol.rhs + psol)
示例#22
0
    try:
        f, opt = poly_from_expr(f, *gens, **args)
    except PolificationFailed, exc:
        raise ComputationFailed("viete", 1, exc)

    if f.is_multivariate:
        raise MultivariatePolynomialError("multivariate polynomials are not allowed")

    n = f.degree()

    if n < 1:
        raise ValueError("can't derive Viete's formulas for a constant polynomial")

    if roots is None:
        roots = numbered_symbols("r", start=1)

    roots = take(roots, n)

    if n != len(roots):
        raise ValueError("required %s roots, got %s" % (n, len(roots)))

    lc, coeffs = f.LC(), f.all_coeffs()
    result, sign = [], -1

    for i, coeff in enumerate(coeffs[1:]):
        poly = symmetric_poly(i + 1, roots)
        coeff = sign * (coeff / lc)
        result.append((poly, coeff))
        sign = -sign
示例#23
0
 def default(cls):
     return numbered_symbols('s', start=1)
示例#24
0
文件: dendro.py 项目: vmiheer/SymPyGR
def generate(ex, vnames, idx):
    """
    Generate the C++ code by simplifying the expressions.
    """
    # print(ex)

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i]+repr(j)+idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i]+midx[j]+idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i]+idx)

    # print(num_e)
    # print(len(lname))

    print('// Dendro: {{{ ')
    print('// Dendro: original ops: ', count_ops(lexp))

    # print("--------------------------------------------------------")
    # print("Now trying Common Subexpression Detection and Collection")
    # print("--------------------------------------------------------")

    # Common Subexpression Detection and Collection
    # for i in range(len(ex)):
    #     # print("--------------------------------------------------------")
    #     # print(ex[i])
    #     # print("--------------------------------------------------------")
    #     ee_name = ''.join(random.choice(string.ascii_uppercase) for _ in range(5))
    #     ee_syms = numbered_symbols(prefix=ee_name)
    #     _v = cse(ex[i],symbols=ee_syms)
    #     # print(type(_v))
    #     for (v1,v2) in _v[0]:
    #         print("double %s = %s;" % (v1, v2))
    #     print("%s = %s" % (vnames[i], _v[1][0]))

    #mex = Matrix(ex)
    ee_name = 'DENDRO_' #''.join(random.choice(string.ascii_uppercase) for _ in range(5))
    ee_syms = numbered_symbols(prefix=ee_name)
    _v = cse(lexp, symbols=ee_syms, optimizations='basic')

    custom_functions = {'grad': 'grad', 'grad2': 'grad2', 'agrad': 'agrad', 'kograd': 'kograd'}

    rops=0
    print('// Dendro: printing temp variables')
    for (v1, v2) in _v[0]:
        # print("double %s = %s;" % (v1, v2)) # replace_pow(v2)))
        print('double ', end='')
        #print_ccode(v2, assign_to=v1, user_functions=custom_functions)
        print(change_deriv_names(ccode(v2, assign_to=v1, user_functions=custom_functions)))
        rops = rops + count_ops(v2)

    print()
    print('// Dendro: printing variables')
    for i, e in enumerate(_v[1]):
        print("//--")
        # print("%s = %s;" % (lname[i], e)) # replace_pow(e)))
        #f = open(str(lname[i])+'.gv','w')
        #print(dotprint(e), file=f)
        #f.close()
        #print_ccode(e, assign_to=lname[i], user_functions=custom_functions)
        print(change_deriv_names(ccode(e, assign_to=lname[i], user_functions=custom_functions)))
        rops = rops + count_ops(e)

    print('// Dendro: reduced ops: ', rops)
    print('// Dendro: }}} ')
示例#25
0
    try:
        f, opt = poly_from_expr(f, *gens, **args)
    except PolificationFailed, exc:
        raise ComputationFailed('viete', 1, exc)

    if f.is_multivariate:
        raise MultivariatePolynomialError("multivariate polynomials are not allowed")

    n = f.degree()

    if n < 1:
        raise ValueError("can't derive Viete's formulas for a constant polynomial")

    if roots is None:
        roots = numbered_symbols('r', start=1)

    roots = take(roots, n)

    if n != len(roots):
        raise ValueError("required %s roots, got %s" % (n, len(roots)))

    lc, coeffs = f.LC(), f.all_coeffs()
    result, sign = [], -1

    for i, coeff in enumerate(coeffs[1:]):
        poly = symmetric_poly(i+1, roots)
        coeff = sign*(coeff/lc)
        result.append((poly, coeff))
        sign = -sign
示例#26
0
def minimal_polynomial(ex, x=None, **args):
    """
    Computes the minimal polynomial of an algebraic number.

    Parameters
    ==========

    ex : algebraic number expression

    x : indipendent variable of the minimal polynomial

    Options
    =======

    compose : if ``True`` _minpoly1`` is used, else the ``groebner`` algorithm

    polys : if ``True`` returns a ``Poly`` object

    Notes
    =====

    By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex``
    are computed, then the arithmetic operations on them are performed using the resultant
    and factorization.
    If ``compose=False``, a bottom-up algorithm is used with ``groebner``.
    The default algorithm stalls less frequently.

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, solve
    >>> from sympy.abc import x

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1
    >>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
    x**3 + x + 3

    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_multinomial
    from sympy.core.basic import preorder_traversal

    compose = args.get('compose', True)
    polys = args.get('polys', False)
    ex = sympify(ex)
    for expr in preorder_traversal(ex):
        if expr.is_AlgebraicNumber:
            compose = False
            break

    if ex.is_AlgebraicNumber:
        compose = False

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly

    if compose:
        result = _minpoly1(ex, x)
        result = result.primitive()[1]
        c = result.coeff(x**degree(result, x))
        if c < 0:
            result = expand_mul(-result)
            c = -c
        return cls(result, x, field=True) if polys else result

    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    def update_mapping(ex, exp, base=None):
        a = generator.next()
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base**(-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (ex.base**ex.exp.p).expand(), Rational(
                        1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1 / exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1 / ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            a = []
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    inverted = False
    ex = expand_multinomial(ex)
    if ex.is_AlgebraicNumber:
        if not polys:
            return ex.minpoly.as_expr(x)
        else:
            return ex.minpoly.replace(x)
    elif ex.is_Rational:
        result = ex.q * x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex**-1
        res = None
        if ex.is_Pow and (1 / ex.exp).is_Integer:
            n = 1 / ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + mapping.values()
            G = groebner(F, symbols.values() + [x], order='lex')

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex)
    if inverted:
        result = _invertx(result, x)
        if result.coeff(x**degree(result, x)) < 0:
            result = expand_mul(-result)
    if polys:
        return cls(result, x, field=True)
    else:
        return result
示例#27
0
def minimal_polynomial(ex, x=None, **args):
    """
    Computes the minimal polynomial of an algebraic number.

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt
    >>> from sympy.abc import x

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1

    """
    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    ex = sympify(ex)

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly

    def update_mapping(ex, exp, base=None):
        a = generator.next()
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base**(-ex.exp)

                if not ex.exp.is_Integer:
                    base, exp = (ex.base**ex.exp.p).expand(), Rational(
                        1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp

                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1 / exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    polys = args.get('polys', False)

    if ex.is_AlgebraicNumber:
        if not polys:
            return ex.minpoly.as_expr(x)
        else:
            return ex.minpoly.replace(x)
    elif ex.is_Rational:
        result = ex.q * x - ex.p
    else:
        F = [x - bottom_up_scan(ex)] + mapping.values()
        G = groebner(F, symbols.values() + [x], order='lex')

        _, factors = factor_list(G[-1])

        if len(factors) == 1:
            ((result, _), ) = factors
        else:
            for result, _ in factors:
                if result.subs(x, ex).evalf(chop=True) == 0:
                    break
            else:  # pragma: no cover
                raise NotImplementedError(
                    "multiple candidates for the minimal polynomial of %s" %
                    ex)

    if polys:
        return cls(result, x, field=True)
    else:
        return result
示例#28
0
def generate_fpcore(ex, vnames, idx):
    """
    Generate the FPCore code, 
    """
    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i] + repr(j) + idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i] + midx[j] + idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i] + idx)

    cse = construct_cse(ex, vnames, idx)
    _v = cse[0]

    #print("// Dendro: {{{ ")
    #print("// Dendro: original ops: %d " %(cse[1]))

    ee_name = 'DENDRO_'
    ee_syms = numbered_symbols(prefix=ee_name)

    custom_functions = {
        'grad': 'grad',
        'grad2': 'grad2',
        'agrad': 'agrad',
        'kograd': 'kograd'
    }
    rops = 0

    #re_symbol=regex.compile(r"Symbol\('[a-z,A-Z,_]+[0-9,\[pp\],\[0-9\]]*'\)")
    re_symbol = regex.compile(r"Symbol\('([a-z,A-Z,0-9,_,\[\]]*)'\)")
    re_integer = regex.compile(r"Integer\(([\-,0-9]+)\)")
    re_float = regex.compile(r"Float\('([\-,0-9]*\.[0-9]*)'\s prec=([0-9]+)\)")
    re_grad = regex.compile(
        r"Function\('([a-z]+[0-9]*)'\)\(Integer\(([0-9]+)\),\s*Symbol\('([a-z,A-Z]+[0-9]*\[pp\])'\)\)"
    )

    subs_functions = {
        "Add(": "(+ ",
        "Integer(-1)": "-1 ",
        "Mul(": "(* ",
        "Div(": "(/ ",
        "Pow(": "(pow ",
        "Rational(": "(/ "
    }

    #print('// Dendro: printing temp variables')
    tmp_vars = list()
    for (v1, v2) in _v[0]:
        tmp_vars.append(str(v1))
        sym_sub = dict()
        srep = srepr(v2)
        #print(srep)

        res = re_grad.findall(srep)
        for g in res:
            s = "Function('%s')(Integer(%s), Symbol('%s'))" % (g[0], g[1],
                                                               g[2])
            #print(s)
            ss = "Symbol('%s')" % (g[0] + "_" + g[1] + "_" + g[2])
            srep = srep.replace(s, ss)

        srep = srep.replace(",", " ")
        #print(srep)

        res = re_symbol.findall(srep)
        inp_params = list()
        #print(res)
        for s in res:
            ss = s.replace("[pp]", "")
            for index in range(0, 6):
                ss = ss.replace("[" + str(index) + "]", str(index))
            inp_params.append(ss)
            tmp_vars.append(ss)
            sym_sub["Symbol(\'%s\')" % (s)] = ss

        int_sub = dict()
        res = re_integer.findall(srep)
        for s in res:
            int_sub["Integer(%s)" % (s)] = s

        float_sub = dict()
        res = re_float.findall(srep)

        for s in res:
            float_sub["Float('%s'  prec=%s)" % (s[0], s[1])] = s[0]

        for key, val in sym_sub.items():
            #print("{%s: %s} "%(key,val))
            srep = srep.replace(key, val)

        for key, val in int_sub.items():
            #print("{%s: %s} "%(key,val))
            srep = srep.replace(key, val)

        for key, val in float_sub.items():
            #print("{%s: %s} "%(key,val))
            srep = srep.replace(key, val)

        for key, val in subs_functions.items():
            srep = srep.replace(key, val)

        print("(FPCore (%s)" % (" ".join(inp_params)))
        print("\t%s" % (srep))
        print(")\n")

    #print(tmp_vars)
    tmp_vars.clear()
    tmp_vars = list()
    for i, e in enumerate(_v[1]):
        srep = srepr(e)

        res = re_grad.findall(srep)
        for g in res:
            s = "Function('%s')(Integer(%s), Symbol('%s'))" % (g[0], g[1],
                                                               g[2])
            #print(s)
            ss = "Symbol('%s')" % (g[0] + "_" + g[1] + "_" + g[2])
            srep = srep.replace(s, ss)

        srep = srep.replace(",", " ")

        res = re_symbol.findall(srep)
        inp_params = list()
        #print(res)
        for s in res:
            ss = s.replace("[pp]", "")
            for index in range(0, 6):
                ss = ss.replace("[" + str(index) + "]", str(index))
            inp_params.append(ss)
            tmp_vars.append(ss)
            sym_sub["Symbol(\'%s\')" % (s)] = ss

        int_sub = dict()
        res = re_integer.findall(srep)
        for s in res:
            int_sub["Integer(%s)" % (s)] = s

        float_sub = dict()
        res = re_float.findall(srep)

        for s in res:
            float_sub["Float('%s'  prec=%s)" % (s[0], s[1])] = s[0]

        for key, val in sym_sub.items():
            #print("{%s: %s} "%(key,val))
            srep = srep.replace(key, val)

        for key, val in int_sub.items():
            #print("{%s: %s} "%(key,val))
            srep = srep.replace(key, val)

        for key, val in float_sub.items():
            #print("{%s: %s} "%(key,val))
            srep = srep.replace(key, val)

        for key, val in subs_functions.items():
            srep = srep.replace(key, val)

        tmp_vars = list(set(tmp_vars))
        print("(FPCore (%s)" % (" ".join(tmp_vars)))
        print("\t%s" % (srep))
        print(")")
示例#29
0
def minimal_polynomial(ex, x=None, **args):
    """
    Computes the minimal polynomial of an algebraic number.

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt
    >>> from sympy.abc import x

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1

    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_mul
    from sympy.simplify.simplify import _is_sum_surds

    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    ex = sympify(ex)

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly

    def update_mapping(ex, exp, base=None):
        a = generator.next()
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base**(-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (ex.base**ex.exp.p).expand(), Rational(
                        1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1 / exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1 / ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            a = []
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    polys = args.get('polys', False)
    prec = args.pop('prec', 10)

    inverted = False
    if ex.is_AlgebraicNumber:
        if not polys:
            return ex.minpoly.as_expr(x)
        else:
            return ex.minpoly.replace(x)
    elif ex.is_Rational:
        result = ex.q * x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex**-1
        res = None
        if ex.is_Pow and (1 / ex.exp).is_Integer:
            n = 1 / ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x, prec)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x, prec)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + mapping.values()
            G = groebner(F, symbols.values() + [x], order='lex')

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex, prec)
            if result is None:
                raise NotImplementedError(
                    "multiple candidates for the minimal polynomial of %s" %
                    ex)
    if inverted:
        result = expand_mul(x**degree(result) * result.subs(x, 1 / x))
        if result.coeff(x**degree(result)) < 0:
            result = expand_mul(-result)
    if polys:
        return cls(result, x, field=True)
    else:
        return result
示例#30
0
def _minpoly_groebner(ex, x, cls):
    """
    Computes the minimal polynomial of an algebraic number
    using Groebner bases

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt, Rational
    >>> from sympy.abc import x
    >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=False)
    x**2 - 2*x - 1

    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_multinomial

    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols = {}, {}

    def update_mapping(ex, exp, base=None):
        a = next(generator)
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0:
                    minpoly_base = _minpoly_groebner(ex.base, x, cls)
                    inverse = invert(x, minpoly_base).as_expr()
                    base_inv = inverse.subs(x, ex.base).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base_inv)
                    else:
                        ex = base_inv**(-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (ex.base**ex.exp.p).expand(), Rational(
                        1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1 / exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1 / ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    inverted = False
    ex = expand_multinomial(ex)
    if ex.is_AlgebraicNumber:
        return ex.minpoly.as_expr(x)
    elif ex.is_Rational:
        result = ex.q * x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex**-1
        res = None
        if ex.is_Pow and (1 / ex.exp).is_Integer:
            n = 1 / ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + list(mapping.values())
            G = groebner(F, list(symbols.values()) + [x], order='lex')

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex)
    if inverted:
        result = _invertx(result, x)
        if result.coeff(x**degree(result, x)) < 0:
            result = expand_mul(-result)

    return result
示例#31
0
def generate(ex, vnames, idx):
    """
    Generate the C++ code by simplifying the expressions.
    """
    # print(ex)

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i]+repr(j)+idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i]+midx[j]+idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i]+idx)

    # print(num_e)
    # print(len(lname))
    with open("bssn.cpp", 'w') as output_file:
        
        print_n_write('// Dendro: {{{ ', output_file)
        print_n_write('// Dendro: original ops: ' + str(count_ops(lexp)), output_file)

        # print("--------------------------------------------------------")
        # print("Now trying Common Subexpression Detection and Collection")
        # print("--------------------------------------------------------")

        # Common Subexpression Detection and Collection
        # for i in range(len(ex)):
        #     # print("--------------------------------------------------------")
        #     # print(ex[i])
        #     # print("--------------------------------------------------------")
        #     ee_name = ''.join(random.choice(string.ascii_uppercase) for _ in range(5))
        #     ee_syms = numbered_symbols(prefix=ee_name)
        #     _v = cse(ex[i],symbols=ee_syms)
        #     # print(type(_v))
        #     for (v1,v2) in _v[0]:
        #         print("double %s = %s;" % (v1, v2))
        #     print("%s = %s" % (vnames[i], _v[1][0]))

        #mex = Matrix(ex)
        ee_name = 'DENDRO_' #''.join(random.choice(string.ascii_uppercase) for _ in range(5))
        ee_syms = numbered_symbols(prefix=ee_name)
        _v = cse(lexp, symbols=ee_syms, optimizations='basic')
        custom_functions = {'grad': 'grad', 'grad2': 'grad2', 'agrad': 'agrad', 'kograd': 'kograd'}

        rops=0
        print_n_write('// Dendro: printing temp variables', output_file)
        for (v1, v2) in _v[0]:
            # print("double %s = %s;" % (v1, v2)) # replace_pow(v2)))
            print_n_write('double ', output_file, isNewLineEnd=False)
            print_n_write(v2, output_file, assign_to=v1, user_functions=custom_functions, isCExp=True)
            rops = rops + count_ops(v2)

        print_n_write('\n// Dendro: printing variables', output_file)
        for i, e in enumerate(_v[1]):
            print_n_write("//--", output_file)
            # print("%s = %s;" % (lname[i], e)) # replace_pow(e)))
            print_n_write(e, output_file, assign_to=lname[i], user_functions=custom_functions, isCExp=True)
            rops = rops + count_ops(e)

        print_n_write('// Dendro: reduced ops: ' + str(rops), output_file)
        print_n_write('// Dendro: }}} ', output_file)

        print_n_write('// Dendro vectorized code: {{{', output_file)
        oper = {'mul': 'dmul', 'add': 'dadd', 'load': '*'}
        prevdefvars = set()
        for (v1, v2) in _v[0]:
            vv = numbered_symbols('v')
            vlist = []
            gen_vector_code(v2, vv, vlist, oper, prevdefvars, idx, output_file)
            print_n_write('  double ' + repr(v1) + ' = ' + repr(vlist[0]) + ';', output_file)
        for i, e in enumerate(_v[1]):
            print_n_write("//--", output_file)
            vv = numbered_symbols('v')
            vlist = []
            gen_vector_code(e, vv, vlist, oper, prevdefvars, idx, output_file)
            #st = '  ' + repr(lname[i]) + '[idx] = ' + repr(vlist[0]) + ';'
            st = '  ' + repr(lname[i]) + " = " + repr(vlist[0]) + ';'
            print_n_write(st.replace("'",""), output_file)

        print_n_write('// Dendro vectorized code: }}} ', output_file)
示例#32
0
def primitive_element(extension, x=None, **args):
    """Construct a common number field for all extensions. """
    if not extension:
        raise ValueError("can't compute primitive element for empty extension")

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly

    if not args.get('ex', False):
        gen, coeffs = extension[0], [1]
        # XXX when minimal_polynomial is extended to work
        # with AlgebraicNumbers this test can be removed
        if isinstance(gen, AlgebraicNumber):
            g = gen.minpoly.replace(x)
        else:
            g = minimal_polynomial(gen, x, polys=True)
        for ext in extension[1:]:
            _, factors = factor_list(g, extension=ext)
            g = _choose_factor(factors, x, gen)
            s, _, g = g.sqf_norm()
            gen += s * ext
            coeffs.append(s)

        if not args.get('polys', False):
            return g.as_expr(), coeffs
        else:
            return cls(g), coeffs

    generator = numbered_symbols('y', cls=Dummy)

    F, Y = [], []

    for ext in extension:
        y = next(generator)

        if ext.is_Poly:
            if ext.is_univariate:
                f = ext.as_expr(y)
            else:
                raise ValueError("expected minimal polynomial, got %s" % ext)
        else:
            f = minpoly(ext, y)

        F.append(f)
        Y.append(y)

    coeffs_generator = args.get('coeffs', _coeffs_generator)

    for coeffs in coeffs_generator(len(Y)):
        f = x - sum([c * y for c, y in zip(coeffs, Y)])
        G = groebner(F + [f], Y + [x], order='lex', field=True)

        H, g = G[:-1], cls(G[-1], x, domain='QQ')

        for i, (h, y) in enumerate(zip(H, Y)):
            try:
                H[i] = Poly(y - h, x,
                            domain='QQ').all_coeffs()  # XXX: composite=False
            except CoercionFailed:  # pragma: no cover
                break  # G is not a triangular set
        else:
            break
    else:  # pragma: no cover
        raise RuntimeError("run out of coefficient configurations")

    _, g = g.clear_denoms()

    if not args.get('polys', False):
        return g.as_expr(), coeffs, H
    else:
        return g, coeffs, H
示例#33
0
def convert_to_symbolic_indices(seq, start=None, gen=None, qubit_map=None):
    """Returns the circuit with symbolic indices and the
    dictionary mapping symbolic indices to real indices.

    The mapping is 1 to 1 and onto (bijective).

    Parameters
    ==========
    seq : tuple, Gate/Integer/tuple or Mul
        A tuple of Gate, Integer, or tuple objects, or a Mul
    start : Symbol
        An optional starting symbolic index
    gen : object
        An optional numbered symbol generator
    qubit_map : dict
        An existing mapping of symbolic indices to real indices

    All symbolic indices have the format 'i#', where # is
    some number >= 0.
    """

    if isinstance(seq, Mul):
        seq = seq.args

    # A numbered symbol generator
    index_gen = numbered_symbols(prefix='i', start=-1)
    cur_ndx = index_gen.next()

    # keys are symbolic indices; values are real indices
    ndx_map = {}

    def create_inverse_map(symb_to_real_map):
        rev_items = lambda item: tuple([item[1], item[0]])
        return dict(map(rev_items, symb_to_real_map.items()))

    if start is not None:
        if not isinstance(start, Symbol):
            msg = 'Expected Symbol for starting index, got %r.' % start
            raise TypeError(msg)
        cur_ndx = start

    if gen is not None:
        if not isinstance(gen, numbered_symbols().__class__):
            msg = 'Expected a generator, got %r.' % gen
            raise TypeError(msg)
        index_gen = gen

    if qubit_map is not None:
        if not isinstance(qubit_map, dict):
            msg = ('Expected dict for existing map, got ' +
                   '%r.' % qubit_map)
            raise TypeError(msg)
        ndx_map = qubit_map

    ndx_map = _sympify_qubit_map(ndx_map)
    # keys are real indices; keys are symbolic indices
    inv_map = create_inverse_map(ndx_map)

    sym_seq = ()
    for item in seq:
        # Nested items, so recurse
        if isinstance(item, Gate):
            result = convert_to_symbolic_indices(item.args,
                                                 qubit_map=ndx_map,
                                                 start=cur_ndx,
                                                 gen=index_gen)
            sym_item, new_map, cur_ndx, index_gen = result
            ndx_map.update(new_map)
            inv_map = create_inverse_map(ndx_map)

        elif isinstance(item, tuple) or isinstance(item, Tuple):
            result = convert_to_symbolic_indices(item,
                                                 qubit_map=ndx_map,
                                                 start=cur_ndx,
                                                 gen=index_gen)
            sym_item, new_map, cur_ndx, index_gen = result
            ndx_map.update(new_map)
            inv_map = create_inverse_map(ndx_map)

        elif item in inv_map:
            sym_item = inv_map[item]

        else:
            cur_ndx = gen.next()
            ndx_map[cur_ndx] = item
            inv_map[item] = cur_ndx
            sym_item = cur_ndx

        if isinstance(item, Gate):
            sym_item = item.__class__(*sym_item)

        sym_seq = sym_seq + (sym_item,)

    return sym_seq, ndx_map, cur_ndx, index_gen
def generate(ex, vnames, idx):
    """
    Generate the C++ code by simplifying the expressions.
    """
    # print(ex)

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i] + repr(j) + idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i] + midx[j] + idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i] + idx)

    # print(num_e)
    # print(len(lname))
    with open("bssn.cpp", 'w') as output_file:

        print_n_write('// Dendro: {{{ ', output_file)
        print_n_write('// Dendro: original ops: ' + str(count_ops(lexp)),
                      output_file)

        # print("--------------------------------------------------------")
        # print("Now trying Common Subexpression Detection and Collection")
        # print("--------------------------------------------------------")

        # Common Subexpression Detection and Collection
        # for i in range(len(ex)):
        #     # print("--------------------------------------------------------")
        #     # print(ex[i])
        #     # print("--------------------------------------------------------")
        #     ee_name = ''.join(random.choice(string.ascii_uppercase) for _ in range(5))
        #     ee_syms = numbered_symbols(prefix=ee_name)
        #     _v = cse(ex[i],symbols=ee_syms)
        #     # print(type(_v))
        #     for (v1,v2) in _v[0]:
        #         print("double %s = %s;" % (v1, v2))
        #     print("%s = %s" % (vnames[i], _v[1][0]))

        #mex = Matrix(ex)
        ee_name = 'DENDRO_'  #''.join(random.choice(string.ascii_uppercase) for _ in range(5))
        ee_syms = numbered_symbols(prefix=ee_name)
        _v = cse(lexp, symbols=ee_syms, optimizations='basic')

        #dp.drawgragh(_v)
        #dependencies = dp.makeCompleteDependencies(_v)
        #dp.printDependencies(dependencies)

        #Generating the graph for dependencies
        #graph, dependencies = lg.makeDependencies(_v)
        #lg.printGraph(graph)

        #Graph Laplacian
        #graphLaplacian = lg.getGraphLaplacian(graph)

        #adj_mat = lg.getAdjecencyMatrix(graph)

        #print("Number of Nodes: "+str(lg.getNumNodes(graph)))
        #print("Dimensions of the matrix" + str(lg.getDimensions(adj_mat)))

        #print(str(type(graphLaplacian)))

        #vals, vecs = lg.getEigenValuesandVectors(graphLaplacian)

        #print("Printing Eigen Values")

        #print(vals)

        #print("Printing Eigen Vectors")
        #print(vecs)

        #spectral clustering
        #sc = lg.doSpectralClustering(adj_mat)

        #lg.printSpectralClustering(sc, graph, dependencies)

        dependencies = cl.makeCompleteDependencies(_v)
        originalVariables = cl.getAllOriginalVariables(dependencies)

        featureVectors = cl.getFeatureVectors(dependencies, originalVariables)
        cl.writeFeatureVectorstoCSV(originalVariables, featureVectors)

        # miniBatchKMeansClusterPoints
        # affinityPropagationClusterPoints
        # meanShiftClusterPoints
        # spectralClusteringClusterPoints
        # agglomerativeClusteringClusterPoints
        # dBSCANClusteringClusterPoints
        # BirchClusteringClusterPoints,

        # kmeans = cl.kMeansClusterPoints(dependencies, featureVectors)
        # cl.writeClusteredResultstoCSV("Kmeans",kmeans, dependencies)
        #
        # miniBatchKMeans = cl.miniBatchKMeansClusterPoints(dependencies, featureVectors)
        # cl.writeClusteredResultstoCSV("MiniBatchKMeans", miniBatchKMeans, dependencies)
        #
        # meanShift = cl.meanShiftClusterPoints(dependencies, featureVectors)
        # cl.writeClusteredResultstoCSV("MeanShift", meanShift, dependencies)
        #
        # spectralClustering = cl.spectralClusteringClusterPoints(dependencies, featureVectors)
        # cl.writeClusteredResultstoCSV("SpectralClustering", spectralClustering, dependencies)

        agglomerative = cl.agglomerativeClusteringClusterPoints(
            7, featureVectors)
        cl.writeClusteredResultstoCSV("Agglomerative7", agglomerative,
                                      dependencies)

        #gnerating the graph for dependencies
        graph = lg.makeGraph(_v)
        lg.printGraph(graph, dependencies, agglomerative)

        # dBSCAN = cl.dBSCANClusteringClusterPoints(dependencies, featureVectors)
        # cl.writeClusteredResultstoCSV("DBSCAN", dBSCAN, dependencies)
        #
        # birch = cl.birchClusteringClusterPoints(dependencies, featureVectors)
        # cl.writeClusteredResultstoCSV("Birch", birch, dependencies)

        custom_functions = {
            'grad': 'grad',
            'grad2': 'grad2',
            'agrad': 'agrad',
            'kograd': 'kograd'
        }

        rops = 0
        print_n_write('// Dendro: printing temp variables', output_file)
        for (v1, v2) in _v[0]:
            # print("double %s = %s;" % (v1, v2)) # replace_pow(v2)))
            print_n_write('double ', output_file, isNewLineEnd=False)
            print_n_write(v2,
                          output_file,
                          assign_to=v1,
                          user_functions=custom_functions,
                          isCExp=True)
            rops = rops + count_ops(v2)

        print_n_write('\n// Dendro: printing variables', output_file)
        for i, e in enumerate(_v[1]):
            print_n_write("//--", output_file)
            # print("%s = %s;" % (lname[i], e)) # replace_pow(e)))
            print_n_write(e,
                          output_file,
                          assign_to=lname[i],
                          user_functions=custom_functions,
                          isCExp=True)
            rops = rops + count_ops(e)

        print_n_write('// Dendro: reduced ops: ' + str(rops), output_file)
        print_n_write('// Dendro: }}} ', output_file)

        print_n_write('// Dendro vectorized code: {{{', output_file)
        oper = {'mul': 'dmul', 'add': 'dadd', 'load': '*'}
        prevdefvars = set()
        for (v1, v2) in _v[0]:
            vv = numbered_symbols('v')
            vlist = []
            gen_vector_code(v2, vv, vlist, oper, prevdefvars, idx, output_file)
            print_n_write(
                '  double ' + repr(v1) + ' = ' + repr(vlist[0]) + ';',
                output_file)
        for i, e in enumerate(_v[1]):
            print_n_write("//--", output_file)
            vv = numbered_symbols('v')
            vlist = []
            gen_vector_code(e, vv, vlist, oper, prevdefvars, idx, output_file)
            #st = '  ' + repr(lname[i]) + '[idx] = ' + repr(vlist[0]) + ';'
            st = '  ' + repr(lname[i]) + " = " + repr(vlist[0]) + ';'
            print_n_write(st.replace("'", ""), output_file)

        print_n_write('// Dendro vectorized code: }}} ', output_file)
示例#35
0
def test_convert_to_symbolic_indices():
    (x, y, z, h) = create_gate_sequence()

    i0 = Symbol('i0')
    exp_map = {i0: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices((x,))
    assert actual == (X(i0),)
    assert act_map == exp_map

    expected = (X(i0), Y(i0), Z(i0), H(i0))
    exp_map = {i0: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices((x, y, z, h))
    assert actual == expected
    assert exp_map == act_map

    (x1, y1, z1, h1) = create_gate_sequence(1)
    i1 = Symbol('i1')

    expected = (X(i0), Y(i0), Z(i0), H(i0))
    exp_map = {i0: Integer(1)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices((x1, y1, z1, h1))
    assert actual == expected
    assert act_map == exp_map

    expected = (X(i0), Y(i0), Z(i0), H(i0), X(i1), Y(i1), Z(i1), H(i1))
    exp_map = {i0: Integer(0), i1: Integer(1)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices((x, y, z, h,
                                         x1, y1, z1, h1))
    assert actual == expected
    assert act_map == exp_map

    exp_map = {i0: Integer(1), i1: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(Mul(x1, y1,
                                         z1, h1, x, y, z, h))
    assert actual == expected
    assert act_map == exp_map

    expected = (X(i0), X(i1), Y(i0), Y(i1), Z(i0), Z(i1), H(i0), H(i1))
    exp_map = {i0: Integer(0), i1: Integer(1)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(Mul(x, x1,
                                         y, y1, z, z1, h, h1))
    assert actual == expected
    assert act_map == exp_map

    exp_map = {i0: Integer(1), i1: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices((x1, x, y1, y,
                                         z1, z, h1, h))
    assert actual == expected
    assert act_map == exp_map

    cnot_10 = CNOT(1, 0)
    cnot_01 = CNOT(0, 1)
    cgate_z_10 = CGate(1, Z(0))
    cgate_z_01 = CGate(0, Z(1))

    expected = (X(i0), X(i1), Y(i0), Y(i1), Z(i0), Z(i1),
                H(i0), H(i1), CNOT(i1, i0), CNOT(i0, i1),
                CGate(i1, Z(i0)), CGate(i0, Z(i1)))
    exp_map = {i0: Integer(0), i1: Integer(1)}
    args = (x, x1, y, y1, z, z1, h, h1, cnot_10, cnot_01,
            cgate_z_10, cgate_z_01)
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map

    args = (x1, x, y1, y, z1, z, h1, h, cnot_10, cnot_01,
            cgate_z_10, cgate_z_01)
    expected = (X(i0), X(i1), Y(i0), Y(i1), Z(i0), Z(i1),
                H(i0), H(i1), CNOT(i0, i1), CNOT(i1, i0),
                CGate(i0, Z(i1)), CGate(i1, Z(i0)))
    exp_map = {i0: Integer(1), i1: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map

    args = (cnot_10, h, cgate_z_01, h)
    expected = (CNOT(i0, i1), H(i1), CGate(i1, Z(i0)), H(i1))
    exp_map = {i0: Integer(1), i1: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map

    args = (cnot_01, h1, cgate_z_10, h1)
    exp_map = {i0: Integer(0), i1: Integer(1)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map

    args = (cnot_10, h1, cgate_z_01, h1)
    expected = (CNOT(i0, i1), H(i0), CGate(i1, Z(i0)), H(i0))
    exp_map = {i0: Integer(1), i1: Integer(0)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map

    i2 = Symbol('i2')
    ccgate_z = CGate(0, CGate(1, Z(2)))
    ccgate_x = CGate(1, CGate(2, X(0)))
    args = (ccgate_z, ccgate_x)

    expected = (CGate(i0, CGate(i1, Z(i2))), CGate(i1, CGate(i2, X(i0))))
    exp_map = {i0: Integer(0), i1: Integer(1), i2: Integer(2)}
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map

    ndx_map = {i0: Integer(0)}
    index_gen = numbered_symbols(prefix='i', start=1)
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args,
                                         qubit_map=ndx_map,
                                         start=i0,
                                         gen=index_gen)
    assert actual == expected
    assert act_map == exp_map

    i3 = Symbol('i3')
    cgate_x0_c321 = CGate((3, 2, 1), X(0))
    exp_map = {i0: Integer(3), i1: Integer(2),
               i2: Integer(1), i3: Integer(0)}
    expected = (CGate((i0, i1, i2), X(i3)),)
    args = (cgate_x0_c321,)
    actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
    assert actual == expected
    assert act_map == exp_map
示例#36
0
def _neq_linear_first_order_const_coeff_homogeneous(match_):
    r"""
    System of n first-order constant-coefficient linear homogeneous differential equations

    .. math:: y'_k = a_{k1} y_1 + a_{k2} y_2 +...+ a_{kn} y_n; k = 1,2,...,n

    or that can be written as `\vec{y'} = A . \vec{y}`
    where `\vec{y}` is matrix of `y_k` for `k = 1,2,...n` and `A` is a `n \times n` matrix.

    Since these equations are equivalent to a first order homogeneous linear
    differential equation. So the general solution will contain `n` linearly
    independent parts and solution will consist some type of exponential
    functions. Assuming `y = \vec{v} e^{rt}` is a solution of the system where
    `\vec{v}` is a vector of coefficients of `y_1,...,y_n`. Substituting `y` and
    `y' = r v e^{r t}` into the equation `\vec{y'} = A . \vec{y}`, we get

    .. math:: r \vec{v} e^{rt} = A \vec{v} e^{rt}

    .. math:: r \vec{v} = A \vec{v}

    where `r` comes out to be eigenvalue of `A` and vector `\vec{v}` is the eigenvector
    of `A` corresponding to `r`. There are three possibilities of eigenvalues of `A`

    - `n` distinct real eigenvalues
    - complex conjugate eigenvalues
    - eigenvalues with multiplicity `k`

    1. When all eigenvalues `r_1,..,r_n` are distinct with `n` different eigenvectors
    `v_1,...v_n` then the solution is given by

    .. math:: \vec{y} = C_1 e^{r_1 t} \vec{v_1} + C_2 e^{r_2 t} \vec{v_2} +...+ C_n e^{r_n t} \vec{v_n}

    where `C_1,C_2,...,C_n` are arbitrary constants.

    2. When some eigenvalues are complex then in order to make the solution real,
    we take a linear combination: if `r = a + bi` has an eigenvector
    `\vec{v} = \vec{w_1} + i \vec{w_2}` then to obtain real-valued solutions to
    the system, replace the complex-valued solutions `e^{rx} \vec{v}`
    with real-valued solution `e^{ax} (\vec{w_1} \cos(bx) - \vec{w_2} \sin(bx))`
    and for `r = a - bi` replace the solution `e^{-r x} \vec{v}` with
    `e^{ax} (\vec{w_1} \sin(bx) + \vec{w_2} \cos(bx))`

    3. If some eigenvalues are repeated. Then we get fewer than `n` linearly
    independent eigenvectors, we miss some of the solutions and need to
    construct the missing ones. We do this via generalized eigenvectors, vectors
    which are not eigenvectors but are close enough that we can use to write
    down the remaining solutions. For a eigenvalue `r` with eigenvector `\vec{w}`
    we obtain `\vec{w_2},...,\vec{w_k}` using

    .. math:: (A - r I) . \vec{w_2} = \vec{w}

    .. math:: (A - r I) . \vec{w_3} = \vec{w_2}

    .. math:: \vdots

    .. math:: (A - r I) . \vec{w_k} = \vec{w_{k-1}}

    Then the solutions to the system for the eigenspace are `e^{rt} [\vec{w}],
    e^{rt} [t \vec{w} + \vec{w_2}], e^{rt} [\frac{t^2}{2} \vec{w} + t \vec{w_2} + \vec{w_3}],
    ...,e^{rt} [\frac{t^{k-1}}{(k-1)!} \vec{w} + \frac{t^{k-2}}{(k-2)!} \vec{w_2} +...+ t \vec{w_{k-1}}
    + \vec{w_k}]`

    So, If `\vec{y_1},...,\vec{y_n}` are `n` solution of obtained from three
    categories of `A`, then general solution to the system `\vec{y'} = A . \vec{y}`

    .. math:: \vec{y} = C_1 \vec{y_1} + C_2 \vec{y_2} + \cdots + C_n \vec{y_n}

    """
    eq = match_['eq']
    func = match_['func']
    fc = match_['func_coeff']
    n = len(eq)
    t = list(list(eq[0].atoms(Derivative))[0].atoms(Symbol))[0]
    constants = numbered_symbols(prefix='C', cls=Symbol, start=1)

    # This needs to be modified in future so that fc is only of type Matrix
    M = -fc if type(fc) is Matrix else Matrix(n, n,
                                              lambda i, j: -fc[i, func[j], 0])

    P, J = matrix_exp_jordan_form(M, t)
    P = simplify(P)
    Cvect = Matrix(list(next(constants) for _ in range(n)))
    sol_vector = P * (J * Cvect)

    sol_vector = [
        collect(s, ordered(J.atoms(exp)), exact=True) for s in sol_vector
    ]

    sol_dict = [Eq(func[i], sol_vector[i]) for i in range(n)]
    return sol_dict
示例#37
0
文件: dendro.py 项目: vmiheer/SymPyGR
def generate_separate(ex, vnames, idx):
    """
    Generate the C++ code by simplifying the expressions.
    """
    # print(ex)
    if len(ex)!=1 :
        print ('pass each variable separately ',end='\n')
        return

    mi = [0, 1, 2, 4, 5, 8]
    midx = ['00', '01', '02', '11', '12', '22']

    # total number of expressions
    # print("--------------------------------------------------------")
    num_e = 0
    lexp = []
    lname = []
    for i, e in enumerate(ex):
        if type(e) == list:
            num_e = num_e + len(e)
            for j, ev in enumerate(e):
                lexp.append(ev)
                lname.append(vnames[i]+repr(j)+idx)
        elif type(e) == Matrix:
            num_e = num_e + len(e)
            for j, k in enumerate(mi):
                lexp.append(e[k])
                lname.append(vnames[i]+midx[j]+idx)
        else:
            num_e = num_e + 1
            lexp.append(e)
            lname.append(vnames[i]+idx)

    # print(num_e)
    # print(len(lname))
    c_file=open(vnames[0]+'.cpp','w')
    print('generating code for '+vnames[0])
    print('    bssn::timer::t_rhs.start();',file=c_file)
    print('for (unsigned int k = 3; k < nz-3; k++) { ',file=c_file)
    print('    z = pmin[2] + k*hz;',file=c_file)

    print('for (unsigned int j = 3; j < ny-3; j++) { ',file=c_file)
    print('    y = pmin[1] + j*hy; ',file=c_file)

    print('for (unsigned int i = 3; i < nx-3; i++) {',file=c_file)
    print('    x = pmin[0] + i*hx;',file=c_file)
    print('    pp = i + nx*(j + ny*k);',file=c_file)
    print('    r_coord = sqrt(x*x + y*y + z*z);',file=c_file)
    print('    eta=ETA_CONST;',file=c_file)
    print('    if (r_coord >= ETA_R0) {',file=c_file)
    print('    eta *= pow( (ETA_R0/r_coord), ETA_DAMPING_EXP);',file=c_file)
    print('    }',file=c_file)




    print('// Dendro: {{{ ',file=c_file)
    print('// Dendro: original ops: ', count_ops(lexp),file=c_file)

    # print("--------------------------------------------------------")
    # print("Now trying Common Subexpression Detection and Collection")
    # print("--------------------------------------------------------")

    # Common Subexpression Detection and Collection
    # for i in range(len(ex)):
    #     # print("--------------------------------------------------------")
    #     # print(ex[i])
    #     # print("--------------------------------------------------------")
    #     ee_name = ''.join(random.choice(string.ascii_uppercase) for _ in range(5))
    #     ee_syms = numbered_symbols(prefix=ee_name)
    #     _v = cse(ex[i],symbols=ee_syms)
    #     # print(type(_v))
    #     for (v1,v2) in _v[0]:
    #         print("double %s = %s;" % (v1, v2))
    #     print("%s = %s" % (vnames[i], _v[1][0]))

    #mex = Matrix(ex)
    ee_name = 'DENDRO_' #''.join(random.choice(string.ascii_uppercase) for _ in range(5))
    ee_syms = numbered_symbols(prefix=ee_name)
    _v = cse(lexp, symbols=ee_syms, optimizations='basic')

    custom_functions = {'grad': 'grad', 'grad2': 'grad2', 'agrad': 'agrad', 'kograd': 'kograd'}

    rops=0
    print('// Dendro: printing temp variables',file=c_file)
    for (v1, v2) in _v[0]:
        # print("double %s = %s;" % (v1, v2)) # replace_pow(v2)))
        print('double ', end='', file=c_file)
        print(change_deriv_names(ccode(v2, assign_to=v1, user_functions=custom_functions)),file=c_file)
        rops = rops + count_ops(v2)


    print('// Dendro: printing variables',file=c_file)
    for i, e in enumerate(_v[1]):
        print("//--",file=c_file)
        # print("%s = %s;" % (lname[i], e)) # replace_pow(e)))
        f = open(str(vnames[0])+'.gv','w')
        print(dotprint(e), file=f)
        f.close()
        print(change_deriv_names(ccode(e, assign_to=lname[i], user_functions=custom_functions)),file=c_file)
        #c_file.write('\n')
        rops = rops + count_ops(e)

    print('// Dendro: reduced ops: ', rops,file=c_file)
    print('// Dendro: }}} ',file=c_file)





    print('     /* debugging */',file=c_file)
    print('     /*unsigned int qi = 46 - 1;',file=c_file)
    print('     unsigned int qj = 10 - 1;',file=c_file)
    print('     unsigned int qk = 60 - 1;',file=c_file)
    print('     unsigned int qidx = qi + nx*(qj + ny*qk);',file=c_file)
    print('     if (0 && qidx == pp) {',file=c_file)
    print('     std::cout << ".... end OPTIMIZED debug stuff..." << std::endl;',file=c_file)
    print('     }*/',file=c_file)
    print('  }',file=c_file)
    print(' }',file=c_file)
    print('}',file=c_file)
    print('     bssn::timer::t_rhs.stop();',file=c_file)
    c_file.close()
    print('generating code for '+vnames[0]+' completed')
示例#38
0
    try:
        f, opt = poly_from_expr(f, *gens, **args)
    except PolificationFailed, exc:
        raise ComputationFailed('viete', 1, exc)

    if f.is_multivariate:
        raise MultivariatePolynomialError("multivariate polynomials are not allowed")

    n = f.degree()

    if n < 1:
        raise ValueError("can't derive Viete's formulas for a constant polynomial")

    if roots is None:
        roots = numbered_symbols('r', start=1)

    roots = take(roots, n)

    if n != len(roots):
        raise ValueError("required %s roots, got %s" % (n, len(roots)))

    lc, coeffs = f.LC(), f.all_coeffs()
    result, sign = [], -1

    for i, coeff in enumerate(coeffs[1:]):
        poly = symmetric_poly(i+1, roots)
        coeff = sign*(coeff/lc)
        result.append((poly, coeff))
        sign = -sign
示例#39
0
def convert_to_symbolic_indices(seq, start=None, gen=None, qubit_map=None):
    """Returns the circuit with symbolic indices and the
    dictionary mapping symbolic indices to real indices.

    The mapping is 1 to 1 and onto (bijective).

    Parameters
    ==========

    seq : tuple, Gate/Integer/tuple or Mul
        A tuple of Gate, Integer, or tuple objects, or a Mul
    start : Symbol
        An optional starting symbolic index
    gen : object
        An optional numbered symbol generator
    qubit_map : dict
        An existing mapping of symbolic indices to real indices

    All symbolic indices have the format 'i#', where # is
    some number >= 0.
    """

    if isinstance(seq, Mul):
        seq = seq.args

    # A numbered symbol generator
    index_gen = numbered_symbols(prefix='i', start=-1)
    cur_ndx = next(index_gen)

    # keys are symbolic indices; values are real indices
    ndx_map = {}

    def create_inverse_map(symb_to_real_map):
        rev_items = lambda item: tuple([item[1], item[0]])
        return dict(map(rev_items, symb_to_real_map.items()))

    if start is not None:
        if not isinstance(start, Symbol):
            msg = 'Expected Symbol for starting index, got %r.' % start
            raise TypeError(msg)
        cur_ndx = start

    if gen is not None:
        if not isinstance(gen, numbered_symbols().__class__):
            msg = 'Expected a generator, got %r.' % gen
            raise TypeError(msg)
        index_gen = gen

    if qubit_map is not None:
        if not isinstance(qubit_map, dict):
            msg = ('Expected dict for existing map, got ' + '%r.' % qubit_map)
            raise TypeError(msg)
        ndx_map = qubit_map

    ndx_map = _sympify_qubit_map(ndx_map)
    # keys are real indices; keys are symbolic indices
    inv_map = create_inverse_map(ndx_map)

    sym_seq = ()
    for item in seq:
        # Nested items, so recurse
        if isinstance(item, Gate):
            result = convert_to_symbolic_indices(item.args,
                                                 qubit_map=ndx_map,
                                                 start=cur_ndx,
                                                 gen=index_gen)
            sym_item, new_map, cur_ndx, index_gen = result
            ndx_map.update(new_map)
            inv_map = create_inverse_map(ndx_map)

        elif isinstance(item, tuple) or isinstance(item, Tuple):
            result = convert_to_symbolic_indices(item,
                                                 qubit_map=ndx_map,
                                                 start=cur_ndx,
                                                 gen=index_gen)
            sym_item, new_map, cur_ndx, index_gen = result
            ndx_map.update(new_map)
            inv_map = create_inverse_map(ndx_map)

        elif item in inv_map:
            sym_item = inv_map[item]

        else:
            cur_ndx = next(gen)
            ndx_map[cur_ndx] = item
            inv_map[item] = cur_ndx
            sym_item = cur_ndx

        if isinstance(item, Gate):
            sym_item = item.__class__(*sym_item)

        sym_seq = sym_seq + (sym_item, )

    return sym_seq, ndx_map, cur_ndx, index_gen
示例#40
0
def minimal_polynomial(ex, x=None, **args):
    """
    Computes the minimal polynomial of an algebraic number.

    **Example**

    >>> from sympy import minimal_polynomial, sqrt
    >>> from sympy.abc import x

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1

    """
    generator = numbered_symbols('a', cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    ex = sympify(ex)

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy('x'), PurePoly

    def update_mapping(ex, exp, base=None):
        a = generator.next()
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a**exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational and ex.q != 0:
                return ex
        elif ex.is_Add:
            return Add(*[ bottom_up_scan(g) for g in ex.args ])
        elif ex.is_Mul:
            return Mul(*[ bottom_up_scan(g) for g in ex.args ])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base**(-ex.exp)

                if not ex.exp.is_Integer:
                    base, exp = (ex.base**ex.exp.p).expand(), Rational(1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp

                base = bottom_up_scan(base)
                expr = base**exp

                if expr not in mapping:
                    return update_mapping(expr, 1/exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    polys = args.get('polys', False)

    if ex.is_AlgebraicNumber:
        if not polys:
            return ex.minpoly.as_expr(x)
        else:
            return ex.minpoly.replace(x)
    elif ex.is_Rational and ex.q != 0:
        result = ex.q*x - ex.p
    else:
        F = [x - bottom_up_scan(ex)] + mapping.values()
        G = groebner(F, symbols.values() + [x], order='lex')

        _, factors = factor_list(G[-1])

        if len(factors) == 1:
            ((result, _),) = factors
        else:
            for result, _ in factors:
                if result.subs(x, ex).evalf(chop=True) == 0:
                    break
            else: # pragma: no cover
                raise NotImplementedError("multiple candidates for the minimal polynomial of %s" % ex)

    if polys:
        return cls(result, x, field=True)
    else:
        return result
示例#41
0
 def default(cls):
     return numbered_symbols('s', start=1)
示例#42
0
def minimal_polynomial(ex, x=None, **args):
    """
    Computes the minimal polynomial of an algebraic number.

    Examples
    ========

    >>> from sympy import minimal_polynomial, sqrt
    >>> from sympy.abc import x

    >>> minimal_polynomial(sqrt(2), x)
    x**2 - 2
    >>> minimal_polynomial(sqrt(2) + sqrt(3), x)
    x**4 - 10*x**2 + 1

    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_mul, expand_multinomial
    from sympy.simplify.simplify import _is_sum_surds

    generator = numbered_symbols("a", cls=Dummy)
    mapping, symbols, replace = {}, {}, []

    ex = sympify(ex)

    if x is not None:
        x, cls = sympify(x), Poly
    else:
        x, cls = Dummy("x"), PurePoly

    def update_mapping(ex, exp, base=None):
        a = generator.next()
        symbols[ex] = a

        if base is not None:
            mapping[ex] = a ** exp + base
        else:
            mapping[ex] = exp.as_expr(a)

        return a

    def bottom_up_scan(ex):
        if ex.is_Atom:
            if ex is S.ImaginaryUnit:
                if ex not in mapping:
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ex.exp < 0 and ex.base.is_Add:
                    coeff, terms = ex.base.as_coeff_add()
                    elt, _ = primitive_element(terms, polys=True)

                    alg = ex.base - coeff

                    # XXX: turn this into eval()
                    inverse = invert(elt.gen + coeff, elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()

                    if ex.exp == -1:
                        return bottom_up_scan(base)
                    else:
                        ex = base ** (-ex.exp)
                if not ex.exp.is_Integer:
                    base, exp = (ex.base ** ex.exp.p).expand(), Rational(1, ex.exp.q)
                else:
                    base, exp = ex.base, ex.exp
                base = bottom_up_scan(base)
                expr = base ** exp

                if expr not in mapping:
                    return update_mapping(expr, 1 / exp, -base)
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if ex.root not in mapping:
                return update_mapping(ex.root, ex.minpoly)
            else:
                return symbols[ex.root]

        raise NotAlgebraic("%s doesn't seem to be an algebraic number" % ex)

    def simpler_inverse(ex):
        """
        Returns True if it is more likely that the minimal polynomial
        algorithm works better with the inverse
        """
        if ex.is_Pow:
            if (1 / ex.exp).is_integer and ex.exp < 0:
                if ex.base.is_Add:
                    return True
        if ex.is_Mul:
            hit = True
            a = []
            for p in ex.args:
                if p.is_Add:
                    return False
                if p.is_Pow:
                    if p.base.is_Add and p.exp > 0:
                        return False

            if hit:
                return True
        return False

    polys = args.get("polys", False)
    prec = args.pop("prec", 10)

    inverted = False
    ex = expand_multinomial(ex)
    if ex.is_AlgebraicNumber:
        if not polys:
            return ex.minpoly.as_expr(x)
        else:
            return ex.minpoly.replace(x)
    elif ex.is_Rational:
        result = ex.q * x - ex.p
    else:
        inverted = simpler_inverse(ex)
        if inverted:
            ex = ex ** -1
        res = None
        if ex.is_Pow and (1 / ex.exp).is_Integer:
            n = 1 / ex.exp
            res = _minimal_polynomial_sq(ex.base, n, x, prec)

        elif _is_sum_surds(ex):
            res = _minimal_polynomial_sq(ex, S.One, x, prec)

        if res is not None:
            result = res

        if res is None:
            bus = bottom_up_scan(ex)
            F = [x - bus] + mapping.values()
            G = groebner(F, symbols.values() + [x], order="lex")

            _, factors = factor_list(G[-1])
            # by construction G[-1] has root `ex`
            result = _choose_factor(factors, x, ex, prec)
            if result is None:
                raise NotImplementedError("multiple candidates for the minimal polynomial of %s" % ex)
    if inverted:
        result = expand_mul(x ** degree(result) * result.subs(x, 1 / x))
        if result.coeff(x ** degree(result)) < 0:
            result = expand_mul(-result)
    if polys:
        return cls(result, x, field=True)
    else:
        return result