Ejemplo n.º 1
0
def test_Transform():
    add1 = Transform(lambda x: x+1, lambda x: x % 2 == 1)
    assert add1[1] == 2
    assert (1 in add1) is True
    assert add1.get(1) == 2

    raises(KeyError, lambda: add1[2])
    assert (2 in add1) is False
    assert add1.get(2) is None
Ejemplo n.º 2
0
def test_Transform():
    add1 = Transform(lambda x: x + 1, lambda x: x % 2 == 1)
    assert add1[1] == 2
    assert (1 in add1) is True
    assert add1.get(1) == 2

    raises(KeyError, lambda: add1[2])
    assert (2 in add1) is False
    assert add1.get(2) is None
Ejemplo n.º 3
0
def real_root(arg, n=None):
    """Return the real nth-root of arg if possible. If n is omitted then
    all instances of -1**(1/odd) will be changed to -1.

    Examples
    ========

    >>> from sympy import root, real_root, Rational
    >>> from sympy.abc import x, n

    >>> real_root(-8, 3)
    -2
    >>> root(-8, 3)
    2*(-1)**(1/3)
    >>> real_root(_)
    -2

    See Also
    ========

    sympy.polys.rootoftools.RootOf
    sympy.core.power.integer_nthroot
    root, sqrt
    """
    if n is not None:
        n = as_int(n)
        rv = C.Pow(arg, Rational(1, n))
        if n % 2 == 0:
            return rv
    else:
        rv = sympify(arg)
    n1pow = Transform(
        lambda x: S.NegativeOne, lambda x: x.is_Pow and x.base is S.NegativeOne
        and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2)
    return rv.xreplace(n1pow)
Ejemplo n.º 4
0
def real_root(arg, n=None, evaluate=None):
    """Return the real *n*'th-root of *arg* if possible.

    Parameters
    ==========

    n : int or None, optional
        If *n* is ``None``, then all instances of
        ``(-n)**(1/odd)`` will be changed to ``-n**(1/odd)``.
        This will only create a real root of a principal root.
        The presence of other factors may cause the result to not be
        real.

    evaluate : bool, optional
        The parameter determines if the expression should be evaluated.
        If ``None``, its value is taken from
        ``global_parameters.evaluate``.

    Examples
    ========

    >>> from sympy import root, real_root

    >>> real_root(-8, 3)
    -2
    >>> root(-8, 3)
    2*(-1)**(1/3)
    >>> real_root(_)
    -2

    If one creates a non-principal root and applies real_root, the
    result will not be real (so use with caution):

    >>> root(-8, 3, 2)
    -2*(-1)**(2/3)
    >>> real_root(_)
    -2*(-1)**(2/3)

    See Also
    ========

    sympy.polys.rootoftools.rootof
    sympy.core.power.integer_nthroot
    root, sqrt
    """
    from sympy.functions.elementary.complexes import Abs, im, sign
    from sympy.functions.elementary.piecewise import Piecewise
    if n is not None:
        return Piecewise((root(arg, n, evaluate=evaluate),
                          Or(Eq(n, S.One), Eq(n, S.NegativeOne))),
                         (Mul(sign(arg),
                              root(Abs(arg), n, evaluate=evaluate),
                              evaluate=evaluate),
                          And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))),
                         (root(arg, n, evaluate=evaluate), True))
    rv = sympify(arg)
    n1pow = Transform(
        lambda x: -(-x.base)**x.exp, lambda x: x.is_Pow and x.base.is_negative
        and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2)
    return rv.xreplace(n1pow)
Ejemplo n.º 5
0
 def __new__(cls, arg):
     # Mostly type checking here
     arg = _sympify(arg)
     predicates = arg.atoms(Predicate)
     applied_predicates = arg.atoms(AppliedPredicate)
     if predicates and applied_predicates:
         raise ValueError(
             "arg must be either completely free or singly applied")
     if not applied_predicates:
         obj = BooleanFunction.__new__(cls, arg)
         obj.pred = arg
         obj.expr = None
         return obj
     predicate_args = {pred.args[0] for pred in applied_predicates}
     if len(predicate_args) > 1:
         raise ValueError(
             "The AppliedPredicates in arg must be applied to a single expression."
         )
     obj = BooleanFunction.__new__(cls, arg)
     obj.expr = predicate_args.pop()
     obj.pred = arg.xreplace(
         Transform(lambda e: e.func,
                   lambda e: isinstance(e, AppliedPredicate)))
     applied = obj.apply()
     if applied is None:
         return obj
     return applied
