Ask Your Question
2

Is it possible to substitute $U^\prime$ to $D_0(U)$ ?

asked 2020-12-04 15:18:11 +0200

Cyrille gravatar image

The result of this code

var('x y p w0 g c')
assume(p>=0)
assume(p<=1)
U=function('U')(x)
EU(x,y,p)=p*U(x)+(1-p)*U(y)
show(EU(w0,g*w0-c,p))
show(diff(EU(w0,g*w0-c,p),w0))

uses $D_0(U)$ for the first order derivative of $U$. Is it possible to substitute $U^\prime$ to $D_0(U)$, to keep the path with textbook notations ?

edit retag flag offensive close merge delete

3 Answers

Sort by » oldest newest most voted
2

answered 2020-12-05 02:22:07 +0200

dsejas gravatar image

Hello, @Cyrille! Maybe you need somebody more Sage-savvy than me, because I don't have a satisfactory/efficient answer for this question, but I can give you a "good enough" solution until you find something better.

Suppose that instead of your last line you write

tmp = diff(EU(w0,g*w0-c,p),w0)
print(latex(tmp))

That will show you the output

-g {\left(p - 1\right)} \mathrm{D}_{0}\left(U\right)\left(g w_{0} - c\right) + p \frac{\partial}{\partial w_{0}}U\left(w_{0}\right)

(This is what show() converts to a beautiful formula in SageCell.) By reading this LaTeX code, you will see that the derivative of U is written in two different ways: \mathrm{D}_{0}\left(U\right) ($\mathrm{D}_{0}\left(U\right)$) and \frac{\partial}{\partial w_{0}}U ($\frac{\partial}{\partial w_{0}}U$). In order to obtain a U' instead of those inelegant versions, you can use the replace() method from the str Python data type. Here is the code:

var('x y p w0 g c')
assume(p>=0)
assume(p<=1)
U = function('U')(x)
EU(x,y,p) = p * U(x) + (1-p) * U(y)
show(EU(w0,g*w0-c,p))
tmp = latex(diff(EU(w0,g*w0-c,p),w0)) # this converts the result to LaTeX syntax
tmp = tmp.replace(r'\mathrm{D}_{0}\left(U\right)', "U'") # replace the first U'
tmp = tmp.replace(r'\frac{\partial}{\partial w_{0}}U', "U'") # replace the second U'
show(LatexExpr(tmp)) # show the formula

Some clarifications are in order. First, notice that I used "raw strings" or "r-strings", which are the ones with a leading r, like r'\mathrm{D}_{0}\left(U\right)'. This is in order to avoid Sage/Python from interpreting the backslash ("\") as an escape character. If you don't want to use raw strings, you should duplicate every backslash, as in '\\mathrm{D}_{0}\\left(U\\right)' (notice this string doesn't have a leading r.) Second, it might surprise you to see the LatexExpr() function in the last line of the previous code. That actually is something I just learned: when you use the replace() method, the result is a character string. Although we know that this string is the LaTeX code of a formula, Sage doesn't know it, so if you were to use show(tmp) instead of what I wrote, you would get the LaTeX code printed in the screen instead of that code being executed to obtain the formula. In order to force Sage to execute the LaTeX code, I used the LatexExpr() constructor.

I must insist that this is a not-so-optimal solution, whose purpose is to help while other solution appears, so perhaps you would like to wait for another option.

I hope this helps!

edit flag offensive delete link more

Comments

Perfect as always Thanks

Cyrille gravatar imageCyrille ( 2020-12-05 08:34:50 +0200 )edit

I disagree : the notation $U'$ of "the derivative" of $U$ is meaningful only for functions of a single variable. Consider :

sage: f1=function("f1")
sage: f2=function("f2")(x)
sage: f1.variables()
()
sage: f2.variables()
(x,)

In consequence :

sage: diff(f2,x)
diff(f2(x), x)

but :

sage: diff(f1,x)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

[ Snip... ]

TypeError: unable to convert f1 to a symbolic expression

The informations available to the algorithms acting of those functions are different.

Furthermore, the arguments of $U$ in the resultant expression are respectively a single variable and a symbolic expression...

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2020-12-05 10:43:54 +0200 )edit

@Emmanuel Charpentier -- in this question, U is indeed a function of a single variable.

It is used to define EU as a function of several variables.

Then EU is evaluated at a position depending on w, and the result is differentiated with respect to w.

The chain rule applies, and involves the derivative of U, but this derivative is always that of a function of a single variable.

slelievre gravatar imageslelievre ( 2020-12-05 12:14:15 +0200 )edit

