Пример #1
0
def myroots(expr_1, expr_2, input_type, output_type):
    from sympy import roots, sympify, latex
    expr_1 = sympify(expr_1)
    expr_2 = sympify(expr_2)
    input_type = str(input_type)
    output_type = str(output_type)

    if input_type == 'LaTeX':

        print('roots({}, {}) = '.format(latex(expr_1), latex(expr_2)))

    elif input_type == 'SymPy':

        print('roots({}, {}) = '.format(expr_1, expr_2))

    else:
        print("Wrong input type")

    if output_type == 'LaTeX':

        print(latex(roots((expr_1), expr_2)))

    elif output_type == 'SymPy':

        print(roots((expr_1), expr_2))

    else:
        print("Wrong output type")
Пример #2
0
    def get_harmonic_standard_deviations_around_minima(self,
                                                       temperature=300.0 *
                                                       unit.kelvin):

        kB = unit.BOLTZMANN_CONSTANT_kB * unit.AVOGADRO_CONSTANT_NA

        Eo = self.parameters['Eo']
        a = self.parameters['a']
        b = self.parameters['b']
        k = self.parameters['k']

        x, y, z = sy.symbols('x y z')
        xu = x * unit.nanometers
        yu = y * unit.nanometers
        zu = z * unit.nanometers

        potential_x = Eo * ((xu / a)**4 - 2.0 * (xu / a)**2) - (b / a) * xu
        potential_y = 0.5 * k * (yu**2)
        potential_z = 0.5 * k * (zu**2)

        g = sy.diff(potential_y, y)
        gg = sy.diff(potential_y, y, y)
        roots_diff = sy.roots(g, y)

        root_y = None
        sigma_y = None
        for root in roots_diff.keys():
            effective_k = gg.subs(y, root)
            if effective_k > 0:
                root_y = root * unit.nanometers
                sigma_y = np.sqrt(kB * temperature /
                                  (effective_k * unit.kilocalories_per_mole /
                                   unit.nanometers**2))

        g = sy.diff(potential_x, x)
        gg = sy.diff(potential_x, x, x)
        roots_diff = sy.roots(g, x)

        roots = []
        sigmas = []
        for root in roots_diff.keys():
            effective_k = gg.subs(x, root)
            if effective_k > 0:
                root_3d = np.zeros([3], dtype=float) * unit.nanometers
                root_3d[0] = root * unit.nanometers
                root_3d[1] = root_y
                root_3d[2] = root_y
                roots.append(root_3d)
                sigma_3d = np.zeros([3], dtype=float) * unit.nanometers
                sigma_3d[0] = np.sqrt(
                    kB * temperature /
                    (effective_k * unit.kilocalories_per_mole /
                     unit.nanometers**2))
                sigma_3d[1] = sigma_y
                sigma_3d[2] = sigma_y
                sigmas.append(sigma_3d)

        del (x, y, z)

        return roots, sigmas
Пример #3
0
def f2zpk(function: Basic,
          var: Symbol) -> Tuple[Dict[Basic, int], Dict[Basic, int], Basic]:
    numer, denom = f2nd(function)
    numer_lc, denom_lc = map(lambda expr: leading_coeff(expr, var),
                             (numer, denom))
    # It's not really necesary to devide by the leading
    # coefficient, but what do I know
    return roots(numer/numer_lc, var), \
           roots(denom/denom_lc, var), numer_lc/denom_lc
Пример #4
0
    def get_small_oscillations_time_periods_around_minima(self):

        Eo = self.parameters['Eo']
        a = self.parameters['a']
        b = self.parameters['b']
        k = self.parameters['k']
        mass = self.parameters['mass']

        x, y, z = sy.symbols('x y z')
        xu = x * unit.nanometers
        yu = y * unit.nanometers
        zu = z * unit.nanometers

        potential_x = Eo * ((xu / a)**4 - 2.0 * (xu / a)**2) - (b / a) * xu
        potential_y = 0.5 * k * (yu**2)
        potential_z = 0.5 * k * (zu**2)

        g = sy.diff(potential_y, y)
        gg = sy.diff(potential_y, y, y)
        roots_diff = sy.roots(g, y)

        root_y = None
        T_y = None
        for root in roots_diff.keys():
            effective_k = gg.subs(y, root)
            if effective_k > 0:
                root_y = root * unit.nanometers
                T_y = 2 * np.pi * np.sqrt(
                    mass / (effective_k * unit.kilocalories_per_mole /
                            unit.nanometers**2))

        g = sy.diff(potential_x, x)
        gg = sy.diff(potential_x, x, x)
        roots_diff = sy.roots(g, x)

        roots = []
        Ts = []
        for root in roots_diff.keys():
            effective_k = gg.subs(x, root)
            if effective_k > 0:
                root_3d = np.zeros([3], dtype=float) * unit.nanometers
                root_3d[0] = root * unit.nanometers
                root_3d[1] = root_y
                root_3d[2] = root_y
                roots.append(root_3d)
                T_3d = np.zeros([3], dtype=float) * unit.picoseconds
                T_3d[0] = 2 * np.pi * np.sqrt(
                    mass / (effective_k * unit.kilocalories_per_mole /
                            unit.nanometers**2))
                T_3d[1] = T_y
                T_3d[2] = T_y
                Ts.append(T_3d)

        del (x, y, z)

        return roots, Ts
Пример #5
0
    def analyze_controller(self, K):
        if self.control_tfs is None:
            self.get_controller_transfer_functions()

        for X_r in self.X_r:
            # set all others in X_r to zero
            tfs = [
                sp.simplify(
                    tf.subs([(X_r_, 0)
                             for X_r_ in self.X_r if X_r_ is not X_r]) / X_r)
                for tf in self.control_tfs
            ]
            for X, tf in zip(self.X, tfs):
                numerator, denominator = tf.as_numer_denom()

                routh_table = np.array(routh(sp.Poly(denominator, self.s)))
                routh_conditions = routh_table[:, 0]

                tf = self.phys.apply_substitutions(tf)
                numerator = self.phys.apply_substitutions(numerator)
                denominator = self.phys.apply_substitutions(denominator)

                zeros = sp.roots(
                    numerator.subs(zip(self.k_pd_mat.flatten(), K.flatten())),
                    self.s)
                poles = sp.roots(
                    denominator.subs(zip(self.k_pd_mat.flatten(),
                                         K.flatten())), self.s)
                gain = get_gain(
                    self.s, tf.subs(zip(self.k_pd_mat.flatten(), K.flatten())),
                    zeros, poles)

                zeros_description = ', '.join([
                    str(zero.evalf(6)) if multiplicity == 1 else
                    f'{zero.evalf(6)} (x{multiplicity})'
                    for zero, multiplicity in zeros.items()
                ])
                poles_description = ', '.join([
                    str(pole.evalf(6)) if multiplicity == 1 else
                    f'{pole.evalf(6)} (x{multiplicity})'
                    for pole, multiplicity in poles.items()
                ])
                routh_conditions_description = '\n'.join([
                    to_string(condition.evalf(3))
                    for condition in routh_conditions
                ])
                print(
                    f'{X}/{X_r}: Routh Conditions:\n{routh_conditions_description}\nGain: {gain.evalf(6)}\n'
                    f'Poles: {poles_description}\nZeros: {zeros_description}\n\n'
                )
Пример #6
0
def get_world_segments(root_a, root_b, root_c, initial_t, final_t,
                       intersection_radius):
    """
    The world consists of
    three axis lines,
    six circles marking the intersections,
    and a single parametric curve.
    @return: a collection of (p0, p1, style) triples
    """
    seg_length_min = 0.1
    segments = []
    # add the axis line segments
    d = 5
    f_x = pcurve.LineSegment(np.array([-d, 0, 0]), np.array([d, 0, 0]))
    f_y = pcurve.LineSegment(np.array([0, -d, 0]), np.array([0, d, 0]))
    f_z = pcurve.LineSegment(np.array([0, 0, -d]), np.array([0, 0, d]))
    x_axis_segs = pcurve.get_piecewise_curve(f_x, 0, 1, 10, seg_length_min)
    y_axis_segs = pcurve.get_piecewise_curve(f_y, 0, 1, 10, seg_length_min)
    z_axis_segs = pcurve.get_piecewise_curve(f_z, 0, 1, 10, seg_length_min)
    segments.extend((p0, p1, STYLE_X) for p0, p1 in x_axis_segs)
    segments.extend((p0, p1, STYLE_Y) for p0, p1 in y_axis_segs)
    segments.extend((p0, p1, STYLE_Z) for p0, p1 in z_axis_segs)
    # add the parametric curve
    roots = (root_a, root_b, root_c)
    polys = interlace.roots_to_differential_polys(roots)
    f_poly = interlace.Multiplex((sympyutils.WrappedUniPoly(p) for p in polys))
    poly_segs = pcurve.get_piecewise_curve(f_poly, initial_t, final_t, 10,
                                           seg_length_min)
    segments.extend((p0, p1, STYLE_CURVE) for p0, p1 in poly_segs)
    # add the intersection circles
    x_roots_symbolic = sympy.roots(polys[0])
    y_roots_symbolic = sympy.roots(polys[1])
    z_roots_symbolic = sympy.roots(polys[2])
    x_roots = [float(r) for r in x_roots_symbolic]
    y_roots = [float(r) for r in y_roots_symbolic]
    z_roots = [float(r) for r in z_roots_symbolic]
    for r in x_roots:
        f = pcurve.OrthoCircle(f_poly(r), intersection_radius, 0)
        segs = pcurve.get_piecewise_curve(f, 0, 1, 10, seg_length_min)
        segments.extend((p0, p1, STYLE_X) for p0, p1 in segs)
    for r in y_roots:
        f = pcurve.OrthoCircle(f_poly(r), intersection_radius, 1)
        segs = pcurve.get_piecewise_curve(f, 0, 1, 10, seg_length_min)
        segments.extend((p0, p1, STYLE_Y) for p0, p1 in segs)
    for r in z_roots:
        f = pcurve.OrthoCircle(f_poly(r), intersection_radius, 2)
        segs = pcurve.get_piecewise_curve(f, 0, 1, 10, seg_length_min)
        segments.extend((p0, p1, STYLE_Z) for p0, p1 in segs)
    # return the segments
    return segments