Ejemplo n.º 6
0
def real_root(arg, n=None):
    """Return the real nth-root of arg if possible. If n is omitted then
    all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this
    will only create a real root of a principle root -- the presence of
    other factors may cause the result to not be real.

    Examples
    ========

    >>> from sympy import root, real_root, Rational
    >>> from sympy.abc import x, n

    >>> real_root(-8, 3)
    -2
    >>> root(-8, 3)
    2*(-1)**(1/3)
    >>> real_root(_)
    -2

    If one creates a non-principle root and applies real_root, the
    result will not be real (so use with caution):

    >>> root(-8, 3, 2)
    -2*(-1)**(2/3)
    >>> real_root(_)
    -2*(-1)**(2/3)


    See Also
    ========

    sympy.polys.rootoftools.RootOf
    sympy.core.power.integer_nthroot
    root, sqrt
    """
    from sympy import im, Piecewise
    if n is not None:
        try:
            n = as_int(n)
            arg = sympify(arg)
            if arg.is_positive or arg.is_negative:
                rv = root(arg, n)
            else:
                raise ValueError
        except ValueError:
            return root(arg, n)*Piecewise(
                (S.One, ~Equality(im(arg), 0)),
                (Pow(S.NegativeOne, S.One/n)**(2*floor(n/2)), And(
                    Equality(n % 2, 1),
                    arg < 0)),
                (S.One, True))
    else:
        rv = sympify(arg)
    n1pow = Transform(lambda x: -(-x.base)**x.exp,
                      lambda x:
                      x.is_Pow and
                      x.base.is_negative and
                      x.exp.is_Rational and
                      x.exp.p == 1 and x.exp.q % 2)
    return rv.xreplace(n1pow)
Ejemplo n.º 7
0
    def __call__(self, _q):
        cth = cos(self.theta_ + _q)
        sth = sin(self.theta_ + _q)
        res = sp.zeros(4, 4)
        res[0, 0] = cth
        res[0, 1] = -sth * self.cosal_
        res[0, 2] = sth * self.sinal_
        res[0, 3] = self.a_ * cth

        res[1, 0] = sth
        res[1, 1] = cth * self.cosal_
        res[1, 2] = -cth * self.sinal_
        res[1, 3] = self.a_ * sth

        res[2, 1] = self.sinal_
        res[2, 2] = self.cosal_
        res[2, 3] = self.d_

        res[3, 3] = 1

        for i in range(3):
            for j in range(4):
                res[i, j] = res[i, j].xreplace(
                    Transform(lambda x: x.round(8),
                              lambda x: isinstance(x, Float)))
        return res
def evaluate_old_assump(pred):
    """
    Replace assumptions of expressions replaced with their values in the old
    assumptions (like Q.negative(-1) => True). Useful because some direct
    computations for numeric objects is defined most conveniently in the old
    assumptions.

    """
    return pred.xreplace(Transform(_old_assump_replacer))
Ejemplo n.º 9
0
def real_root(arg, n=None):
    """Return the real nth-root of arg if possible. If n is omitted then
    all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this
    will only create a real root of a principal root -- the presence of
    other factors may cause the result to not be real.

    Examples
    ========

    >>> from sympy import root, real_root, Rational
    >>> from sympy.abc import x, n

    >>> real_root(-8, 3)
    -2
    >>> root(-8, 3)
    2*(-1)**(1/3)
    >>> real_root(_)
    -2

    If one creates a non-principal root and applies real_root, the
    result will not be real (so use with caution):

    >>> root(-8, 3, 2)
    -2*(-1)**(2/3)
    >>> real_root(_)
    -2*(-1)**(2/3)


    See Also
    ========

    sympy.polys.rootoftools.rootof
    sympy.core.power.integer_nthroot
    root, sqrt
    """
    from sympy.functions.elementary.complexes import Abs, im, sign
    from sympy.functions.elementary.piecewise import Piecewise
    if n is not None:
        return Piecewise(
            (root(arg, n), Or(Eq(n, S.One), Eq(n, S.NegativeOne))),
            (sign(arg)*root(Abs(arg), n), And(Eq(im(arg), S.Zero),
                Eq(Mod(n, 2), S.One))),
            (root(arg, n), True))
    rv = sympify(arg)
    n1pow = Transform(lambda x: -(-x.base)**x.exp,
                      lambda x:
                      x.is_Pow and
                      x.base.is_negative and
                      x.exp.is_Rational and
                      x.exp.p == 1 and x.exp.q % 2)
    return rv.xreplace(n1pow)
