示例#1
0
def test_linear_eq_to_matrix():
    x, y, z = symbols('x, y, z')
    eqns1 = [2 * x + y - 2 * z - 3, x - y - z, x + y + 3 * z - 12]
    eqns2 = [
        Eq(3 * x + 2 * y - z, 1),
        Eq(2 * x - 2 * y + 4 * z, -2), -2 * x + y - 2 * z
    ]

    A, b = linear_eq_to_matrix(eqns1, x, y, z)
    assert A == Matrix([[2, 1, -2], [1, -1, -1], [1, 1, 3]])
    assert b == Matrix([[3], [0], [12]])

    A, b = linear_eq_to_matrix(eqns2, x, y, z)
    assert A == Matrix([[3, 2, -1], [2, -2, 4], [-2, 1, -2]])
    assert b == Matrix([[1], [-2], [0]])

    # Pure symbolic coefficients
    from sympy.abc import a, b, c, d, e, f, g, h, i, j, k, l
    eqns3 = [
        a * x + b * y + c * z - d, e * x + f * y + g * z - h,
        i * x + j * y + k * z - l
    ]
    A, B = linear_eq_to_matrix(eqns3, x, y, z)
    assert A == Matrix([[a, b, c], [e, f, g], [i, j, k]])
    assert B == Matrix([[d], [h], [l]])

    # raise ValueError if no symbols are given
    raises(ValueError, lambda: linear_eq_to_matrix(eqns3))
示例#2
0
def test_linear_eq_to_matrix():
    x, y, z = symbols('x, y, z')
    eqns1 = [2*x + y - 2*z - 3, x - y - z, x + y + 3*z - 12]
    eqns2 = [Eq(3*x + 2*y - z, 1), Eq(2*x - 2*y + 4*z, -2), -2*x + y - 2*z]

    A, b = linear_eq_to_matrix(eqns1, x, y, z)
    assert A == Matrix([[2, 1, -2], [1, -1, -1], [1, 1, 3]])
    assert b == Matrix([[3], [0], [12]])

    A, b = linear_eq_to_matrix(eqns2, x, y, z)
    assert A == Matrix([[3, 2, -1], [2, -2, 4], [-2, 1, -2]])
    assert b == Matrix([[1], [-2], [0]])

    # Pure symbolic coefficients
    from sympy.abc import a, b, c, d, e, f, g, h, i, j, k, l
    eqns3 = [a*x + b*y + c*z - d, e*x + f*y + g*z - h, i*x + j*y + k*z - l]
    A, B = linear_eq_to_matrix(eqns3, x, y, z)
    assert A == Matrix([[a, b, c], [e, f, g], [i, j, k]])
    assert B == Matrix([[d], [h], [l]])

    # raise ValueError if no symbols are given
    raises(ValueError, lambda: linear_eq_to_matrix(eqns3))
示例#3
0
def linsolve(system, *symbols):

    if not system:
        return S.EmptySet

    # If second argument is an iterable
    if symbols and hasattr(symbols[0], '__iter__'):
        symbols = symbols[0]
    sym_gen = isinstance(symbols, GeneratorType)

    swap = {}
    b = None  # if we don't get b the input was bad
    syms_needed_msg = None

    # unpack system

    if hasattr(system, '__iter__'):

        # 1). (A, b)
        if len(system) == 2 and isinstance(system[0], Matrix):
            A, b = system

        # 2). (eq1, eq2, ...)
        if not isinstance(system[0], Matrix):
            if sym_gen or not symbols:
                raise ValueError(
                    filldedent('''
                    When passing a system of equations, the explicit
                    symbols for which a solution is being sought must
                    be given as a sequence, too.
                '''))
            system = [
                _mexpand(i.lhs - i.rhs if isinstance(i, Eq) else i,
                         recursive=True) for i in system
            ]
            system, symbols, swap = recast_to_symbols(system, symbols)
            A, b = linear_eq_to_matrix(system, symbols)
            syms_needed_msg = 'free symbols in the equations provided'

    elif isinstance(system, Matrix) and not (symbols and not isinstance(
            symbols, GeneratorType) and isinstance(symbols[0], Matrix)):
        # 3). A augmented with b
        A, b = system[:, :-1], system[:, -1:]

    if b is None:
        raise ValueError("Invalid arguments")

    syms_needed_msg = syms_needed_msg or 'columns of A'

    if sym_gen:
        symbols = [next(symbols) for i in range(A.cols)]
        if any(set(symbols) & (A.free_symbols | b.free_symbols)):
            raise ValueError(
                filldedent('''
                At least one of the symbols provided
                already appears in the system to be solved.
                One way to avoid this is to use Dummy symbols in
                the generator, e.g. numbered_symbols('%s', cls=Dummy)
            ''' % symbols[0].name.rstrip('1234567890')))

    try:
        solution, params, free_syms = A.gauss_jordan_solve(b, freevar=True)
    except ValueError:
        # No solution
        return S.EmptySet

    # Replace free parameters with free symbols
    if params:
        if not symbols:
            symbols = [_ for _ in params]
            # re-use the parameters but put them in order
            # params       [x, y, z]
            # free_symbols [2, 0, 4]
            # idx          [1, 0, 2]
            idx = list(zip(*sorted(zip(free_syms, range(len(free_syms))))))[1]
            # simultaneous replacements {y: x, x: y, z: z}
            replace_dict = dict(zip(symbols, [symbols[i] for i in idx]))
        elif len(symbols) >= A.cols:
            replace_dict = {
                v: symbols[free_syms[k]]
                for k, v in enumerate(params)
            }
        else:
            raise IndexError(
                filldedent('''
                the number of symbols passed should have a length
                equal to the number of %s.
                ''' % syms_needed_msg))
        solution = [sol.xreplace(replace_dict) for sol in solution]

    solution = [(sol).xreplace(swap) for sol in solution]
    return FiniteSet(tuple(solution))