Пример #7
0
    def ZPK(self):
        """Convert to pole-zero-gain (PZK) form.

        See also canonical, general, mixedfrac, and partfrac"""

        N, D, delay = self._as_ratfun_delay()

        K = sym.cancel(N.LC() / D.LC())
        if delay != 0:
            K *= sym.exp(self.var * delay)

        zeros = sym.roots(N)
        poles = sym.roots(D)

        return self.__class__(_zp2tf(zeros, poles, K, self.var))
Пример #8
0
    def ZPK(self):
        """Convert to pole-zero-gain (PZK) form.

        See also canonical, general, mixedfrac, and partfrac"""

        N, D, delay = self.as_ratfun_delay()

        K = sym.cancel(N.LC() / D.LC())
        if delay != 0:
            K *= sym.exp(self.var * delay)

        zeros = sym.roots(N)
        poles = sym.roots(D)

        return _zp2tf(zeros, poles, K, self.var)
Пример #9
0
def get_world_segments(root_a, root_b, root_c, initial_t, final_t, intersection_radius):
    """
    The world consists of
    three axis lines,
    six circles marking the intersections,
    and a single parametric curve.
    @return: a collection of (p0, p1, style) triples
    """
    seg_length_min = 0.1
    segments = []
    # add the axis line segments
    d = 5
    f_x = pcurve.LineSegment(np.array([-d, 0, 0]), np.array([d, 0, 0]))
    f_y = pcurve.LineSegment(np.array([0, -d, 0]), np.array([0, d, 0]))
    f_z = pcurve.LineSegment(np.array([0, 0, -d]), np.array([0, 0, d]))
    x_axis_segs = pcurve.get_piecewise_curve(f_x, 0, 1, 10, seg_length_min)
    y_axis_segs = pcurve.get_piecewise_curve(f_y, 0, 1, 10, seg_length_min)
    z_axis_segs = pcurve.get_piecewise_curve(f_z, 0, 1, 10, seg_length_min)
    segments.extend((p0, p1, STYLE_X) for p0, p1 in x_axis_segs)
    segments.extend((p0, p1, STYLE_Y) for p0, p1 in y_axis_segs)
    segments.extend((p0, p1, STYLE_Z) for p0, p1 in z_axis_segs)
    # add the parametric curve
    roots = (root_a, root_b, root_c)
    polys = interlace.roots_to_differential_polys(roots)
    f_poly = interlace.Multiplex((sympyutils.WrappedUniPoly(p) for p in polys))
    poly_segs = pcurve.get_piecewise_curve(f_poly, initial_t, final_t, 10, seg_length_min)
    segments.extend((p0, p1, STYLE_CURVE) for p0, p1 in poly_segs)
    # add the intersection circles
    x_roots_symbolic = sympy.roots(polys[0])
    y_roots_symbolic = sympy.roots(polys[1])
    z_roots_symbolic = sympy.roots(polys[2])
    x_roots = [float(r) for r in x_roots_symbolic]
    y_roots = [float(r) for r in y_roots_symbolic]
    z_roots = [float(r) for r in z_roots_symbolic]
    for r in x_roots:
        f = pcurve.OrthoCircle(f_poly(r), intersection_radius, 0)
        segs = pcurve.get_piecewise_curve(f, 0, 1, 10, seg_length_min)
        segments.extend((p0, p1, STYLE_X) for p0, p1 in segs)
    for r in y_roots:
        f = pcurve.OrthoCircle(f_poly(r), intersection_radius, 1)
        segs = pcurve.get_piecewise_curve(f, 0, 1, 10, seg_length_min)
        segments.extend((p0, p1, STYLE_Y) for p0, p1 in segs)
    for r in z_roots:
        f = pcurve.OrthoCircle(f_poly(r), intersection_radius, 2)
        segs = pcurve.get_piecewise_curve(f, 0, 1, 10, seg_length_min)
        segments.extend((p0, p1, STYLE_Z) for p0, p1 in segs)
    # return the segments
    return segments
Пример #10
0
    def get_coordinates_maximum(self):

        Eo = self.parameters['Eo']
        a = self.parameters['a']
        b = self.parameters['b']
        k = self.parameters['k']

        x, y, z = sy.symbols('x y z')
        xu = x * unit.nanometers
        yu = y * unit.nanometers
        zu = z * unit.nanometers

        potential_x = Eo * ((xu / a)**4 - 2.0 * (xu / a)**2) - (b / a) * xu
        potential_y = 0.5 * k * (yu**2)
        potential_z = 0.5 * k * (zu**2)

        g = sy.diff(potential_x, x)
        gg = sy.diff(potential_x, x, x)
        roots_diff = sy.roots(g, x)

        roots = []
        for root in roots_diff.keys():
            effective_k = gg.subs(x, root)
            if effective_k < 0:
                root_3d = np.zeros([3], dtype=float) * unit.nanometers
                root_3d[0] = root * unit.nanometers
                roots.append(root_3d)

        del (x, y, z)

        return roots
Пример #11
0
    def test_singularities(self):
        S1 = sympify(singularities(f1,x,y))
        S2 = sympify(singularities(f2,x,y))
        S3 = sympify(singularities(f3,x,y))
        S4 = sympify(singularities(f4,x,y))
        S5 = sympify(singularities(f5,x,y))
        S6 = sympify(singularities(f6,x,y))
#         S7 = sympify(singularities(f7,x,y))
#         S8 = sympify(singularities(f8,x,y))
        S9 = sympify(singularities(f9,x,y))
        S10= sympify(singularities(f10,x,y))

        rt5 = sympy.roots(x**2 + 1, x).keys()

        S1act = sympify([
            ((0,0,1),(2,2,1)),
            ((0,1,0),(2,1,2))
            ])
        S2act = sympify([
            ((0,0,1),(3,4,2)),
            ((0,1,0),(4,9,1))
            ])
        S3act = sympify([
            ((0,0,1),(2,1,2)),
            ((1,-1,1),(2,1,2)),
            ((1,1,1),(2,1,2))
            ])
        S4act = sympify([
            ((0,0,1),(2,1,2))
            ])
        S5act = sympify([
            ((0,0,1),(3,3,3)),
            ((1,rt5[1],0),(3,3,3)),
            ((1,rt5[0],0),(3,3,3))
            ])
        S6act = sympify([
            ((0,0,1),(2,2,2)),
            ((1,0,0),(2,2,2))
            ])
#         S7act = sympify([((0,1,0),(3,6,3))])
#         S8act = sympify([
#             ((0,1,0),(6,21,3)),
#             ((1,0,0),(3,7,2))
#             ])
        S9act = sympify([((0,1,0),(5,12,1))])
        S10act= sympify([
            ((0,1,0),(3,6,1)),
            ((1,0,0),(4,6,4))
            ])

        self.assertItemsEqual(S1,S1act)
        self.assertItemsEqual(S2,S2act)
        self.assertItemsEqual(S3,S3act)
        self.assertItemsEqual(S4,S4act)
        self.assertItemsEqual(S5,S5act)
        self.assertItemsEqual(S6,S6act)
#         self.assertItemsEqual(S7,S7act)
#         self.assertItemsEqual(S8,S8act)
        self.assertItemsEqual(S9,S9act)
        self.assertItemsEqual(S10,S10act)
Пример #12
0
    def test_singular_points(self):
        S1 = singularities(f1,x,y)
        S2 = singularities(f2,x,y)
        S3 = singularities(f3,x,y)
        S4 = singularities(f4,x,y)
        S5 = singularities(f5,x,y)
        S6 = singularities(f6,x,y)
        S7 = singularities(f7,x,y)
        S8 = singularities(f8,x,y)
        S9 = singularities(f9,x,y)
        S10= singularities(f10,x,y)

        rt5 = [rt for rt,_ in sympy.roots(x**2 + 1, x).iteritems()]

        S1act = [(0,0,1),(0,1,0)]
        S2act = [(0,0,1),(0,1,0)]
        S3act = [(0,0,1),(1,-1,1),(1,1,1)]
        S4act = [(0,0,1)]
        S5act = [(0,0,1),(rt5[0],1,0),(rt5[1],1,0)]
        S6act = [(0,0,1),(1,0,0)]
        S7act = [(0,1,0)]
        S8act = [(0,1,0),(1,0,0)]
        S9act = [(0,1,0)]
        S10act= [(0,1,0),(1,0,0)]

        self.assertItemsEqual(S1,S1act)
        self.assertItemsEqual(S2,S2act)
        self.assertItemsEqual(S3,S3act)
        self.assertItemsEqual(S4,S4act)
        self.assertItemsEqual(S5,S5act)
        self.assertItemsEqual(S6,S6act)
        self.assertItemsEqual(S7,S7act)
        self.assertItemsEqual(S8,S8act)
        self.assertItemsEqual(S9,S9act)
        self.assertItemsEqual(S10,S10act)