Ejemplo n.º 10
0
def plot():

    maclaurinPolynomial = maclaurin(degree)

    maclaurinText.set_text("Maclaurin Series: " + str(
        maclaurinPolynomial.xreplace(
            Transform(lambda x: x.round(degree),
                      lambda x: isinstance(x, Float)))))

    f = lambdify(x, maclaurinPolynomial, 'numpy')
    fx = f(xvals)

    if np.all(fx == 0):
        maclaurinGraph.set_ydata(np.zeros(50))
    else:
        maclaurinGraph.set_ydata(fx)

    fig.canvas.draw_idle()
Ejemplo n.º 11
0
    def __call__(self, _q=None):

        if _q is None:
            q = self.q_
        else:
            q = _q

        self.m0j_[0] = self.mij_[0](q[0])

        for i, mij in enumerate(self.mij_[1:], start=1):
            self.m0j_[i] = self.m0j_[i - 1] * mij(q[i])

        res = self.m0j_[-1] * self.mee
        for i in range(3):
            for j in range(4):
                res[i, j] = res[i, j].xreplace(
                    Transform(lambda x: x.round(8),
                              lambda x: isinstance(x, Float)))
        return res
Ejemplo n.º 12
0
    def jac(self, _q=None):

        if _q is None:
            q = self.q_
        else:
            q = _q

        pe = self(q)[:3, -1]
        jac = sp.zeros(6, self.dim_)
        axis = sp.Matrix([0.0, 0.0, 1.0])
        p = sp.Matrix([0.0, 0.0, 0.0])
        for j in range(0, self.dim_):
            jac[:3, j] = axis.cross(pe - p).doit()
            jac[3:, j] = axis
            axis = self.m0j_[j][:3, 2]
            p = self.m0j_[j][:3, -1]

        for i in range(6):
            for j in range(self.dim_):
                jac[i, j] = jac[i, j].xreplace(
                    Transform(lambda x: x.round(8),
                              lambda x: isinstance(x, Float)))

        return jac