示例#4
0
def linear_ode_to_matrix(eqs, funcs, t, order):
    r"""
    Convert a linear system of ODEs to matrix form

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

    Express a system of linear ordinary differential equations as a single
    matrix differential equation [1]. For example the system $x' = x + y + 1$
    and $y' = x - y$ can be represented as

    .. math:: A_1 X' + A_0 X = b

    where $A_1$ and $A_0$ are $2 \times 2$ matrices and $b$, $X$ and $X'$ are
    $2 \times 1$ matrices with $X = [x, y]^T$.

    Higher-order systems are represented with additional matrices e.g. a
    second-order system would look like

    .. math:: A_2 X'' + A_1 X' + A_0 X = b

    Examples
    ========

    >>> from sympy import (Function, Symbol, Matrix, Eq)
    >>> from sympy.solvers.ode.systems import linear_ode_to_matrix
    >>> t = Symbol('t')
    >>> x = Function('x')
    >>> y = Function('y')

    We can create a system of linear ODEs like

    >>> eqs = [
    ...     Eq(x(t).diff(t), x(t) + y(t) + 1),
    ...     Eq(y(t).diff(t), x(t) - y(t)),
    ... ]
    >>> funcs = [x(t), y(t)]
    >>> order = 1 # 1st order system

    Now ``linear_ode_to_matrix`` can represent this as a matrix
    differential equation.

    >>> (A1, A0), b = linear_ode_to_matrix(eqs, funcs, t, order)
    >>> A1
    Matrix([
    [1, 0],
    [0, 1]])
    >>> A0
    Matrix([
    [-1, -1],
    [-1,  1]])
    >>> b
    Matrix([
    [1],
    [0]])

    The original equations can be recovered from these matrices:

    >>> eqs_mat = Matrix([eq.lhs - eq.rhs for eq in eqs])
    >>> X = Matrix(funcs)
    >>> A1 * X.diff(t) + A0 * X - b == eqs_mat
    True

    If the system of equations has a maximum order greater than the
    order of the system specified, a ODEOrderError exception is raised.

    >>> eqs = [Eq(x(t).diff(t, 2), x(t).diff(t) + x(t)), Eq(y(t).diff(t), y(t) + x(t))]
    >>> linear_ode_to_matrix(eqs, funcs, t, 1)
    Traceback (most recent call last):
    ...
    ODEOrderError: Cannot represent system in 1-order form

    If the system of equations is nonlinear, then ODENonlinearError is
    raised.

    >>> eqs = [Eq(x(t).diff(t), x(t) + y(t)), Eq(y(t).diff(t), y(t)**2 + x(t))]
    >>> linear_ode_to_matrix(eqs, funcs, t, 1)
    Traceback (most recent call last):
    ...
    ODENonlinearError: The system of ODEs is nonlinear.

    Parameters
    ==========

    eqs : list of sympy expressions or equalities
        The equations as expressions (assumed equal to zero).
    funcs : list of applied functions
        The dependent variables of the system of ODEs.
    t : symbol
        The independent variable.
    order : int
        The order of the system of ODEs.

    Returns
    =======

    The tuple ``(As, b)`` where ``As`` is a tuple of matrices and ``b`` is the
    the matrix representing the rhs of the matrix equation.

    Raises
    ======

    ODEOrderError
        When the system of ODEs have an order greater than what was specified
    ODENonlinearError
        When the system of ODEs is nonlinear

    See Also
    ========

    linear_eq_to_matrix: for systems of linear algebraic equations.

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Matrix_differential_equation

    """
    from sympy.solvers.solveset import linear_eq_to_matrix

    if any(ode_order(eq, func) > order for eq in eqs for func in funcs):
        msg = "Cannot represent system in {}-order form"
        raise ODEOrderError(msg.format(order))

    As = []

    for o in range(order, -1, -1):
        # Work from the highest derivative down
        funcs_deriv = [func.diff(t, o) for func in funcs]

        # linear_eq_to_matrix expects a proper symbol so substitute e.g.
        # Derivative(x(t), t) for a Dummy.
        rep = {func_deriv: Dummy() for func_deriv in funcs_deriv}
        eqs = [eq.subs(rep) for eq in eqs]
        syms = [rep[func_deriv] for func_deriv in funcs_deriv]

        # Ai is the matrix for X(t).diff(t, o)
        # eqs is minus the remainder of the equations.
        try:
            Ai, b = linear_eq_to_matrix(eqs, syms)
        except NonlinearError:
            raise ODENonlinearError("The system of ODEs is nonlinear.")

        As.append(Ai)
        if o:
            eqs = [-eq for eq in b]
        else:
            rhs = b

    return As, rhs