Пример #13
0
    def characteristic_roots(self):
        """Compute the roots of the characteristic equation.

        :returns: List of roots returned by :mod:`sympy`.

        """
        return sympy.roots(self.characteristic_poly())
Пример #14
0
def polyroots(poly, var):
    """Return roots of polynomial `poly` for variable `var`."""

    roots = sym.roots(poly)
    num_roots = 0
    for root, n in roots.items():
        num_roots += n
    if num_roots != poly.degree():
        if poly.degree() >= 5:
            warn(
                'Cannot find symbolic roots for polynomial of degree %d, see Abel-Ruffini theorem'
                % poly.degree())

        # If the coefficients of the polynomial are numerical,
        # the SymPy nroots function can be used to find
        # numerical approximations to the roots.
        a = set()
        a.add(var)
        if poly.free_symbols == a:
            warn('Only %d of %d roots found, using numerical approximation' %
                 (num_roots, poly.degree()))

            nroots = poly.nroots()

            roots = {}
            for root in nroots:
                if root in roots:
                    roots[root] += 1
                else:
                    roots[root] = 1

            return roots
        warn('Only %d of %d roots found' % (num_roots, poly.degree()))

    return roots
Пример #15
0
def test_legendre():
    raises(ValueError, lambda: legendre(-1, x))
    assert legendre(0, x) == 1
    assert legendre(1, x) == x
    assert legendre(2, x) == ((3 * x**2 - 1) / 2).expand()
    assert legendre(3, x) == ((5 * x**3 - 3 * x) / 2).expand()
    assert legendre(4, x) == ((35 * x**4 - 30 * x**2 + 3) / 8).expand()
    assert legendre(5, x) == ((63 * x**5 - 70 * x**3 + 15 * x) / 8).expand()
    assert legendre(6, x) == ((231 * x**6 - 315 * x**4 + 105 * x**2 - 5) /
                              16).expand()

    assert legendre(10, -1) == 1
    assert legendre(11, -1) == -1
    assert legendre(10, 1) == 1
    assert legendre(11, 1) == 1
    assert legendre(10, 0) != 0
    assert legendre(11, 0) == 0

    assert roots(legendre(4, x), x) == {
        sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1,
        -sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1,
        sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1,
        -sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1,
    }

    n = Symbol("n")

    X = legendre(n, x)
    assert isinstance(X, legendre)

    assert legendre(-n, x) == legendre(n - 1, x)
    assert legendre(n, -x) == (-1)**n * legendre(n, x)
    assert diff(legendre(
        n, x), x) == n * (x * legendre(n, x) - legendre(n - 1, x)) / (x**2 - 1)
    assert diff(legendre(n, x), n) == Derivative(legendre(n, x), n)
Пример #16
0
def get_pane_tikz_lines(poly_pair, color_pair, t0, t1):
    """
    This is called maybe three times.
    @param poly_pair: the lower and higher order Poly objects
    @param color_pair: the polynomial colors
    @param t0: initial time
    @param t1: final time
    @return: a list of tikz lines
    """
    lines = []
    pa, pb = poly_pair
    ca, cb = color_pair
    # draw the segmentation corresponding to the lower order polynomial
    for left, right, sign in get_segmentation(pa, t0, t1):
        width = {-1 : '0.5mm', 1 : '2mm'}[sign]
        line = '\\draw[color=%s,line width=%s] (%s, 0) -- (%s, 0);' % (
                ca, width, left, right)
        lines.append(line)
    # draw the cuts corresponding to the higher order polynomial
    for r in sorted(sympy.roots(pb)):
        cut = float(r)
        line = '\\draw[color=%s,line width=0.5mm] (%s, -3mm) -- (%s, 3mm);' % (
                cb, cut, cut)
        lines.append(line)
    return lines
Пример #17
0
def test_legendre():
    raises(ValueError, lambda: legendre(-1, x))
    assert legendre(0, x) == 1
    assert legendre(1, x) == x
    assert legendre(2, x) == ((3*x**2 - 1)/2).expand()
    assert legendre(3, x) == ((5*x**3 - 3*x)/2).expand()
    assert legendre(4, x) == ((35*x**4 - 30*x**2 + 3)/8).expand()
    assert legendre(5, x) == ((63*x**5 - 70*x**3 + 15*x)/8).expand()
    assert legendre(6, x) == ((231*x**6 - 315*x**4 + 105*x**2 - 5)/16).expand()

    assert legendre(10, -1) == 1
    assert legendre(11, -1) == -1
    assert legendre(10, 1) == 1
    assert legendre(11, 1) == 1
    assert legendre(10, 0) != 0
    assert legendre(11, 0) == 0

    assert roots(legendre(4, x), x) == {
        sqrt(Rational(3, 7) - Rational(2, 35)*sqrt(30)): 1,
        -sqrt(Rational(3, 7) - Rational(2, 35)*sqrt(30)): 1,
        sqrt(Rational(3, 7) + Rational(2, 35)*sqrt(30)): 1,
        -sqrt(Rational(3, 7) + Rational(2, 35)*sqrt(30)): 1,
    }

    n = Symbol("n")

    X = legendre(n, x)
    assert isinstance(X, legendre)

    assert legendre(-n, x) == legendre(n - 1, x)
    assert legendre(n, -x) == (-1)**n*legendre(n, x)
    assert diff(legendre(n, x), x) == \
        n*(x*legendre(n, x) - legendre(n - 1, x))/(x**2 - 1)
    assert diff(legendre(n, x), n) == Derivative(legendre(n, x), n)
def factor_linear_quadratic(f, x, as_list=False):
    """
    Factors a polynomial f(x) with real coefficients
    into linear and quadratic terms.
    Will not work if f depends on variables other than x.
    Returns a tuple with the constant coefficient and a list of the factors
    if as_list is True.
    """
    factors = []
    origin_roots = 0
    for root, multiplicity in sp.roots(f, x).items():
        if root == 0:
            factors.append((x, multiplicity))
            origin_roots = multiplicity
        elif root.is_real:
            factors.append((x - root, multiplicity))
        elif sp.im(root) > 0:
            factors.append((sp.expand(
                (x - root) * (x - sp.conjugate(root))), multiplicity))
    coefficient = (f / x ** origin_roots).subs(x, 0) / \
        sp.prod([factor.subs(x, 0) ** multiplicity
                 for factor, multiplicity in factors if factor != x])
    if as_list:
        return coefficient, factors
    return coefficient * sp.prod(
        [factor**multiplicity for factor, multiplicity in factors])
Пример #19
0
def _roots(poly, var):
    """ like roots, but works on higher-order polynomials. """
    r = roots(poly, var, multiple=True)
    n = degree(poly)
    if len(r) != n:
        r = [rootof(poly, var, k) for k in range(n)]
    return r
Пример #20
0
    def as_ZPK(self):
        """Decompose expression into zeros, poles, gain, undef where

        expression = K * (prod_n (var - z_n) / (prod_n (var - p_n)) * undef
        """

        Bpoly = self.Bpoly
        Apoly = self.Apoly

        K = sym.cancel(Bpoly.LC() / Apoly.LC())
        if self.delay != 0:
            K *= sym.exp(self.var * self.delay)

        zeros = sym.roots(Bpoly)
        poles = sym.roots(Apoly)

        return zeros, poles, K, self.undef
Пример #21
0
def find_roots(equation):
    poly_values = []
    for key, value in equation.items():
        # poly_values.append(float(value.split("*r")[0]))
        poly_values.append(parse_expr(value.split("*r")[0]))
    poly_roots = sy.roots(poly_values)
    print("roots:", poly_roots)

    return poly_roots
def get_poles_from_matrix(a, show_steps=False):
    '''Takes the A matrix of a system and returns the poles, format is {pole: multiplicity} can be 	 	used to determine stability'''
    ss = sy.symbols('s')
    char_mtx = ss * sy.eye(a.rows) - a
    char_eq = char_mtx.det()
    if show_steps:
        display(char_mtx)
        display(char_eq)
    return (sy.roots(char_eq))
Пример #23
0
 def d1c_roots(self, h_):
     # substitute U_0**2 into eq. 2.8 for given value of h and
     # simplify to create a polynomial in d1c
     d1cp = WHBase.eq28().subs(U0 ** 2, u_squared())
     d1cp = d1cp.subs({h: h_, S: self.S, d0: self.d0})
     d1cp = sp.fraction(d1cp.simplify())[0]
     # get all roots of this polynomial
     d1c_roots = sp.roots(d1cp, filter=None, multiple=True)
     return np.array(d1c_roots, dtype=complex)