Emmanuel in economics, this is a situation one encounters often. For instance $U(w)$ is a fonction of wealth. We use to take expectation among states of nature which leads to different values of w understood as functions of other variables (as interest rates, collateral, probabilities. So $EU$ is a composition of U. The answer of dsejas is perfect.

Cyrille gravatar imageCyrille ( 2020-12-05 22:18:39 +0200 )edit
2

answered 2020-12-05 21:56:02 +0200

nbruin gravatar image

One solution is to consider $U'$ as not a generic notation for the derivative (it is not, as pointed out, because it suppresses with respect to which variable the derivative is taken). The question then is really how to specify a non-generic derivative for a formal symbolic function. Reading the documentation of function, there is a way of specifying specific differentiation rules via the derivative_func argument. One way is to denote $U'$ by Up. Letting that print as $U'$ is a matter of specifying a special LaTeX representative of your function, for which there are separate tools. Then it's just a matter of telling the system that D[0](U) should yield Up. We make the code slightly more general. Amend code as you see fit if you really want to allow U to be a function in more variables and allow differentiation to those as well. I think you'll need to specify special names for all those derivatives then, because I suspect that the automatic simplification rules for D[i](U)(x,y,z) will otherwise get stuck in an infinite loop (I haven't checkde that, though).

This should do the trick:

def special_diff(i,Up):
    def deriv(*args,**kwargs):
        if kwargs['diff_param'] == i:
            return Up(*args[1:])
        else:
            raise ValueError("cannot differentiate this function wrt. {}".format(i))
    return deriv

Up=function('Up')
U=function('U',derivative_func=special_diff(0,Up))
edit flag offensive delete link more

Comments

Rhis could be exploited to denote the derivative with respect to time, as do some notations used in mechanics (i. e. $\dot{g}=\displaystyle\frac{dg}{dt})$.

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2020-12-05 22:58:39 +0200 )edit

Rhis -> This.

slelievre gravatar imageslelievre ( 2020-12-07 02:37:44 +0200 )edit

@nbruin -- seems much more elegant than my (way too long) answer.

slelievre gravatar imageslelievre ( 2020-12-07 03:43:58 +0200 )edit
3

answered 2020-12-05 15:16:11 +0200

slelievre gravatar image

updated 2020-12-05 17:35:15 +0200

Display derivative with prime

Setup

To better focus on the actual question, in this answer we use simpler names w and V instead of w0 and EU, and skip the assumptions on $p$.

Define U (as a symbolic function U, not as the expression U(x)):

sage: U = function('U')

Define a function V of three variables based on U:

sage: V(x, y, p) = p*U(x) + (1 - p)*U(y)

Note that all names on the left hand side of the assignment operator = get defined by that line: V as a function, and x, y, p as symbolic variables. No need to declare them beforehand.

Define three symbolic variables, an expression f based on V and these variables, and another one, differentiating with respect to w:

sage: w, g, c = SR.var('w, g, c')
sage: f = V(w, g*w - c, p)
sage: h = diff(f, w)
sage: view(h)

$$-g {(p - 1)} {\rm D}_0(U)(g w - c) + p ({∂}/{∂ w}) U(w)$$

That has two occurrences of $U'$, which we would like to show as $U'(g w - c)$ and $U'(w)$ instead of ${\rm D}_0(U)(g w - c)$ and $({∂}/{∂ w}) U(w)$.

The answer by @dsejas covers an approach using string replacements in the latex representation.

Here we discuss an alternative approach performing substitutions in the expression tree before displaying.

First we provide two versions of this approach, one ad-hoc for a single derivative replacement, one more general. Then we explain how one could explore to get to these solutions.

Make a particular derivative display with prime

Here is a function for operator substitution in an expression:

def subs_op(expr, op1, op2):
    r"""
    Return the expression `expr` with operator `op1` replaced by `op2`.
    """
    op = expr.operator()
    if op:
        opp = (op2 if str(op) == str(op1) else op)
        args = expr.operands()
        aargs = (subs_op(a, op1, op2) for a in args)
        return opp(*aargs)
    else:
        return expr

To address the question with this, define the to-be-replaced and the replacement operators, then use subs_op:

