pythonsympysymbolic-math

Why Does Sympy Say This Derivative Is Constant When It's Obviously Not?


I am trying to make a Jacobian matrix using sympy.

I want to make a matrix of 2nd order derivatives, which I will call a 2nd order Jacobian.

I did this:

gk_letters = ["Δ", "Γ", "v"]

def greek_symbols():
    return symbols(" ".join(gk_letters))

def partials_1st_order():
    rows = []
    gks = greek_symbols()
    for idx1 in range(len(gk_letters)):
        gk1 = gks[idx1]
        col = []
        for idx2 in range(len(gk_letters)):
            gk2 = gks[idx2]
            if gk1 == gk2:
                col.append(1)
            else:
                col.append(Derivative(gk1, gk2))
        rows.append(col)
    return gks, Matrix(rows)

def partials_2nd_order():
    gks, jacobian = partials_1st_order()
    y = zeros(len(gks)**2, len(gks))
    input_rows, input_cols = jacobian.shape
    output_chunk = 0
    for den_idx in range(len(gks)):
        denominator = gks[den_idx]
        for input_row_num in range(input_rows):
            for input_col_num in range(input_cols):
                numerator = jacobian[input_row_num, input_col_num]
                new_diff = Derivative(numerator, denominator)
                y[output_chunk*len(gks) + input_row_num, input_col_num] = new_diff
        output_chunk += 1
    return y

When I call partials_2nd_order() at the command prompt, I get this:

⎡            2         2     ⎤
⎢ d         d         d      ⎥
⎢ ──(1)    ─────(Δ)  ─────(Δ)⎥
⎢ dΔ       dΔ dΓ     dΔ dv   ⎥
⎢                            ⎥
⎢  2                   2     ⎥
⎢ d         d         d      ⎥
⎢ ───(Γ)    ──(1)    ─────(Γ)⎥
⎢   2       dΔ       dΔ dv   ⎥
⎢ dΔ                         ⎥
⎢                            ⎥
              ...
⎢                            ⎥
⎢  2         2               ⎥
⎢ d         d         d      ⎥
⎢─────(v)  ─────(v)   ──(1)  ⎥
⎣dv dΔ     dv dΓ      dv     ⎦

I want to collapse to 0 everything that will always be 0, such as derivatives of constants.

However, when I try this:

[jj.is_constant() for jj in x]

I get this:

[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]

In other words, sympy thinks everything in this matrix is constant.

What am I missing?


Solution

  • All the derivatives in your matrix are zero. The partial derivative of x with respect to y is zero:

    In [1]: x, y = symbols('x, y')
    
    In [2]: d = Derivative(x, y)
    
    In [3]: d
    Out[3]: 
    d    
    ──(x)
    dy   
    
    In [4]: d.is_constant()
    Out[4]: True
    
    In [5]: d.doit()
    Out[5]: 0
    
    In [6]: diff(x, y)
    Out[6]: 0
    

    If you want a symbol that is a function of other symbols then you need a function:

    In [10]: f = Function('f')
    
    In [11]: d = Derivative(f(x), x)
    
    In [12]: d
    Out[12]: 
    d       
    ──(f(x))
    dx      
    
    In [13]: d.doit()
    Out[13]: 
    d       
    ──(f(x))
    dx      
    
    In [14]: d.is_constant()
    Out[14]: False
    

    There is no way to make a set of 3 symbols that are all functions of each other though which seems to be what you want here.

    You can keep the derivatives unevaluated though and just remove the ones that have a constant as the expression to be differentiated:

    In [23]: d = [Derivative(x, y), Derivative(1, x)]
    
    In [24]: d
    Out[24]: 
    ⎡d      d    ⎤
    ⎢──(x), ──(1)⎥
    ⎣dy     dx   ⎦
    
    In [25]: [di for di in d if not di.expr.is_constant()]
    Out[25]: 
    ⎡d    ⎤
    ⎢──(x)⎥
    ⎣dy   ⎦