Пример #24
0
def test_legendre():
    assert legendre(0, x) == 1
    assert legendre(1, x) == x
    assert legendre(2, x) == ((3 * x**2 - 1) / 2).expand()
    assert legendre(3, x) == ((5 * x**3 - 3 * x) / 2).expand()
    assert legendre(4, x) == ((35 * x**4 - 30 * x**2 + 3) / 8).expand()
    assert legendre(5, x) == ((63 * x**5 - 70 * x**3 + 15 * x) / 8).expand()
    assert (legendre(6, x) == ((231 * x**6 - 315 * x**4 + 105 * x**2 - 5) /
                               16).expand())

    assert legendre(10, -1) == 1
    assert legendre(11, -1) == -1
    assert legendre(10, 1) == 1
    assert legendre(11, 1) == 1
    assert legendre(10, 0) != 0
    assert legendre(11, 0) == 0

    assert legendre(-1, x) == 1
    k = Symbol("k")
    assert legendre(5 - k, x).subs(k, 2) == ((5 * x**3 - 3 * x) / 2).expand()

    assert roots(legendre(4, x), x) == {
        sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1,
        -sqrt(Rational(3, 7) - Rational(2, 35) * sqrt(30)): 1,
        sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1,
        -sqrt(Rational(3, 7) + Rational(2, 35) * sqrt(30)): 1,
    }

    n = Symbol("n")

    X = legendre(n, x)
    assert isinstance(X, legendre)
    assert unchanged(legendre, n, x)

    assert legendre(n,
                    0) == sqrt(pi) / (gamma(S.Half - n / 2) * gamma(n / 2 + 1))
    assert legendre(n, 1) == 1
    assert legendre(n, oo) is oo
    assert legendre(-n, x) == legendre(n - 1, x)
    assert legendre(n, -x) == (-1)**n * legendre(n, x)
    assert unchanged(legendre, -n + k, x)

    assert conjugate(legendre(n, x)) == legendre(n, conjugate(x))

    assert diff(legendre(
        n, x), x) == n * (x * legendre(n, x) - legendre(n - 1, x)) / (x**2 - 1)
    assert diff(legendre(n, x), n) == Derivative(legendre(n, x), n)

    _k = Dummy("k")
    assert (legendre(n, x).rewrite("polynomial").dummy_eq(
        Sum(
            (-1)**_k * (S.Half - x / 2)**_k * (x / 2 + S.Half)**(-_k + n) *
            binomial(n, _k)**2,
            (_k, 0, n),
        )))
    raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(1))
    raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(3))
Пример #25
0
def rivnynnya(equt):
    """
    Function to find all roots (returns a dict of them)
    Here: key - root; value - number of its repetitions 
    >>> 'r**2 - 2* r + 1'
    {1: 2}    
    """
    result = roots(equt)
    return result
Пример #26
0
def getSols(poly, sym, orderDiff):
    df = poly
    polyDiffs = []
    diffRoots = []
    for i in range(1 + orderDiff):
        polyDiffs += [df]
        roots = sympy.roots(df)
        diffRoots += [roots]
        df = df.diff()
    return polyDiffs, diffRoots
Пример #27
0
    def ZPK(self):
        """Convert to zero-pole-gain (ZPK) form.

        See also canonical, general, standard, timeconst, and partfrac"""

        N, D, delay, undef = self.as_ratfun_delay_undef()

        var = self.var
        Npoly = sym.Poly(N, var)
        Dpoly = sym.Poly(D, var)

        K = sym.cancel(Npoly.LC() / Dpoly.LC())
        if delay != 0:
            K *= sym.exp(self.var * delay)

        zeros = sym.roots(Npoly)
        poles = sym.roots(Dpoly)

        return _zp2tf(zeros, poles, K, self.var) * undef
Пример #28
0
def getSols(poly, sym, orderDiff):
    df = poly
    polyDiffs = []
    diffRoots = []
    for i in range(1+orderDiff):
        polyDiffs += [df]
        roots = sympy.roots(df)
        diffRoots += [roots]
        df = df.diff()
    return polyDiffs, diffRoots
Пример #29
0
 def test_roots_to_poly(self):
     roots = (1.0, 4.0, 5.0)
     p = sympyutils.roots_to_poly(roots)
     self.assertTrue(p.is_monic)
     root_to_count = sympy.roots(p)
     self.assertEqual(set(root_to_count.values()), set([1]))
     observed = set(root_to_count.keys())
     expected = set(roots)
     for r_observed, r_expected in zip(sorted(observed), sorted(expected)):
         self.assertAlmostEqual(r_observed, r_expected)
Пример #30
0
 def test_roots_to_poly(self):
     roots = (1.0, 4.0, 5.0)
     p = sympyutils.roots_to_poly(roots)
     self.assertTrue(p.is_monic)
     root_to_count = sympy.roots(p)
     self.assertEqual(set(root_to_count.values()), set([1]))
     observed = set(root_to_count.keys())
     expected = set(roots)
     for r_observed, r_expected in zip(sorted(observed), sorted(expected)):
         self.assertAlmostEqual(r_observed, r_expected)
Пример #31
0
    def ZPK(self):
        """Convert to pole-zero-gain (PZK) form.

        See also canonical, general, mixedfrac, and partfrac"""

        N, D, delay, undef = self.as_ratfun_delay_undef()

        var = self.var        
        Npoly = sym.Poly(N, var)
        Dpoly = sym.Poly(D, var)
        
        K = sym.cancel(Npoly.LC() / Dpoly.LC())
        if delay != 0:
            K *= sym.exp(self.var * delay)

        zeros = sym.roots(Npoly)
        poles = sym.roots(Dpoly)

        return _zp2tf(zeros, poles, K, self.var) * undef
Пример #32
0
def singular_term(F,X,Y,L,I,version):
    """
    Computes a single set of singular terms of the Puiseux expansions.

    For `I=1`, the function computes the first term of each finite 
    `\mathbb{K}` expansion. For `I=2`, it computes the other terms of the
    expansion.
    """
    T = []

    # if the curve is singular then compute the singular tuples
    # otherwise, use the standard newton polygon method
    if is_singular(F,X,Y):
        for (q,m,l,Phi) in desingularize(F,X,Y):
            for eta in Phi.all_roots(radicals=True):
                tau = (q,1,m,1,sympy.together(eta))
                T.append((tau,0,1))
    else:
        # each side of the newton polygon corresponds to a K-term.
        for (q,m,l,Phi) in polygon(F,X,Y,I):
            # the rational method
            if version == 'rational':
                u,v = _bezout(q,m)      

            # each newton polygon side has a characteristic
            # polynomial. For each square-free factor, each root
            # corresponds to a K-term
            for (Psi,r) in _square_free(Phi,_Z):
                Psi = sympy.Poly(Psi,_Z)
                
                # compute the roots of Psi. Use the RootOf construct if 
                # possible. In the case when Psi is over EX (i.e. when
                # RootOf doesn't work) then compute symbolic roots.
                try:
                    roots = Psi.all_roots(radicals=True)
                except NotImplementedError:
                    roots = sympy.roots(Psi,_Z).keys()

                for xi in roots:
                    # the classical version returns the "raw" roots
                    if version == 'classical':
                        P = sympy.Poly(_U**q-xi,_U)
                        beta = RootOf(P,0,radicals=True)
                        tau = (q,1,m,beta,1)
                        T.append((tau,l,r))
                    # the rational version rescales parameters so as
                    # to include ony rational terms in the Puiseux
                    # expansions.
                    if version == 'rational':
                        mu = xi**(-v)
                        beta = sympy.together(xi**u)
                        tau = (q,mu,m,beta,1)
                        T.append((tau,l,r))
    return T
Пример #33
0
def run_copper_smith(f, N, h, k):
    X = s.S(s.ceiling((s.Pow(2, - 1 / 2) * s.Pow(h * k, -1 / (h * k - 1))) *
                      s.Pow(N, (h - 1) / (h * k - 1))) - 1)
    gen = lll(generate(f, N, h, k, X), s.S(0.75))
    final_poly = [gen[0][i] / s.Pow(X, i) for i in range(len(gen[0]))][::-1]

    roots = s.roots(final_poly)
    for r in roots:
        print(r)

    return roots
Пример #34
0
    def timeconst(self):
        """Convert rational function to time constant form with unity
        lowest power of denominator.

        See also canonical, general, partfrac, standard, and ZPK"""

        N, D, delay, undef = self.as_ratfun_delay_undef()

        var = self.var
        Npoly = sym.Poly(N, var)
        Dpoly = sym.Poly(D, var)

        K = sym.cancel(Npoly.LC() / Dpoly.LC())
        if delay != 0:
            K *= sym.exp(self.var * delay)

        zeros = sym.roots(Npoly)
        poles = sym.roots(Dpoly)

        return _tc2tf(zeros, poles, K, self.var) * undef
Пример #35
0
def _singular_points_finite(f,x,y):
    """
    Returns the finite singular points of f.
    """
    S = []

    # compute the finite singularities: use the resultant
    p  = sympy.Poly(f,[x,y])
    n  = p.degree(y)

    res = sympy.Poly(sympy.resultant(p,p.diff(y),y),x)
    for xk,deg in sympy.roots(res,x).iteritems():
        if deg > 1:
            fxk = sympy.Poly(f.subs({x:xk,y:_Z}), _Z)
            for ykj,_ in sympy.roots(fxk, _Z).iteritems():
                fx = f.diff(x)
                fy = f.diff(y)
                subs = {x:xk,y:ykj}
                if (fx.subs(subs) == 0) and (fy.subs(subs) == 0):
                    S.append((xk,ykj,1))

    return S
Пример #36
0
def fund_ries(drc):
    a2,a1,a0 = drc
    r = roots(a2*t**2 + a1*t +a0,t)
    kl = list(r.keys())
    if len(kl) == 2:  # jednoduche korene
        r1,r2 = kl        
        re_k,im_k = r1.as_real_imag()
        if im_k == 0: # jednoduche realne korene
            return exp(r1*t), exp(r2*t)
        else:         # komplexne zdruz.korene
            return exp(re_k*t)*sin(im_k*t), exp(re_k*t)*cos(im_k*t)
    else: # dvojnasobny koren
        return exp(kl[0]*t), t*exp(kl[0]*t)
Пример #37
0
def solve_eq(init_conditions, associated):
    degree = len(init_conditions)

    eq = util.characteristic_eq(degree, associated)

    rts = roots(parse_expr(eq))
    nr_of_a = util.nr_of_alphas(rts)

    if len(rts) == 1:
        alphas = util.find_alphas_sol2(rts, init_conditions, nr_of_a)
        return util.build_solution2(rts, alphas)
    else:
        alphas = util.find_alphas_sol1(rts, init_conditions, nr_of_a)
        return util.build_solution1(rts, alphas)