sage: DU = U(x).diff().operator()
sage: Uprime = function("U'")
sage: DU, Uprime
(D[0](U), U')
sage: fff = subs_op(ff, DU, Uprime)
sage: fff
-g*(p - 1)*U'(g*w - c) + p*U'(w)
sage: view(fff)

$$-g {(p - 1)} {\rm U'}(g w - c) + p {\rm U'}(w)$$

Problem solved, at least in an ad-hoc way.

Make all derivatives display with prime

Here is a use_prime function that walks through an expression and replaces any derivatives of functions of a single variable by "prime" versions (or "double-prime", etc. depending on the order of differentiation).

def use_prime(expr):
    r"""
    Return the expression with one-variable function derivatives "primed".
    """
    op = expr.operator()
    if op:
        args = expr.operands()
        aargs = (use_prime(a) for a in args)
        opp = op
        if (isinstance(op, sage.symbolic.operators.FDerivativeOperator)
                and len(args) == 1):
            name = op.function().name()
            primes = "'" * len(op.parameter_set())
            opp = function(f"{name}{primes}")
        return opp(*aargs)
    else:
        return expr

Example with various types of derivatives:

sage: a, b = (function(f) for f in 'ab')
sage: x, z = SR.var('x, z')
sage: f(x, z) = z * a(x * z) + x * z * diff(b(z), z)
sage: h = diff(f(x, z), z, x)
sage: h
x*z^2*D[0, 0](a)(x*z) + 2*z*D[0](a)(x*z) + z*diff(b(z), z, z) + diff(b(z), z)
sage: view(h)

$$x z^2 {\rm D}_{0,0}(a)(x z) + 2 z {\rm D}_0 (a)(x z) + z ({∂^2}/{(∂ z)^2})b(z) + ({∂}/{∂ z})b(z)$$

sage: hh = use_prime(h)
sage: hh
x*z^2*a''(x*z) + 2*z*a'(x*z) + z*b''(z) + b'(z)
sage: view(hh)

$$x z^2 {\rm a''}(x z) + 2 z {\rm a'}(x z) + z {\rm b''}(z) + {\rm b'}(z)$$

Example with the original question:

U = function('U')
V(x, y, p) = p*U(x) + (1 - p)*U(y)
w, g, c = SR.var('w, g, c')
f = V(w, g*w - c, p)
h = diff(f, w)
show(h)
hh = use_prime(h)
show(hh)

$$-g {(p - 1)} {\rm D}_0(U)(g w - c) + p ({∂}/{∂ z})U(w)$$

$$-g {(p - 1)} {\rm U'}(g w - c) + p {\rm U'}(w)$$

Explore the problem to reach a solution

Having provided an approach above, we now explain the exploration that can lead to such an approach.

Define again

sage: U = function('U')
sage: V(x, y, p) = p*U(x) + (1 - p)*U(y)
sage: w, g, c = SR.var('w, g, c')
sage: f = V(w, g*w - c, p)
sage: h = diff(f, w)

Explore the available methods for expression h with h.<TAB> (ie type h. then hit the TAB key).

Find among the available methods operator and operands:

sage: h.operator(), h.operands()
(<function add_vararg at 0x2007603a0>,
 [-g*(p - 1)*D[0](U)(g*w - c), p*diff(U(w), w)])

Give names to the operands and get one level deeper:

sage: a, b = h.operands()
sage: a.operator(), a.operands()
(<function mul_vararg at 0x2007601f0>, [g, p - 1, D[0](U)(g*w - c), -1])
sage: b.operator(), b.operands()
(<function mul_vararg at 0x2007601f0>, [p, diff(U(w), w)])

Name the operands we care about and explore one level further:

sage: _, _, aa, _ = a.operands()
sage: _, bb = b.operands()

sage: aa
D[0](U)(g*w - c)
sage: bb
diff(U(w), w)

sage: aa.operator(), aa.operands()
(D[0](U), [g*w - c])
sage: bb.operator(), bb.operands()
(D[0](U), [w])

Unfortunately aa.operator() and bb.operator() do not compare equal:

sage: a.operator() == b.operator()
False

So we have to resort to string comparison:

sage: str(a.operator()) == str(b.operator())

Now we try to build this operator in a simpler way:

sage: DUx = U(x).diff()
sage: DUx
diff(U(x), x)
sage: DU = DUx.operator()
sage: DU
D[0](U)

Good, now for the replacement we use a symbolic function whose string representation is U'.

sage: function("U'")
sage: function("U'")
U'

All that is left is to recursively replace one operator by the other by walking the expression tree. See subs_op above.

Now for the more general function, we analyse a little further:

sage: type(DU)
<class 'sage.symbolic.operators.FDerivativeOperator'>
sage: isinstance(DU, sage.symbolic.operators.FDerivativeOperator)
True

and exploring DU. + TAB we find function and parameter_set.

The cases when we want to replace are those where the operator is an FDerivativeOperator and has a single variable. See use_prime above.

Besides exploring using TAB and ?, searching existing questions and tickets can also prove useful, see below.

Inspiration and related material

This answer was inspired by answers to similar questions.

Some queries

In particular see @tmonteil's answer to

and some answers to

Making the D operator more accessible is the object of

edit flag offensive delete link more

Comments

The fact that diff(f(x),x).operator() != diff(f(x),x).operator() is because the FDerivativeOperator class does not have an __eq__ defined on it. That could easily be fixed. With that in place, one could hope that a substitute_function-based approach would work, but the problem there is that diff(f(x),x).substitute_function(f,g) does a function replacement inside the FDerivativeOperator, So you can't use substitute_function. That suggests the right approach is to change the differentiation rules on U rather than try to fix the representation after the fact.

nbruin gravatar imagenbruin ( 2020-12-05 22:14:21 +0200 )edit

@nbruin -- yes, I almost opened a ticket for adding a method __eq__ to the class FDerivativeOperator while preparing my answer. I was not sure whether to do it since in the symbolic ring, == creates an equation rather than comparing; but FDerivativeOperator elements do not seem to be counted as symbolic expressions, so adding this __eq__ method might be a good idea after all.

Now tracked at

slelievre gravatar imageslelievre ( 2020-12-07 03:52:51 +0200 )edit

Thank you, @slelievre! your answer was really informative. Although my approach is simpler, yours is way more elegant. I learned some interesting things with it.

dsejas gravatar imagedsejas ( 2021-01-04 06:28:32 +0200 )edit

@dsejas -- thanks for the feedback!

slelievre gravatar imageslelievre ( 2021-01-04 09:31:16 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2020-12-04 15:18:11 +0200

Seen: 575 times

Last updated: Dec 05 '20