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