Пример #38
0
def _singular_points_infinite(f,x,y):
    """
    Returns the singular points of f at infinity.
    """
    S = []

    # compute homogenous polynomial
    F, d = homogenize(f,x,y,_z)

    # find singular points at infinity
    F0 = sympy.Poly(F.subs([(_z,0)]),[x,y])
    domain = sympy.QQ[sympy.I]
    solsX1 = sympy.roots(F0.subs({x:1,y:_Z}),_Z).keys()
    solsY1 = sympy.roots(F0.subs({y:1,x:_Z}),_Z).keys()

    all_sols = [ (1,yi,0) for yi in solsX1 ]
    all_sols.extend( [ (xi,1,0) for xi in solsY1 ] )

    # these points are in projective space, so filter out equal points
    # such as (1,I,0) == (-I,1,0). We normalize these projective
    # points such that 1 appears in either the x- or y- coordinate
    sols = []
    for xi,yi,zi in all_sols:
        normalized = (1,yi/xi,0) if xi != sympy.S(0) else (xi/yi,1,0)
        if not normalized in sols:
            sols.append(normalized)

    # Filter out any points that are not singular by checking if the
    # gradient vanishes.
    grad = [F.diff(var) for var in [x,y,_z]]
    for xi,yi,zi in sols:
        fsub = lambda e,x=x,y=y,_z=_z,xi=xi,yi=yi,zi=zi:  \
               e.subs({x:xi,y:yi,_z:zi}).simplify() != sympy.S(0)
        if not any(map(fsub,grad)):
            S.append((xi,yi,zi))

    return S
Пример #39
0
def tustin(tf, sRate):
    s = getMapping(tf)['s']
    T = 1 / sRate
    poles = sympy.roots(sympy.denom(tf), s, multiple=True)
    centroid = np.mean(np.abs(poles))
    invz = sympy.Symbol('invz', real=True)
    # normalized center frequency derived from poles of filter SISO transfer function
    w0 = 2 * np.pi * centroid / (sRate * 2 * np.pi)
    # modified bilinear transform w/ frequency warping
    bt = w0 / sympy.tan(w0 * T / 2) * ((1 - invz) / (1 + invz))
    dt = sympy.simplify(tf.subs({s: bt}))
    b = sympy.Poly(sympy.numer(dt)).all_coeffs()[::-1]
    a = sympy.Poly(sympy.denom(dt)).all_coeffs()[::-1]
    normalize = lambda x: float(x / a[0])
    return (map(normalize, b), map(normalize, a))
Пример #40
0
 def test_ndiff_roots_symbolic(self):
     roots = (1.25, 4.5, 5.75)
     a, b, c = roots
     polys = roots_to_differential_polys(roots)
     # compute linear root manually
     r = float(a + b + c) / 3
     # check linear root
     observed = sorted(float(r) for r in sympy.roots(polys[0]))
     expected = sorted([r])
     self.assertTrue(np.allclose(observed, expected))
     # compute quadratic roots manually
     A = a * a + b * b + c * c
     B = a * b + a * c + b * c
     S = a + b + c
     r0 = float(S + math.sqrt(A - B)) / 3
     r1 = float(S - math.sqrt(A - B)) / 3
     # check quadratic roots
     observed = sorted(float(r) for r in sympy.roots(polys[1]))
     expected = sorted([r0, r1])
     self.assertTrue(np.allclose(observed, expected))
     # check cubic roots
     observed = sorted(float(r) for r in sympy.roots(polys[2]))
     expected = sorted(roots)
     self.assertTrue(np.allclose(observed, expected))
Пример #41
0
def tustin(tf, sRate):
	s =	getMapping(tf)['s']
	T = 1/sRate
	poles = sympy.roots(sympy.denom(tf), s, multiple=True)
	centroid = np.mean(np.abs(poles))
	invz = sympy.Symbol('invz', real=True)
	# normalized center frequency derived from poles of filter SISO transfer function
	w0 = 2*np.pi*centroid/(sRate*2*np.pi)
	# modified bilinear transform w/ frequency warping
	bt = w0/sympy.tan(w0*T/2) * ((1-invz)/(1+invz))
	dt = sympy.simplify(tf.subs({s: bt}))
	b = sympy.Poly(sympy.numer(dt)).all_coeffs()[::-1]
	a = sympy.Poly(sympy.denom(dt)).all_coeffs()[::-1]
	normalize = lambda x: float(x/a[0])
	return (map(normalize, b), map(normalize, a))
Пример #42
0
 def test_ndiff_roots_symbolic(self):
     roots = (1.25, 4.5, 5.75)
     a, b, c = roots
     polys = roots_to_differential_polys(roots)
     # compute linear root manually
     r = float(a + b + c) / 3
     # check linear root
     observed = sorted(float(r) for r in sympy.roots(polys[0]))
     expected = sorted([r])
     self.assertTrue(np.allclose(observed, expected))
     # compute quadratic roots manually
     A = a*a + b*b + c*c
     B = a*b + a*c + b*c
     S = a + b + c
     r0 = float(S + math.sqrt(A - B)) / 3
     r1 = float(S - math.sqrt(A - B)) / 3
     # check quadratic roots
     observed = sorted(float(r) for r in sympy.roots(polys[1]))
     expected = sorted([r0, r1])
     self.assertTrue(np.allclose(observed, expected))
     # check cubic roots
     observed = sorted(float(r) for r in sympy.roots(polys[2]))
     expected = sorted(roots)
     self.assertTrue(np.allclose(observed, expected))
    def _solve(self):
        """
        Solve the recurrence relation into a closed form

        Returns:
            String: The solved recurrence relation in string format
        """

        logging.info("Started solving recurrence relation: %s" % str(self._recurrence))

        self._degree, homogenous, nonHomogenous, linear = self._analyseExpression()

        msg = "homogenous" if nonHomogenous == 0 else "nonhomogenous"
        logging.info("Analyzation complete, It is a %s recurrence relation with degree %d" % (msg, self._degree))
        if nonHomogenous != 0:
            logging.info("The part that makes the recurrence nonhomogenous is: %s" % str(nonHomogenous))

        if not linear:
            raise RecurrenceSolveFailed("The equation is not linear")

        characteristicEq = self._getCharacteristicEquation(homogenous)
        logging.info("The characteristic equation is: %s" % str(characteristicEq))
       
        # get roots of characteristic equations and remove
        # the complex roots
        realRoots = { s:m for (s,m) in sympy.roots(characteristicEq).items() if sympy.I not in s.atoms() }
        logging.info("With roots: multiplicities: %s" % str(realRoots))

        # the sum of the multiplicity must be the same as the degree
        # else we can't solve the equation 
        if sum(realRoots.values()) != self._degree:
            msg = "The characteristic equation \"%s\" has the following real roots: %s, and the multiplicities is not the same as the degree" % (str(characteristicEq), str(realRoots))
            raise RecurrenceSolveFailed(msg)

        generalSolution, ctx = self._getGeneralSolution(realRoots)
        logging.info("The general solution has the form: %s" % str(generalSolution))

        solved = sympy.sympify("0")
        if nonHomogenous == 0:
            solved = self._calculateClosedFromGeneralSolution(generalSolution, ctx)
        else:
            solved = self._solveNonHomogeneous(realRoots, homogenous, nonHomogenous, generalSolution, ctx)
        
        logging.info("Solved raw: %s" % str(solved))
        solved = solved.simplify()
        logging.info("Solved simplified: %s" % str(solved))

        return solved
Пример #44
0
def ballpath(xinit=0, yinit=0, vxinit=1, vyinit=1):
    x0val = xinit
    y0val = yinit
    v0xval = vxinit
    v0yval = vyinit

    # create symbolic exprs for ball path and intersection polynomial
    x0, y0, v0x, v0y, t = symbols('x0 y0 v0x v0y t')
    xt = x0 + v0x * t
    yt = y0 + v0y * t - (1 / 2) * 9.8 * (t**2)
    pgen = poly(xt**2 + yt**2 - 1, t)

    # create actual functions from symbolic exprs
    xtf = lambdify((t, x0, v0x), xt)
    ytf = lambdify((t, y0, v0y), yt)
    vytf = lambdify((t, v0y), diff(yt, t))

    while True:
        # subst current conditions into intersect poly
        p = pgen.subs({x0: x0val, y0: y0val, v0x: v0xval, v0y: v0yval})

        # solve for t
        rts = roots(p, t)
        rts = np.array([complex(r) for r in rts.keys()])
        tcol = np.min(rts[np.logical_and(rts > 0, np.imag(rts) == 0)]).real

        # find intersect point and speed at the moment
        xcol = xtf(tcol, x0val, v0xval)
        ycol = ytf(tcol, y0val, v0yval)
        vxcol = v0xval
        vycol = vytf(tcol, v0yval)
        vcol = np.array([[vxcol], [vycol]])

        # calculate speed vector after bounce
        alpha = np.arctan2(ycol, xcol) - np.arctan2(vycol, vxcol)
        R = np.array([[np.cos(2*alpha), -np.sin(2*alpha)], \
                      [np.sin(2*alpha),  np.cos(2*alpha)]])
        newv0 = R @ -vcol
        tvals = np.linspace(0, tcol, 100)
        xvals = xtf(tvals, x0val, v0xval)
        yvals = ytf(tvals, y0val, v0yval)

        yield (xvals.tolist(), yvals.tolist())

        x0val = xcol
        y0val = ycol
        v0xval = newv0[0].item()
        v0yval = newv0[1].item()
