# Revision history [back]

This is tricky, but it can be done. The idea is to replace (in the expression tree) derivatives of $f$ with respect to $t$ by the right-hand side of the equation, substituted into itself as many times as there are derivatives with respect to $t$ minus one, and finally replacing $f$ by the derivative of $f$ with respect to the remaining variables (if any).

My attempt to implement this (based on SubstituteFunction) is below, with an example (your example) in the docstring.

from sage.symbolic.expression_conversions import ExpressionTreeWalker
from sage.symbolic.operators import FDerivativeOperator

class SubstituteEvolutionaryPDE(ExpressionTreeWalker):
def __init__(self, ex, pde):
"""
A class that walks the tree and replaces derivatives of f with
respect to t by the right-hand side of an evolutionary PDE.
EXAMPLES::
sage: var('x,t'); f = function('f'); g = function('g')
sage: pde = diff(f(t,x),t) == 1/2*diff(f(t,x),x,x)
sage: s = SubstituteEvolutionaryPDE(0, pde)
sage: h = g(diff(f(t,x),t), diff(f(t,x),t,x))
sage: s(h)
g(1/2*diff(f(t, x), x, x), 1/2*diff(f(t, x), x, x, x))

ASSUMPTION::

pde is of the form diff(f(t,...),t) == ... and the first
argument of f is always t.
"""
self.f = integrate(pde.lhs(), t).operator()
self.rhs = pde.rhs()
self.ex = ex

def derivative(self, ex, operator):
if operator.function() == self.f and 0 in operator.parameter_set(): # f is differentiated with respect to t
t_derivatives = [p for p in operator.parameter_set() if p == 0] # (assumes t is the first argument)
result = self.rhs
for _ in range(len(t_derivatives)-1):
result = result.substitute_function(self.f, self.rhs)
if len(t_derivatives) < len(operator.parameter_set()): # derivatives w.r.t variables other than t
other_derivatives = [p for p in operator.parameter_set() if not p == 0] # (assumes t is the first argument)
new_operator = FDerivativeOperator(operator.function(), other_derivatives)
result = result.substitute_function(self.f, new_operator(*[self(_) for _ in ex.operands()]))
return result
else:
return operator(*[self(_) for _ in ex.operands()])


This is tricky, but it can be done. The idea is to replace (in the expression tree) derivatives of $f$ with respect to $t$ by the right-hand side of the equation, substituted into itself as many times as there are derivatives with respect to $t$ minus one, and finally replacing $f$ by the derivative of $f$ with respect to the remaining variables (if any).

My attempt to implement this (based on SubstituteFunction) is below, with an example (your example) in the docstring.

docstring.
from sage.symbolic.expression_conversions import ExpressionTreeWalker
from sage.symbolic.operators import FDerivativeOperator

FDerivativeOperator class SubstituteEvolutionaryPDE(ExpressionTreeWalker):
def __init__(self, ex, pde):
pde, t):
"""
A class that walks the tree and replaces derivatives of f with
respect to t by the right-hand side of an evolutionary PDE.
EXAMPLES::
sage: var('x,t'); f = function('f'); g = function('g')
sage: pde = diff(f(t,x),t) == 1/2*diff(f(t,x),x,x)
sage: s = SubstituteEvolutionaryPDE(0, pde)
pde, t)
sage: h = g(diff(f(t,x),t), diff(f(t,x),t,x))
sage: s(h)
g(1/2*diff(f(t, x), x, x), 1/2*diff(f(t, x), x, x, x))

ASSUMPTION::

pde is of the form diff(f(t,...),t) == ... and the first
argument of f is always t.
"""
self.f = integrate(pde.lhs(), t).operator()
self.rhs = pde.rhs()
self.ex = ex