Ejemplo n.º 13
0
def powdenest(eq, force=False, polar=False):
    r"""
    Collect exponents on powers as assumptions allow.

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

    Given ``(bb**be)**e``, this can be simplified as follows:
        * if ``bb`` is positive, or
        * ``e`` is an integer, or
        * ``|be| < 1`` then this simplifies to ``bb**(be*e)``

    Given a product of powers raised to a power, ``(bb1**be1 *
    bb2**be2...)**e``, simplification can be done as follows:

    - if e is positive, the gcd of all bei can be joined with e;
    - all non-negative bb can be separated from those that are negative
      and their gcd can be joined with e; autosimplification already
      handles this separation.
    - integer factors from powers that have integers in the denominator
      of the exponent can be removed from any term and the gcd of such
      integers can be joined with e

    Setting ``force`` to ``True`` will make symbols that are not explicitly
    negative behave as though they are positive, resulting in more
    denesting.

    Setting ``polar`` to ``True`` will do simplifications on the Riemann surface of
    the logarithm, also resulting in more denestings.

    When there are sums of logs in exp() then a product of powers may be
    obtained e.g. ``exp(3*(log(a) + 2*log(b)))`` - > ``a**3*b**6``.

    Examples
    ========

    >>> from sympy.abc import a, b, x, y, z
    >>> from sympy import Symbol, exp, log, sqrt, symbols, powdenest

    >>> powdenest((x**(2*a/3))**(3*x))
    (x**(2*a/3))**(3*x)
    >>> powdenest(exp(3*x*log(2)))
    2**(3*x)

    Assumptions may prevent expansion:

    >>> powdenest(sqrt(x**2))
    sqrt(x**2)

    >>> p = symbols('p', positive=True)
    >>> powdenest(sqrt(p**2))
    p

    No other expansion is done.

    >>> i, j = symbols('i,j', integer=True)
    >>> powdenest((x**x)**(i + j)) # -X-> (x**x)**i*(x**x)**j
    x**(x*(i + j))

    But exp() will be denested by moving all non-log terms outside of
    the function; this may result in the collapsing of the exp to a power
    with a different base:

    >>> powdenest(exp(3*y*log(x)))
    x**(3*y)
    >>> powdenest(exp(y*(log(a) + log(b))))
    (a*b)**y
    >>> powdenest(exp(3*(log(a) + log(b))))
    a**3*b**3

    If assumptions allow, symbols can also be moved to the outermost exponent:

    >>> i = Symbol('i', integer=True)
    >>> powdenest(((x**(2*i))**(3*y))**x)
    ((x**(2*i))**(3*y))**x
    >>> powdenest(((x**(2*i))**(3*y))**x, force=True)
    x**(6*i*x*y)

    >>> powdenest(((x**(2*a/3))**(3*y/i))**x)
    ((x**(2*a/3))**(3*y/i))**x
    >>> powdenest((x**(2*i)*y**(4*i))**z, force=True)
    (x*y**2)**(2*i*z)

    >>> n = Symbol('n', negative=True)

    >>> powdenest((x**i)**y, force=True)
    x**(i*y)
    >>> powdenest((n**i)**x, force=True)
    (n**i)**x

    """
    from sympy.simplify.simplify import posify

    if force:

        def _denest(b, e):
            if not isinstance(b, (Pow, exp)):
                return b.is_positive, Pow(b, e, evaluate=False)
            return _denest(b.base, b.exp * e)

        reps = []
        for p in eq.atoms(Pow, exp):
            if isinstance(p.base, (Pow, exp)):
                ok, dp = _denest(*p.args)
                if ok is not False:
                    reps.append((p, dp))
        if reps:
            eq = eq.subs(reps)
        eq, reps = posify(eq)
        return powdenest(eq, force=False, polar=polar).xreplace(reps)

    if polar:
        eq, rep = polarify(eq)
        return unpolarify(powdenest(unpolarify(eq, exponents_only=True)), rep)

    new = powsimp(sympify(eq))
    return new.xreplace(
        Transform(_denest_pow,
                  filter=lambda m: m.is_Pow or isinstance(m, exp)))