Пример #45
0
def get_segmentation(p, t0, t1):
    """
    A segmentation is a sequence of triples (left, right, sign).
    @param p: a sympy Poly
    @param t0: initial time
    @param t1: final time
    @return: a segmentation
    """
    roots = sorted(float(r) for r in sympy.roots(p))
    points = [t0] + roots + [t1]
    segmentation = []
    for left, right in iterutils.pairwise(points):
        mid = (left + right) / 2
        sign = -1 if p.eval(mid) <= 0 else 1
        seg = (left, right, sign)
        segmentation.append(seg)
    return segmentation
Пример #46
0
def get_segmentation(p, t0, t1):
    """
    A segmentation is a sequence of triples (left, right, sign).
    @param p: a sympy Poly
    @param t0: initial time
    @param t1: final time
    @return: a segmentation
    """
    roots = sorted(float(r) for r in sympy.roots(p))
    points = [t0] + roots + [t1]
    segmentation = []
    for left, right in iterutils.pairwise(points):
        mid = (left + right) / 2
        sign = -1 if p.eval(mid) <= 0 else 1
        seg = (left, right, sign)
        segmentation.append(seg)
    return segmentation
Пример #47
0
def test_poly():
    output("""\
    poly_:{
        r:{$[prec>=abs(x:reim x)1;x 0;x]} each .qml.poly x;
        r iasc {x:reim x;(abs x 1;neg x 1;x 0)} each r};""")

    for A in poly_subjects:
        A = sp.Poly(A, sp.Symbol("x"))
        if A.degree() <= 3 and all(a.is_real for a in A.all_coeffs()):
            R = []
            for r in sp.roots(A, multiple=True):
                r = sp.simplify(sp.expand_complex(r))
                R.append(r)
            R.sort(key=lambda x: (abs(sp.im(x)), -sp.im(x), sp.re(x)))
        else:
            R = mp.polyroots([mp.mpc(*(a.evalf(mp.mp.dps)).as_real_imag())
                              for a in A.all_coeffs()])
            R.sort(key=lambda x: (abs(x.imag), -x.imag, x.real))
        assert len(R) == A.degree()
        test("poly_", A.all_coeffs(), R, complex_pair=True)
Пример #48
0
def given():
    xp0 = randrange(7, 10)
    pmax = randrange(7, 10)
    Ep = R(-pmax, xp0) * x + pmax
    E = sympy.integrate(Ep, x)
    b = randrange(2, xp0 - 2)
    cmax = int(Ep.subs(x, b).n())
    c = randrange(1, cmax)
    a = R(randrange(1, pmax - c), b * b)
    Kp = a * (x - b) ** 2 + c
    Gp = Ep - Kp
    rG = [r.n() for r in sympy.roots(Gp) if r > 0][0]
    G = sympy.integrate(Gp, x)
    mG = G.subs(x, rG)
    Ko = int(mG - 1) / 2
    #K = sympy.integrate(Kp,x)+Ko
    #G = E.n()-K.n()
    #rts = sorted([r.n() for r in sympy.roots(G) if r > 0])
    g = Struct(pmax=pmax, xp0=xp0, Ko=Ko, Kp=sympy.sstr(Kp))
    return g
Пример #49
0
def test_legendre():
    assert legendre(0, x) == 1
    assert legendre(1, x) == x
    assert legendre(2, x) == ((3*x**2-1)/2).expand()
    assert legendre(3, x) == ((5*x**3-3*x)/2).expand()
    assert legendre(4, x) == ((35*x**4-30*x**2+3)/8).expand()
    assert legendre(5, x) == ((63*x**5-70*x**3+15*x)/8).expand()
    assert legendre(6, x) == ((231*x**6-315*x**4+105*x**2-5)/16).expand()

    assert legendre(10, -1) == 1
    assert legendre(11, -1) == -1
    assert legendre(10, 1) == 1
    assert legendre(11, 1) == 1
    assert legendre(10, 0) != 0
    assert legendre(11, 0) == 0

    assert roots(legendre(4,x), x) == {
         sqrt(Rational(3, 7) - Rational(2, 35)*sqrt(30)): 1,
        -sqrt(Rational(3, 7) - Rational(2, 35)*sqrt(30)): 1,
         sqrt(Rational(3, 7) + Rational(2, 35)*sqrt(30)): 1,
        -sqrt(Rational(3, 7) + Rational(2, 35)*sqrt(30)): 1,
    }
Пример #50
0
def get_pane_tikz_lines(poly_pair, color_pair, t0, t1):
    """
    This is called maybe three times.
    @param poly_pair: the lower and higher order Poly objects
    @param color_pair: the polynomial colors
    @param t0: initial time
    @param t1: final time
    @return: a list of tikz lines
    """
    lines = []
    pa, pb = poly_pair
    ca, cb = color_pair
    # draw the segmentation corresponding to the lower order polynomial
    for left, right, sign in get_segmentation(pa, t0, t1):
        width = {-1: "0.5mm", 1: "2mm"}[sign]
        line = "\\draw[color=%s,line width=%s] (%s, 0) -- (%s, 0);" % (ca, width, left, right)
        lines.append(line)
    # draw the cuts corresponding to the higher order polynomial
    for r in sorted(sympy.roots(pb)):
        cut = float(r)
        line = "\\draw[color=%s,line width=0.5mm] (%s, -3mm) -- (%s, 3mm);" % (cb, cut, cut)
        lines.append(line)
    return lines
Пример #51
0
def calc(g):
    Kp = S(g.Kp)
    Ep = R(-g.pmax, g.xp0) * x + g.pmax
    E = sympy.integrate(Ep, x)
    K = sympy.integrate(Kp, x) + S(g.Ko)
    Gp = Ep - Kp
    rG = [r.n() for r in sympy.roots(Gp) if r > 0][0]
    G = E - K
    mG = G.subs(x, rG)
    kk = sympy.Wild('kk')
    dd = sympy.Wild('dd')
    kd = Ep.match(kk * x + dd)
    p = kd[kk] * x / 2 + kd[dd]
    mp = p.subs(x, rG)
    el = S(1 + kd[dd] / (kd[kk] * x / 2))
    return [
        sympy.sstr(Ep),
        sympy.sstr(E),
        sympy.sstr(K),
        sympy.sstr(p),
        sympy.sstr(el),
        rG,
        mp]
Пример #52
0
def coefficient(polinom_in):
    """

    :param polinom_in:
    :return:
    """
    edge_dot = []
    polinom_antispace = re.sub(r'\s', '', polinom_in)
    edge_y = test_eval(0, polinom_antispace) # нахождение максимального y при x=0
    edge_y = edge_y * 1.03
    r = roots(polinom_antispace) #получаю словарь возможных корней(пересечение с x)
    edge_list_x = []
    for k in r.keys():
        if k.__class__.__name__ == "Float":
            if float(k) > 0:
                edge_list_x.append(float(k))

    edge_x = min(edge_list_x)
    edge_x = edge_x * 1.03
    print edge_x
    edge_dot.append(edge_x)
    edge_dot.append(edge_y)
    return edge_dot  # возвращает список с точкой пересечения оси икс и игрик
phi_sum = np.zeros(np.diag(Phi[:,0]).shape)
for i in xrange(Phi.shape[1]):
    phi_sum+= alpha[i] * np.diag(Phi[:,i])


(lambda_2 * phi_sum)**(-.5)

#
# implementing the set-level optimization
# alternate between alpha and sigma optimization

from sympy import roots,symbols,I
from sympy.utilities.lambdify import lambdify

x,a_rootvar,b_rootvar,d_rootvar = symbols('x,a_rootvar,b_rootvar,d_rootvar')
root_list = roots(a_rootvar*x**3 +b_rootvar*x**2 +d_rootvar,x).keys()


root_exprs = [ root_expr.as_real_imag() for root_expr in root_list]


def get_real_root(a,b,d):
    """ Get the real solution
    to the equation in x
    a*x**3 + b*x**2 + d = 0
    """
    real_soln_idx = np.argmin(np.abs([root_exprs[n][1].evalf(subs={a_rootvar:a,b_rootvar:b,d_rootvar:d}) for n in xrange(len(root_exprs))]))
    return root_exprs[real_soln_idx][0].evalf(subs={a_rootvar:a,b_rootvar:b,d_rootvar:d})


# now we are going to 
Пример #54
0
def log_to_real(h, q, x, t):
    """Convert complex logarithms to real functions.

       Given real field K and polynomials h in K[t,x] and q in K[t],
       returns real function f such that:
                              ___
                      df   d  \  `
                      -- = --  )  a log(h(a, x))
                      dx   dx /__,
                             a | q(a) = 0

    """
    u, v = symbols('u v')

    H = h.subs({t:u+I*v}).as_basic().expand()
    Q = q.subs({t:u+I*v}).as_basic().expand()

    H_map = collect(H, I, evaluate=False)
    Q_map = collect(Q, I, evaluate=False)

    a, b = H_map.get(S(1), S(0)), H_map.get(I, S(0))
    c, d = Q_map.get(S(1), S(0)), Q_map.get(I, S(0))

    R = Poly(resultant(c, d, v), u)

    R_u = roots(R, domain='R')

    if len(R_u) != number_of_real_roots(R):
        return None

    result = S(0)

    for r_u in R_u.iterkeys():
        C = Poly(c.subs({u:r_u}), v)
        R_v = roots(C, domain='R')

        if len(R_v) != number_of_real_roots(C):
            return None

        for r_v in R_v:
            if not r_v.is_positive:
                continue

            D = d.subs({u:r_u, v:r_v})

            if D.evalf(chop=True) != 0:
                continue

            A = Poly(a.subs({u:r_u, v:r_v}), x)
            B = Poly(b.subs({u:r_u, v:r_v}), x)

            AB = (A**2 + B**2).as_basic()

            result += r_u*log(AB) + r_v*log_to_atan(A, B)

    R_q = roots(q, domain='R')

    if len(R_q) != number_of_real_roots(q):
        return None

    for r in R_q.iterkeys():
        result += r*log(h.subs(t, r).as_basic())

    return result