示例#5
0
def _symcheck():
    # import sympy as sym
    # # Create the index for our indexable sequence objects
    # i = sym.symbols('i', cls=sym.Idx)

    # measured = list(map(sym.IndexedBase, ['A_m', 'B_m', 'C_m']))
    # smoothed = list(map(sym.IndexedBase, ['A_s', 'B_s', 'C_s']))

    # for S in smoothed:
    #     S[0] = 0

    # for M, S in zip(measured, smoothed):
    #     M[i]
    #     pass

    # for r in raw_values:
    #     z = r[i]
    #     .is_nonnegative = True
    #     r.is_real = True

    ###########
    # I'm not sure how to used index objects correctly, so lets hack it
    import sympy as sym
    kw = dict(is_nonnegative=True, is_real=True)

    measured = {'A_m': [], 'B_m': [], 'C_m': [], 'T_m': []}
    smoothed = {'A_s': [], 'B_s': [], 'C_s': [], 'T_s': []}

    for i in range(3):
        _syms = sym.symbols('A_m{i}, B_m{i}, C_m{i}, T_m{i}'.format(i=i), **kw)
        for _sym in _syms:
            prefix = _sym.name[0:-1]
            measured[prefix].append(_sym)

        _syms = sym.symbols('A_s{i}, B_s{i}, C_s{i}, T_s{i}'.format(i=i), **kw)
        for _sym in _syms:
            prefix = _sym.name[0:-1]
            smoothed[prefix].append(_sym)

    # alpha, beta = sym.symbols('α,  β', is_real=1, is_positive=True)
    # constraints.append(sym.Eq(beta, 1 - alpha))
    # constraints.append(sym.Le(alpha, 1))
    # constraints.append(sym.Ge(alpha, 0))

    constraints = []
    N = 2
    alpha = 0.6
    beta = 1 - 0.6

    for i in range(N):
        # Total measure constraints
        constr = sym.Eq(
            measured['T_m'][i],
            measured['A_m'][i] + measured['B_m'][i] + measured['C_m'][i])

        # EWMA constraints
        for s_key in smoothed.keys():
            m_key = s_key.replace('_s', '_m')
            S = smoothed[s_key]
            M = measured[m_key]
            if i == 0:
                constr = sym.Eq(S[i], M[i])
                constraints.append(constr)
            else:
                constr = sym.Eq(S[i], M[i] * alpha + beta * S[i - 1])
                constraints.append(constr)

        constr = sym.Eq(
            measured['T_m'][i],
            measured['A_m'][i] + measured['B_m'][i] + measured['C_m'][i])
        constraints.append(constr)

    from sympy.solvers.solveset import linear_eq_to_matrix
    from sympy.solvers.solveset import linsolve
    import itertools as it
    import ubelt as ub

    all_symbols = list(
        ub.flatten(it.chain(measured.values(), smoothed.values())))

    # WE WANT TO KNOW IF THIS IS POSSIBLE
    constraints.append(sym.Gt(measured['A_m'][-1], measured['T_m'][-1]), )

    A, b = linear_eq_to_matrix(constraints, all_symbols)
    linsolve((A, b))