def derivative(self, ex, operator):
if operator.function() == self.f and 0 in operator.parameter_set(): # f is differentiated with respect to t
t_derivatives = [p for p in operator.parameter_set() if p == 0] # (assumes t is the first argument)
result = self.rhs
for _ in range(len(t_derivatives)-1):
result = result.substitute_function(self.f, self.rhs)
if len(t_derivatives) < len(operator.parameter_set()): # derivatives w.r.t variables other than t
other_derivatives = [p for p in operator.parameter_set() if not p == 0] # (assumes t is the first argument)
new_operator = FDerivativeOperator(operator.function(), other_derivatives)
result = result.substitute_function(self.f, new_operator(*[self(_) for _ in ex.operands()]))
return result
else:
return operator(*[self(_) for _ in ex.operands()]) 3 No.3 Revision updated 2018-11-01 17:39:25 +0200 This is tricky, but it can be done. The idea is to replace (in the expression tree) derivatives of $f$ with respect to $t$ by the right-hand side of the equation, substituted into itself as many times as there are derivatives with respect to $t$ minus one, and finally replacing $f$ by the derivative of $f$ with respect to the remaining variables (if any). My attempt to implement this (based on SubstituteFunction) is below, with an example (your example) in the docstring. docstring. from sage.symbolic.expression_conversions import ExpressionTreeWalker from sage.symbolic.operators import FDerivativeOperator FDerivativeOperator class SubstituteEvolutionaryPDE(ExpressionTreeWalker): def __init__(self, ex, pde, t): """ A class that walks the tree and replaces derivatives of f with respect to t by the right-hand side of an evolutionary PDE. EXAMPLES:: sage: var('x,t'); f = function('f'); g = function('g') sage: pde = diff(f(t,x),t) == 1/2*diff(f(t,x),x,x) sage: s = SubstituteEvolutionaryPDE(0, pde, t) sage: h = g(diff(f(t,x),t), diff(f(t,x),t,x)) sage: s(h) g(1/2*diff(f(t, x), x, x), 1/2*diff(f(t, x), x, x, x)) ASSUMPTION:: pde is of the form diff(f(t,...),t) == ... and the first argument of f is always t. """ self.f = integrate(pde.lhs(), t).operator() self.rhs = pde.rhs() self.ex = ex def derivative(self, ex, operator): if operator.function() == self.f and 0 in operator.parameter_set(): # f is differentiated with respect to t t_derivatives = [p for p in operator.parameter_set() if p == 0] # (assumes t is the first argument) result = self.rhs for _ in range(len(t_derivatives)-1): result = result.substitute_function(self.f, self.rhs) if len(t_derivatives) < len(operator.parameter_set()): # derivatives w.r.t variables other than t other_derivatives = [p for p in operator.parameter_set() if not p == 0] # (assumes t is the first argument) new_operator = FDerivativeOperator(operator.function(), other_derivatives) result = result.substitute_function(self.f, new_operator(*[self(_) for _ in ex.operands()])) return result else: return operator(*[self(_) for _ in ex.operands()]) 4 No.4 Revision updated 2018-11-01 18:18:05 +0200 This is tricky, but it can be done. The idea is to replace (in the expression tree) derivatives of $f$ (with at least one derivative with respect to $t$ $t$) by the right-hand side of the equation, substituted into itself as many times as there are derivatives with respect to $t$ minus one, and finally replacing $f$ by the derivative of $f$ with respect to the remaining variables (if any). My attempt to implement this (based on SubstituteFunction) is below, with an example (your example) in the docstring. from sage.symbolic.expression_conversions import ExpressionTreeWalker from sage.symbolic.operators import FDerivativeOperator class SubstituteEvolutionaryPDE(ExpressionTreeWalker): def __init__(self, ex, pde, t): """ A class that walks the tree and replaces derivatives of f with respect to t by the right-hand side of an evolutionary PDE. EXAMPLES:: sage: var('x,t'); f = function('f'); g = function('g') sage: pde = diff(f(t,x),t) == 1/2*diff(f(t,x),x,x) sage: s = SubstituteEvolutionaryPDE(0, pde, t) sage: h = g(diff(f(t,x),t), diff(f(t,x),t,x)) sage: s(h) g(1/2*diff(f(t, x), x, x), 1/2*diff(f(t, x), x, x, x)) ASSUMPTION:: pde is of the form diff(f(t,...),t) == ... and the first argument of f is always t. """ self.f = integrate(pde.lhs(), t).operator() self.rhs = pde.rhs() self.ex = ex def derivative(self, ex, operator): if operator.function() == self.f and 0 in operator.parameter_set(): # f is differentiated with respect to t t_derivatives = [p for p in operator.parameter_set() if p == 0] # (assumes t is the first argument) result = self.rhs for _ in range(len(t_derivatives)-1): result = result.substitute_function(self.f, self.rhs) if len(t_derivatives) < len(operator.parameter_set()): # derivatives w.r.t variables other than t other_derivatives = [p for p in operator.parameter_set() if not p == 0] # (assumes t is the first argument) new_operator = FDerivativeOperator(operator.function(), other_derivatives) result = result.substitute_function(self.f, new_operator(*[self(_) for _ in ex.operands()])) return result else: return operator(*[self(_) for _ in ex.operands()]) 5 No.5 Revision updated 2020-02-14 23:18:57 +0200 This is tricky, but it can be done. The idea is to replace (in the expression tree) derivatives of $f$ (with at least one derivative with respect to $t$) by the right-hand side of the equation, substituted into itself as many times as there are derivatives with respect to $t$ minus one, and finally replacing $f$ by the derivative of $f$ with respect to the remaining variables (if any). My attempt to implement this (based on SubstituteFunction) is below, with an example (your example) in the docstring. from sage.symbolic.expression_conversions import ExpressionTreeWalker from sage.symbolic.operators import FDerivativeOperator class SubstituteEvolutionaryPDE(ExpressionTreeWalker): def __init__(self, ex, pde, t): """ A class that walks the tree and replaces derivatives of f with respect to t by the right-hand side of an evolutionary PDE. EXAMPLES:: sage: var('x,t'); f = function('f'); g = function('g') sage: pde = diff(f(t,x),t) == 1/2*diff(f(t,x),x,x) sage: s = SubstituteEvolutionaryPDE(0, pde, SubstituteEvolutionaryPDE(pde, t) sage: h = g(diff(f(t,x),t), diff(f(t,x),t,x)) sage: s(h) g(1/2*diff(f(t, x), x, x), 1/2*diff(f(t, x), x, x, x)) ASSUMPTION:: pde is of the form diff(f(t,...),t) == ... and the first argument of f is always t. """ f_expr = integrate(pde.lhs(), t) self.f = integrate(pde.lhs(), t).operator() f_expr.operator() self.args = f_expr.operands() self.rhs = pde.rhs() self.ex = ex def derivative(self, ex, operator): if operator.function() == self.f and 0 in operator.parameter_set(): # f is differentiated with respect to t t_derivatives = [p for p in operator.parameter_set() if p == 0] # (assumes t is the first argument) result = self.rhs for _ in range(len(t_derivatives)-1): result = result.substitute_function(self.f, self.rhs) self.rhs.function(*self.args)) if len(t_derivatives) < len(operator.parameter_set()): # derivatives w.r.t variables other than t other_derivatives = [p for p in operator.parameter_set() if not p == 0] # (assumes t is the first argument) new_operator = FDerivativeOperator(operator.function(), other_derivatives) result = result.substitute_function(self.f, new_operator(*[self(_) for _ in ex.operands()])) ex.operands()]).function(*self.args)) return result else: return operator(*[self(_) for _ in ex.operands()]) Edit: updated to use substitute_function correctly (the second argument should also be a function). Copyright Sage, 2010. Some rights reserved under creative commons license. Content on this site is licensed under a Creative Commons Attribution Share Alike 3.0 license. about | faq | help | privacy policy | terms of service Powered by Askbot version 0.7.59 Please note: Askbot requires javascript to work properly, please enable javascript in your browser, here is how //IE fix to hide the red margin var noscript = document.getElementsByTagName('noscript'); noscript.style.padding = '0px'; noscript.style.backgroundColor = 'transparent'; askbot['urls']['mark_read_message'] = '/s/messages/markread/'; askbot['urls']['get_tags_by_wildcard'] = '/s/get-tags-by-wildcard/'; askbot['urls']['get_tag_list'] = '/s/get-tag-list/'; askbot['urls']['follow_user'] = '/followit/follow/user/{{userId}}/'; askbot['urls']['unfollow_user'] = '/followit/unfollow/user/{{userId}}/'; askbot['urls']['user_signin'] = '/account/signin/'; askbot['urls']['getEditor'] = '/s/get-editor/'; askbot['urls']['apiGetQuestions'] = '/s/api/get_questions/'; askbot['urls']['ask'] = '/questions/ask/'; askbot['urls']['questions'] = '/questions/'; askbot['settings']['groupsEnabled'] = false; askbot['settings']['static_url'] = '/m/'; askbot['settings']['minSearchWordLength'] = 4; askbot['settings']['mathjaxEnabled'] = true; askbot['settings']['sharingSuffixText'] = ''; askbot['settings']['errorPlacement'] = 'after-label'; askbot['data']['maxCommentLength'] = 800; askbot['settings']['editorType'] = 'markdown'; askbot['settings']['commentsEditorType'] = 'rich\u002Dtext'; askbot['messages']['askYourQuestion'] = 'Ask Your Question'; askbot['messages']['acceptOwnAnswer'] = 'accept or unaccept your own answer'; askbot['messages']['followQuestions'] = 'follow questions'; askbot['settings']['allowedUploadFileTypes'] = [ "jpg", "jpeg", "gif", "bmp", "png", "tiff" ]; askbot['data']['haveFlashNotifications'] = true; askbot['data']['activeTab'] = 'questions'; askbot['settings']['csrfCookieName'] = 'asksage_csrf'; askbot['data']['searchUrl'] = ''; /*<![CDATA[*/ $('.mceStatusbar').remove();//a hack to remove the tinyMCE status bar$(document).ready(function(){ // focus input on the search bar endcomment var activeTab = askbot['data']['activeTab']; if (inArray(activeTab, ['users', 'questions', 'tags', 'badges'])) { var searchInput = $('#keywords'); } else if (activeTab === 'ask') { var searchInput =$('#id_title'); } else { var searchInput = undefined; animateHashes(); } var wasScrolled = $('#scroll-mem').val(); if (searchInput && !wasScrolled) { searchInput.focus(); putCursorAtEnd(searchInput); } var haveFullTextSearchTab = inArray(activeTab, ['questions', 'badges', 'ask']); var haveUserProfilePage =$('body').hasClass('user-profile-page'); if ((haveUserProfilePage || haveFullTextSearchTab) && searchInput && searchInput.length) { var search = new FullTextSearch(); askbot['controllers'] = askbot['controllers'] || {}; askbot['controllers']['fullTextSearch'] = search; search.setSearchUrl(askbot['data']['searchUrl']); if (activeTab === 'ask') { search.setAskButtonEnabled(false); } search.decorate(searchInput); } else if (activeTab === 'tags') { var search = new TagSearch(); search.decorate(searchInput); } if (askbot['data']['userIsAdminOrMod']) { $('body').addClass('admin'); } if (askbot['settings']['groupsEnabled']) { askbot['urls']['add_group'] = "/s/add-group/"; var group_dropdown = new GroupDropdown();$('.groups-dropdown').append(group_dropdown.getElement()); } var userRep = $('#userToolsNav .reputation'); if (userRep.length) { var showPermsTrigger = new ShowPermsTrigger(); showPermsTrigger.decorate(userRep); } }); if (askbot['data']['haveFlashNotifications']) {$('#validate_email_alert').click(function(){notify.close(true)}) notify.show(); } var langNav = $('.lang-nav'); if (langNav.length) { var nav = new LangNav(); nav.decorate(langNav); } /*]]>*/ if (typeof MathJax != 'undefined') { MathJax.Hub.Config({ extensions: ["tex2jax.js"], jax: ["input/TeX","output/HTML-CSS"], tex2jax: {inlineMath: [["$","$"],["\$","\$"]]} }); } else { console.log('Could not load MathJax'); } //todo - take this out into .js file$(document).ready(function(){ $('div.revision div[id^=rev-header-]').bind('click', function(){ var revId = this.id.substr(11); toggleRev(revId); }); lanai.highlightSyntax(); }); function toggleRev(id) { var arrow =$("#rev-arrow-" + id); var visible = arrow.attr("src").indexOf("hide") > -1; if (visible) { var image_path = '/m/default/media/images/expander-arrow-show.gif?v=19'; } else { var image_path = '/m/default/media/images/expander-arrow-hide.gif?v=19'; } image_path = image_path + "?v=19"; arrow.attr("src", image_path); \$("#rev-body-" + id).slideToggle("fast"); } for (url_name in askbot['urls']){ askbot['urls'][url_name] = cleanUrl(askbot['urls'][url_name]); }