Пример #55
0
def log_to_real(h, q, x, t):
    """
    Convert complex logarithms to real functions.

    Given real field K and polynomials h in K[t,x] and q in K[t],
    returns real function f such that:
                          ___
                  df   d  \  `
                  -- = --  )  a log(h(a, x))
                  dx   dx /__,
                         a | q(a) = 0

    Examples
    ========

        >>> from sympy.integrals.rationaltools import log_to_real
        >>> from sympy.abc import x, y
        >>> from sympy import Poly, sqrt, S
        >>> log_to_real(Poly(x + 3*y/2 + S(1)/2, x, domain='QQ[y]'),
        ... Poly(3*y**2 + 1, y, domain='ZZ'), x, y)
        2*sqrt(3)*atan(2*sqrt(3)*x/3 + sqrt(3)/3)/3
        >>> log_to_real(Poly(x**2 - 1, x, domain='ZZ'),
        ... Poly(-2*y + 1, y, domain='ZZ'), x, y)
        log(x**2 - 1)/2

    See Also
    ========

    log_to_atan
    """
    u, v = symbols('u,v', cls=Dummy)

    H = h.as_expr().subs({t: u + I*v}).expand()
    Q = q.as_expr().subs({t: u + I*v}).expand()

    H_map = collect(H, I, evaluate=False)
    Q_map = collect(Q, I, evaluate=False)

    a, b = H_map.get(S(1), S(0)), H_map.get(I, S(0))
    c, d = Q_map.get(S(1), S(0)), Q_map.get(I, S(0))

    R = Poly(resultant(c, d, v), u)

    R_u = roots(R, filter='R')

    if len(R_u) != R.count_roots():
        return None

    result = S(0)

    for r_u in R_u.keys():
        C = Poly(c.subs({u: r_u}), v)
        R_v = roots(C, filter='R')

        if len(R_v) != C.count_roots():
            return None

        for r_v in R_v:
            if not r_v.is_positive:
                continue

            D = d.subs({u: r_u, v: r_v})

            if D.evalf(chop=True) != 0:
                continue

            A = Poly(a.subs({u: r_u, v: r_v}), x)
            B = Poly(b.subs({u: r_u, v: r_v}), x)

            AB = (A**2 + B**2).as_expr()

            result += r_u*log(AB) + r_v*log_to_atan(A, B)

    R_q = roots(q, filter='R')

    if len(R_q) != q.count_roots():
        return None

    for r in R_q.keys():
        result += r*log(h.as_expr().subs(t, r))

    return result
Пример #56
0
def _rewrite_gamma(f, s, a, b):
    """
    Try to rewrite the product f(s) as a product of gamma functions,
    so that the inverse mellin transform of f can be expressed as a meijer
    G function.

    Return (an, ap), (bm, bq), arg, exp, fac such that
    G((an, ap), (bm, bq), arg/z**exp)*fac is the inverse mellin transform of f(s).

    Raises IntegralTransformError or MellinTransformStripError on failure.

    It is asserted that f has no poles in the fundamental strip designated by
    (a, b). One of a and b is allowed to be None. The fundamental strip is
    important, because it determines the inversion contour.

    This function can handle exponentials, linear factors, trigonometric
    functions.

    This is a helper function for inverse_mellin_transform that will not
    attempt any transformations on f.

    >>> from sympy.integrals.transforms import _rewrite_gamma
    >>> from sympy.abc import s
    >>> from sympy import oo
    >>> _rewrite_gamma(s*(s+3)*(s-1), s, -oo, oo)
    (([], [-3, 0, 1]), ([-2, 1, 2], []), 1, 1, -1)
    >>> _rewrite_gamma((s-1)**2, s, -oo, oo)
    (([], [1, 1]), ([2, 2], []), 1, 1, 1)

    Importance of the fundamental strip:

    >>> _rewrite_gamma(1/s, s, 0, oo)
    (([1], []), ([], [0]), 1, 1, 1)
    >>> _rewrite_gamma(1/s, s, None, oo)
    (([1], []), ([], [0]), 1, 1, 1)
    >>> _rewrite_gamma(1/s, s, 0, None)
    (([1], []), ([], [0]), 1, 1, 1)
    >>> _rewrite_gamma(1/s, s, -oo, 0)
    (([], [1]), ([0], []), 1, 1, -1)
    >>> _rewrite_gamma(1/s, s, None, 0)
    (([], [1]), ([0], []), 1, 1, -1)
    >>> _rewrite_gamma(1/s, s, -oo, None)
    (([], [1]), ([0], []), 1, 1, -1)

    >>> _rewrite_gamma(2**(-s+3), s, -oo, oo)
    (([], []), ([], []), 1/2, 1, 8)
    """
    from itertools import repeat
    from sympy import (Poly, gamma, Mul, re, RootOf, exp as exp_, E, expand,
                       roots, ilcm, pi, sin, cos, tan, cot, igcd, exp_polar)
    # Our strategy will be as follows:
    # 1) Guess a constant c such that the inversion integral should be
    #    performed wrt s'=c*s (instead of plain s). Write s for s'.
    # 2) Process all factors, rewrite them independently as gamma functions in
    #    argument s, or exponentials of s.
    # 3) Try to transform all gamma functions s.t. they have argument
    #    a+s or a-s.
    # 4) Check that the resulting G function parameters are valid.
    # 5) Combine all the exponentials.

    a_, b_ = S([a, b])
    def left(c, is_numer):
        """
        Decide whether pole at c lies to the left of the fundamental strip.
        """
        # heuristically, this is the best chance for us to solve the inequalities
        c = expand(re(c))
        if a_ is None:
            return c < b_
        if b_ is None:
            return c <= a_
        if (c >= b_) is True:
            return False
        if (c <= a_) is True:
            return True
        if is_numer:
            return None
        if a_.free_symbols or b_.free_symbols or c.free_symbols:
            return None # XXX
            #raise IntegralTransformError('Inverse Mellin', f,
            #                     'Could not determine position of singularity %s'
            #                     ' relative to fundamental strip' % c)
        raise MellinTransformStripError('Pole inside critical strip?')

    # 1)
    s_multipliers = []
    for g in f.atoms(gamma):
        if not g.has(s):
            continue
        arg = g.args[0]
        if arg.is_Add:
            arg = arg.as_independent(s)[1]
        coeff, _ = arg.as_coeff_mul(s)
        s_multipliers += [coeff]
    for g in f.atoms(sin, cos, tan, cot):
        if not g.has(s):
            continue
        arg = g.args[0]
        if arg.is_Add:
            arg = arg.as_independent(s)[1]
        coeff, _ = arg.as_coeff_mul(s)
        s_multipliers += [coeff/pi]
    s_multipliers = [abs(x) for x in s_multipliers if x.is_real]
    common_coefficient = S(1)
    for x in s_multipliers:
        if not x.is_Rational:
            common_coefficient = x
            break
    s_multipliers = [x/common_coefficient for x in s_multipliers]
    if any(not x.is_Rational for x in s_multipliers):
        raise NotImplementedError
    s_multiplier = common_coefficient/reduce(ilcm, [S(x.q) for x in s_multipliers], S(1))
    if s_multiplier == common_coefficient:
        if len(s_multipliers) == 0:
            s_multiplier = common_coefficient
        else:
            s_multiplier = common_coefficient \
                           *reduce(igcd, [S(x.p) for x in s_multipliers])

    exponent = S(1)
    fac = S(1)
    f = f.subs(s, s/s_multiplier)
    fac /= s_multiplier
    exponent = 1/s_multiplier
    if a_ is not None:
        a_ *= s_multiplier
    if b_ is not None:
        b_ *= s_multiplier

    # 2)
    numer, denom = f.as_numer_denom()
    numer = Mul.make_args(numer)
    denom = Mul.make_args(denom)
    args = zip(numer, repeat(True)) + zip(denom, repeat(False))

    facs = []
    dfacs = []
    # *_gammas will contain pairs (a, c) representing Gamma(a*s + c)
    numer_gammas = []
    denom_gammas = []
    # exponentials will contain bases for exponentials of s
    exponentials = []
    def exception(fact):
        return IntegralTransformError("Inverse Mellin", f, "Unrecognised form '%s'." % fact)
    while args:
        fact, is_numer = args.pop()
        if is_numer:
            ugammas, lgammas = numer_gammas, denom_gammas
            ufacs, lfacs = facs, dfacs
        else:
            ugammas, lgammas = denom_gammas, numer_gammas
            ufacs, lfacs = dfacs, facs

        def linear_arg(arg):
            """ Test if arg is of form a*s+b, raise exception if not. """
            if not arg.is_polynomial(s):
                raise exception(fact)
            p = Poly(arg, s)
            if p.degree() != 1:
                raise exception(fact)
            return p.all_coeffs()

        # constants
        if not fact.has(s):
            ufacs += [fact]
        # exponentials
        elif fact.is_Pow or isinstance(fact, exp_):
            if fact.is_Pow:
                base = fact.base
                exp  = fact.exp
            else:
                base = exp_polar(1)
                exp  = fact.args[0]
            if exp.is_Integer:
                cond = is_numer
                if exp < 0:
                    cond = not cond
                args += [(base, cond)]*abs(exp)
                continue
            elif not base.has(s):
                a, b = linear_arg(exp)
                if not is_numer:
                    base = 1/base
                exponentials += [base**a]
                facs += [base**b]
            else:
                raise exception(fact)
        # linear factors
        elif fact.is_polynomial(s):
            p = Poly(fact, s)
            if p.degree() != 1:
                # We completely factor the poly. For this we need the roots.
                # Now roots() only works in some cases (low degree), and RootOf
                # only works without parameters. So try both...
                coeff = p.LT()[1]
                rs = roots(p, s)
                if len(rs) != p.degree():
                    rs = RootOf.all_roots(p)
                ufacs += [coeff]
                args += [(s - c, is_numer) for c in rs]
                continue
            a, c = p.all_coeffs()
            ufacs += [a]
            c /= -a
            # Now need to convert s - c
            if left(c, is_numer):
                ugammas += [(S(1), -c + 1)]
                lgammas += [(S(1), -c)]
            else:
                ufacs += [-1]
                ugammas += [(S(-1), c + 1)]
                lgammas += [(S(-1), c)]
        elif isinstance(fact, gamma):
            a, b = linear_arg(fact.args[0])
            if is_numer:
                if (a > 0 and (left(-b/a, is_numer) is False)) or \
                   (a < 0 and (left(-b/a, is_numer) is True)):
                    raise NotImplementedError('Gammas partially over the strip.')
            ugammas += [(a, b)]
        elif isinstance(fact, sin):
            # We try to re-write all trigs as gammas. This is not in
            # general the best strategy, since sometimes this is impossible,
            # but rewriting as exponentials would work. However trig functions
            # in inverse mellin transforms usually all come from simplifying
            # gamma terms, so this should work.
            a = fact.args[0]
            if is_numer:
                # No problem with the poles.
                gamma1, gamma2, fac_ = gamma(a/pi), gamma(1 - a/pi), pi
            else:
                gamma1, gamma2, fac_ = _rewrite_sin(linear_arg(a), s, a_, b_)
            args += [(gamma1, not is_numer), (gamma2, not is_numer)]
            ufacs += [fac_]
        elif isinstance(fact, tan):
            a = fact.args[0]
            args += [(sin(a, evaluate=False), is_numer),
                     (sin(pi/2 - a, evaluate=False), not is_numer)]
        elif isinstance(fact, cos):
            a = fact.args[0]
            args += [(sin(pi/2 - a, evaluate=False), is_numer)]
        elif isinstance(fact, cot):
            a = fact.args[0]
            args += [(sin(pi/2 - a, evaluate=False), is_numer),
                     (sin(a, evaluate=False), not is_numer)]
        else:
            raise exception(fact)

    fac *= Mul(*facs)/Mul(*dfacs)

    # 3)
    an, ap, bm, bq = [], [], [], []
    for gammas, plus, minus, is_numer in [(numer_gammas, an, bm, True),
                                          (denom_gammas, bq, ap, False)]:
        while gammas:
            a, c = gammas.pop()
            if a != -1 and a != +1:
                # We use the gamma function multiplication theorem.
                p = abs(S(a))
                newa = a/p
                newc = c/p
                assert a.is_Integer
                for k in range(p):
                    gammas += [(newa, newc + k/p)]
                if is_numer:
                    fac *= (2*pi)**((1 - p)/2) * p**(c - S(1)/2)
                    exponentials += [p**a]
                else:
                    fac /= (2*pi)**((1 - p)/2) * p**(c - S(1)/2)
                    exponentials += [p**(-a)]
                continue
            if a == +1:
                plus.append(1 - c)
            else:
                minus.append(c)

    # 4)
    # TODO

    # 5)
    arg = Mul(*exponentials)

    # for testability, sort the arguments
    an.sort()
    ap.sort()
    bm.sort()
    bq.sort()

    return (an, ap), (bm, bq), arg, exponent, fac