Ejemplo n.º 14
0
def simplify(expr, ratio=1.7, measure=count_ops, rational=False):
    # type: (object, object, object, object) -> object
    """
    Simplifies the given expression.

    Simplification is not a well defined term and the exact strategies
    this function tries can change in the future versions of SymPy. If
    your algorithm relies on "simplification" (whatever it is), try to
    determine what you need exactly  -  is it powsimp()?, radsimp()?,
    together()?, logcombine()?, or something else? And use this particular
    function directly, because those are well defined and thus your algorithm
    will be robust.

    Nonetheless, especially for interactive use, or when you don't know
    anything about the structure of the expression, simplify() tries to apply
    intelligent heuristics to make the input expression "simpler".  For
    example:

    >>> from sympy import simplify, cos, sin
    >>> from sympy.abc import x, y
    >>> a = (x + x**2)/(x*sin(y)**2 + x*cos(y)**2)
    >>> a
    (x**2 + x)/(x*sin(y)**2 + x*cos(y)**2)
    >>> simplify(a)
    x + 1

    Note that we could have obtained the same result by using specific
    simplification functions:

    >>> from sympy import trigsimp, cancel
    >>> trigsimp(a)
    (x**2 + x)/x
    >>> cancel(_)
    x + 1

    In some cases, applying :func:`simplify` may actually result in some more
    complicated expression. The default ``ratio=1.7`` prevents more extreme
    cases: if (result length)/(input length) > ratio, then input is returned
    unmodified.  The ``measure`` parameter lets you specify the function used
    to determine how complex an expression is.  The function should take a
    single argument as an expression and return a number such that if
    expression ``a`` is more complex than expression ``b``, then
    ``measure(a) > measure(b)``.  The default measure function is
    :func:`count_ops`, which returns the total number of operations in the
    expression.

    For example, if ``ratio=1``, ``simplify`` output can't be longer
    than input.

    ::

        >>> from sympy import sqrt, simplify, count_ops, oo
        >>> root = 1/(sqrt(2)+3)

    Since ``simplify(root)`` would result in a slightly longer expression,
    root is returned unchanged instead::

       >>> simplify(root, ratio=1) == root
       True

    If ``ratio=oo``, simplify will be applied anyway::

        >>> count_ops(simplify(root, ratio=oo)) > count_ops(root)
        True

    Note that the shortest expression is not necessary the simplest, so
    setting ``ratio`` to 1 may not be a good idea.
    Heuristically, the default value ``ratio=1.7`` seems like a reasonable
    choice.

    You can easily define your own measure function based on what you feel
    should represent the "size" or "complexity" of the input expression.  Note
    that some choices, such as ``lambda expr: len(str(expr))`` may appear to be
    good metrics, but have other problems (in this case, the measure function
    may slow down simplify too much for very large expressions).  If you don't
    know what a good metric would be, the default, ``count_ops``, is a good
    one.

    For example:

    >>> from sympy import symbols, log
    >>> a, b = symbols('a b', positive=True)
    >>> g = log(a) + log(b) + log(a)*log(1/b)
    >>> h = simplify(g)
    >>> h
    log(a*b**(-log(a) + 1))
    >>> count_ops(g)
    8
    >>> count_ops(h)
    5

    So you can see that ``h`` is simpler than ``g`` using the count_ops metric.
    However, we may not like how ``simplify`` (in this case, using
    ``logcombine``) has created the ``b**(log(1/a) + 1)`` term.  A simple way
    to reduce this would be to give more weight to powers as operations in
    ``count_ops``.  We can do this by using the ``visual=True`` option:

    >>> print(count_ops(g, visual=True))
    2*ADD + DIV + 4*LOG + MUL
    >>> print(count_ops(h, visual=True))
    2*LOG + MUL + POW + SUB

    >>> from sympy import Symbol, S
    >>> def my_measure(expr):
    ...     POW = Symbol('POW')
    ...     # Discourage powers by giving POW a weight of 10
    ...     count = count_ops(expr, visual=True).subs(POW, 10)
    ...     # Every other operation gets a weight of 1 (the default)
    ...     count = count.replace(Symbol, type(S.One))
    ...     return count
    >>> my_measure(g)
    8
    >>> my_measure(h)
    14
    >>> 15./8 > 1.7 # 1.7 is the default ratio
    True
    >>> simplify(g, measure=my_measure)
    -log(a)*log(b) + log(a) + log(b)

    Note that because ``simplify()`` internally tries many different
    simplification strategies and then compares them using the measure
    function, we get a completely different result that is still different
    from the input expression by doing this.

    If rational=True, Floats will be recast as Rationals before simplification.
    If rational=None, Floats will be recast as Rationals but the result will
    be recast as Floats. If rational=False(default) then nothing will be done
    to the Floats.
    """
    expr = sympify(expr)

    try:
        return expr._eval_simplify(ratio=ratio, measure=measure)
    except AttributeError:
        pass

    original_expr = expr = signsimp(expr)

    from sympy.simplify.hyperexpand import hyperexpand
    from sympy.functions.special.bessel import BesselBase
    from sympy import Sum, Product

    if not isinstance(expr, Basic) or not expr.args:  # XXX: temporary hack
        return expr

    if not isinstance(expr, (Add, Mul, Pow, ExpBase)):
        if isinstance(expr, Function) and hasattr(expr, "inverse"):
            if len(expr.args) == 1 and len(expr.args[0].args) == 1 and \
               isinstance(expr.args[0], expr.inverse(argindex=1)):
                return simplify(expr.args[0].args[0], ratio=ratio,
                                measure=measure, rational=rational)
        return expr.func(*[simplify(x, ratio=ratio, measure=measure, rational=rational)
                         for x in expr.args])

    # TODO: Apply different strategies, considering expression pattern:
    # is it a purely rational function? Is there any trigonometric function?...
    # See also https://github.com/sympy/sympy/pull/185.

    def shorter(*choices):
        '''Return the choice that has the fewest ops. In case of a tie,
        the expression listed first is selected.'''
        if not has_variety(choices):
            return choices[0]
        return min(choices, key=measure)

    # rationalize Floats
    floats = False
    if rational is not False and expr.has(Float):
        floats = True
        expr = nsimplify(expr, rational=True)

    expr = bottom_up(expr, lambda w: w.normal())
    expr = Mul(*powsimp(expr).as_content_primitive())
    _e = cancel(expr)
    expr1 = shorter(_e, _mexpand(_e).cancel())  # issue 6829
    expr2 = shorter(together(expr, deep=True), together(expr1, deep=True))

    if ratio is S.Infinity:
        expr = expr2
    else:
        expr = shorter(expr2, expr1, expr)
    if not isinstance(expr, Basic):  # XXX: temporary hack
        return expr

    expr = factor_terms(expr, sign=False)

    # hyperexpand automatically only works on hypergeometric terms
    expr = hyperexpand(expr)

    expr = piecewise_fold(expr)

    if expr.has(BesselBase):
        expr = besselsimp(expr)

    if expr.has(TrigonometricFunction, HyperbolicFunction):
        expr = trigsimp(expr, deep=True)

    if expr.has(log):
        expr = shorter(expand_log(expr, deep=True), logcombine(expr))

    if expr.has(CombinatorialFunction, gamma):
        # expression with gamma functions or non-integer arguments is
        # automatically passed to gammasimp
        expr = combsimp(expr)

    if expr.has(Sum):
        expr = sum_simplify(expr)

    if expr.has(Product):
        expr = product_simplify(expr)

    short = shorter(powsimp(expr, combine='exp', deep=True), powsimp(expr), expr)
    short = shorter(short, cancel(short))
    short = shorter(short, factor_terms(short), expand_power_exp(expand_mul(short)))
    if short.has(TrigonometricFunction, HyperbolicFunction, ExpBase):
        short = exptrigsimp(short)

    # get rid of hollow 2-arg Mul factorization
    hollow_mul = Transform(
        lambda x: Mul(*x.args),
        lambda x:
        x.is_Mul and
        len(x.args) == 2 and
        x.args[0].is_Number and
        x.args[1].is_Add and
        x.is_commutative)
    expr = short.xreplace(hollow_mul)

    numer, denom = expr.as_numer_denom()
    if denom.is_Add:
        n, d = fraction(radsimp(1/denom, symbolic=False, max_terms=1))
        if n is not S.One:
            expr = (numer*n).expand()/d

    if expr.could_extract_minus_sign():
        n, d = fraction(expr)
        if d != 0:
            expr = signsimp(-n/(-d))

    if measure(expr) > ratio*measure(original_expr):
        expr = original_expr

    # restore floats
    if floats and rational is None:
        expr = nfloat(expr, exponent=False)

    return expr
Ejemplo n.º 15
0
axDegree = plt.axes([0.25, .1, 0.65, 0.03], facecolor='lightgoldenrodyellow')

degreeSlider = Slider(axDegree,
                      'Degree',
                      0,
                      18,
                      valinit=6,
                      valstep=2,
                      color='goldenrod')


def update(val):
    global degree
    degree = val
    plot()


degreeSlider.on_changed(update)

ax.plot(xvals, yvals, 'k-')
maclaurinText = axDegree.text(
    -3.2, 1.5, "Maclaurin Series: " + str(
        maclaurin(degree).xreplace(
            Transform(lambda x: x.round(2), lambda x: isinstance(x, Float)))))
maclaurinGraph, = ax.plot(xvals,
                          lambdify(x, maclaurin(degree), 'numpy')(xvals),
                          color='red')

plt.show()
Ejemplo n.º 16
0
from sympy import *
init_printing()

# Need the following to fold the conjugates. See
# https://stackoverflow.com/questions/48754975/simplification-of-derivative-of-square-using-sympy

from sympy.core.rules import Transform
fold_conjugates = Transform(
    lambda f: 2 * re(f.args[0]), lambda f: isinstance(f, Add) and len(f.args)
    == 2 and f.args[1] == f.args[0].conjugate())

fold_conjugates_2 = Transform(
    lambda f: f.args[0] + 2 * re(f.args[1]), lambda f: isinstance(f, Add) and
    len(f.args) == 3 and f.args[2] == f.args[1].conjugate())

S, l, m, n = symbols('S l m n', real=True)
u, v, w, wt = symbols('u v w wt', real=True)
Vobs, Vres0 = symbols('Vobs Vres', complex=True)
Vres = Vobs - S * exp(-I * 2 * pi * (u * l + v * m))
J = Vres * wt * conjugate(Vres)
axes = [S, l, m]
grad = derive_by_array(J, axes)
hess = derive_by_array(grad, axes)

print("J = ", J)

for axis in range(3):
    print(
        "grad[%d] = %s" % (axis, grad[axis].subs(Vres, Vres0).conjugate().subs(
            Vres, Vres0).conjugate().xreplace(fold_conjugates)))