Пример #57
0
 def eval(cls, f, *gens):
     from sympy import roots
     rootslist = list(roots(f, *gens, filter='R').keys())
     rootslist.sort(key=customized_sort_key)
     return TupleNoParen(*rootslist)
Пример #58
0
def integral_basis(f,x,y):
    """
    Compute the integral basis {b1, ..., bg} of the algebraic function
    field C[x,y] / (f).
    """
    # If the curve is not monic then map y |-> y/lc(x) where lc(x)
    # is the leading coefficient of f
    T  = sympy.Dummy('T')
    d  = sympy.degree(f,y)
    lc = sympy.LC(f,y)
    if x in lc:
        f = sympy.ratsimp( f.subs(y,y/lc)*lc**(d-1) )
    else:
        f = f/lc
        lc = 1

    #
    # Compute df
    #
    p = sympy.Poly(f,[x,y])
    n = p.degree(y)
    res = sympy.resultant(p,p.diff(y),y)
    factors = sympy.factor_list(res)[1]
    df = [k for k,deg in factors if (deg > 1) and (sympy.LC(k) == 1)]

    #
    # Compute series truncations at appropriate x points
    #
    alpha = []
    r = []
    for l in range(len(df)):
        k = df[l]
        alphak = sympy.roots(k).keys()[0]
        rk = compute_series_truncations(f,x,y,alphak,T)
        alpha.append(alphak)
        r.append(rk)

        
    #
    # Main Loop
    #
    a = [sympy.Dummy('a%d'%k) for k in xrange(n)]
    b = [1]
    for d in range(1,n):
        bd = y*b[-1]

        for l in range(len(df)):
            k = df[l]
            alphak = alpha[l]
            rk = r[l]

            found_something = True            
            while found_something:
                # construct system of equations consisting of the coefficients
                # of negative powers of (x-alphak) in the substitutions
                # A(r_{k,1}),...,A(r_{k,n})
                A  = (sum(ak*bk for ak,bk in zip(a,b)) + bd) / (x - alphak)

                coeffs = []
                for rki in rk:
                    # substitute and extract coefficients
                    A_rki  = A.subs(y,rki)
                    coeffs.extend(_negative_power_coeffs(A_rki, x, alphak))
               
                # solve the coefficient equations for a0,...,a_{d-1}
                coeffs = [coeff.as_numer_denom()[0] for coeff in coeffs]
                sols = sympy.solve_poly_system(coeffs, a[:d])
                if sols is None or sols == []:
                    found_something = False
                else:
                    sol  = sols[0]
                    bdm1 = sum( sol[i]*bk for i,bk in zip(range(d),b) )
                    bd   = (bdm1 + bd) / k
                        
        # bd found. Append to list of basis elements
        b.append( bd )

    # finally, convert back to singularized curve if necessary
    for i in xrange(1,len(b)):
        b[i] = b[i].subs(y,y*lc).ratsimp()

    return b
Пример #59
0
def build_series(pis,x,y,T,a,parametric):
    """
    Builds all Puiseux series from pi data.

    `\pi_i=(q,\mu,m,\beta,\eta), X \mapsto\mu X^q,Y \mapsto X^m(\beta+\eta Y)`

    Algorithm:

    Uses the formulas from p. 135 "Rational puiseux expandsions" by
    D. Duval. The indexing is adjusted: m,beta,mu,eta are all shifted
    down by one. However, the intexing on qh should match that of
    D. Duval.
    """
    series = []

    # build singular part of expansion series
    for pi in pis:
        q,mu,m,beta,eta = zip(*pi)
        R = len(pi)

        qh = build_qh_dict(q)

        # compute X = lam*T**e
        e = qh[(0,R)]
        lam = reduce(lambda z1,z2: z1*z2, 
                     (mu[k]**qh[(0,k)] for k in xrange(R)))
        X = sympy.simplify(lam)*T**e + a

        # compute Y = \sum_{h=1}^R alpha_h * T**n_h. 
        if parametric:
            Y = sympy.S(0)
        else:
            lams = sympy.roots(lam*_Z**e - 1,_Z,multiple=True)
            Y = [sympy.S(0) for _ in xrange(e)]

        n_h = sympy.S(0)
        eta_h = sympy.S(1)
        for h in xrange(0,R):
            eta_h *= eta[h]            
            n_h += m[h] * qh[(h+1,R)]

            alpha_h = sympy.S(1)
            for i in xrange(0,h):
                alpha_h *= mu[i+1]**sum(m[j]*qh[(j+1,i)] 
                                      for j in xrange(0,i))
            for i in xrange(h,R-1):
                alpha_h *= mu[i+1]**sum(m[j]*qh[(j+1,i)] 
                                      for j in xrange(0,h))
            
            alpha_h *= eta_h*beta[h]
            if parametric:
                Y += sympy.simplify(alpha_h)*T**n_h
            else:
                s_h = sympy.Rational(n_h,e)
                for i in xrange(e):
                    alpha_h_i = sympy.simplify(alpha_h*(lams[i]**n_h))
                    Y[i] += alpha_h_i*(x-a)**s_h

        # All puiseux series associated with this place are computed.
        # Add to series list.
        if parametric:
            series.append((X,Y))
        else:
            series.append(Y)

    return series
# In[8]:

invL(G)


# The characteristic equation is the denominator of the transfer function

# In[5]:

ce = sympy.Eq(sympy.denom(G), 0)
ce


# In[6]:

roots = sympy.roots(ce, s)
roots


# The shape of the inverse Laplace depends on the nature of the roots, which depends on the value of $\zeta$

# Overdamped: $\zeta>1$. Two distinct real roots

# In[3]:

G


# In[7]:

invL(G.subs({zeta: 2}))