How to apply a variational operator in SymPy?

282 views
Skip to first unread message

Saullo Castro

unread,
Sep 4, 2013, 4:31:04 AM9/4/13
to sy...@googlegroups.com
I've been trying to use SymPy to apply the variational operator in some functions but I believe I am not in the right way.

I have this toy example and the expected result below:

import sympy
from sympy import Function as f
sympy.var('x, t')
N = f('N')(x,t)
w = f('w')(x,t)
test = N*w.diff(x, x)
print test
#N(x, t)*Derivative(w(x, t), x, x)

#expected results after applying the variational operator (\delta)
# \delta{Derivative(w(x, t), x, x)}*N + Derivative(w(x, t), x, x)*\deltaN

Is there such operator in SymPy?

Thank you in advance!
Saullo

Sergey Kirpichev

unread,
Sep 4, 2013, 5:48:30 AM9/4/13
to sy...@googlegroups.com
No.  But an implementation of variational calculus could be helpful (e.g., here: https://github.com/sympy/sympy/pull/2431).  See, for example, the VariationalMethods Mathematica package.

Saullo Castro

unread,
Sep 4, 2013, 6:20:55 AM9/4/13
to sy...@googlegroups.com
I have been using a differential operator which could be adjusted to a variational operator. The differential requires commutative=False, but I think the variational operator can be implemented without this requirement... 

in this Issue 3198: implement Euler-Lagrange equations, did you implement this kind of operator? Is this pull request already merged?
Thank you


2013/9/4 Sergey Kirpichev <skirp...@gmail.com>

--
You received this message because you are subscribed to a topic in the Google Groups "sympy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sympy/cvOjJdEWprM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
For more options, visit https://groups.google.com/groups/opt_out.

Sergey B Kirpichev

unread,
Sep 4, 2013, 7:11:16 AM9/4/13
to sy...@googlegroups.com
On Wed, Sep 04, 2013 at 12:20:55PM +0200, Saullo Castro wrote:
> in this Issue 3198: implement Euler-Lagrange equations, did you implement this kind of operator?

The left-hand side of Euler-Lagrange equation is a functional
derivative for the functional of some (well known) form.

> Is this pull request already merged?

No, AFAIK. You can check the current status of the pr.

Saullo Castro

unread,
Sep 4, 2013, 1:26:54 PM9/4/13
to sy...@googlegroups.com
Today I've done this so far.... it works very well for many test cases I've played here:


Tomorrow or on Friday I will implement the integration by parts which is very typical to get the Euler-Lagrange equations....


Thank you for the support!
Saullo


2013/9/4 Sergey B Kirpichev <skirp...@gmail.com>

Aaron Meurer

unread,
Sep 4, 2013, 11:34:49 PM9/4/13
to sy...@googlegroups.com
One note about your code, you should use expr.func, not
expr.__class__. Right now, they are generally the same, but we reserve
the right to make them differ at some point, in case it becomes
convenient to make expressions rebuild with something other than their
literal class.

Aaron Meurer
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Saullo Castro

unread,
Sep 5, 2013, 7:02:14 AM9/5/13
to sy...@googlegroups.com
Thank you very much by the tip Aaron.... I will keep working on that and let you know.

One think, is it possible to define a method like __diff__() that tells how the class should be differentiated in Sympy, like we do for __mul__, __add__ etc... ?

Saullo


2013/9/5 Aaron Meurer <asme...@gmail.com>

Sergey B Kirpichev

unread,
Sep 5, 2013, 7:35:45 AM9/5/13
to sy...@googlegroups.com
On Thu, Sep 05, 2013 at 01:02:14PM +0200, Saullo Castro wrote:
> One think, is it possible to define a method like __diff__() that tells
> how the class should be differentiated in Sympy, like we do for __mul__,
> __add__ etc... ?

See the Derivative class docstring.

Saullo Castro

unread,
Sep 5, 2013, 7:47:14 AM9/5/13
to sy...@googlegroups.com
Thank you! that helped!



2013/9/5 Sergey B Kirpichev <skirp...@gmail.com>

Saullo Castro

unread,
Sep 5, 2013, 9:59:22 AM9/5/13
to sy...@googlegroups.com
I've updated the routine with the suggestions given by you.
So far the variational operations are being applied correctly.
You create the functional using the built-in Function class and then transform it to a variational expression Vexpr():
You can then differentiate an instance of Vexpr() using diff as usual.

I would kindly ask you some more help:
- how to change the printer from Function to give just "u" instead of "u(x, t)", for example. I tried subclassing Function like shown in the code but without success
- how to change the printer to print "\delta" + function.__class__.__name__. In qtconsole when I create a Symbol called 'delta' it changes it to a symbolic \delta.... is it possible to declare a method in the class to guide the printer in qtconsole?

Thank you all!



2013/9/5 Saullo Castro <saullo...@gmail.com>

Sergey B Kirpichev

unread,
Sep 5, 2013, 10:46:36 AM9/5/13
to sy...@googlegroups.com
On Thu, Sep 05, 2013 at 03:59:22PM +0200, Saullo Castro wrote:
> - how to change the printer from Function to give just "u" instead of
> "u(x, t)", for example. I tried subclassing Function like shown in the
> code but without success

You can see how printers works in sympy/printing/

Alan Bromborsky

unread,
Sep 5, 2013, 10:51:01 AM9/5/13
to sy...@googlegroups.com
Below is what I did to achieve what you want (note the last statement)


class GaPrinter(StrPrinter):

function_names = ('acos', 'acosh', 'acot', 'acoth', 'arg', 'asin',
'asinh',
'atan', 'atan2', 'atanh', 'ceiling', 'conjugate',
'cos',
'cosh', 'cot', 'coth', 'exp', 'floor', 'im',
'log', 're',
'root', 'sin', 'sinh', 'sqrt', 'sign', 'tan',
'tanh', 'Abs')

def _print_Function(self, expr):
name = expr.func.__name__

if expr.func.nargs is not None:
if name in GaPrinter.function_names:
return(expr.func.__name__ + "(%s)" %
self.stringify(expr.args, ", "))

return Eprint.Fct("%s" % (name,))

Basic.__str__ = lambda self: GaPrinter().doprint(self)

Aaron Meurer

unread,
Sep 5, 2013, 7:16:28 PM9/5/13
to sy...@googlegroups.com
See http://docs.sympy.org/0.7.3/modules/printing.html. You need to
override a method in your class (the method names differ depending on
what printer you want to override).

Aaron Meurer
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Saullo Castro

unread,
Sep 6, 2013, 12:53:07 PM9/6/13
to sy...@googlegroups.com
Thank you all by the tips!
I've finished the integration by parts and now it's working really well. I've added a known functional as one of the testing cases.
In the next days I would like to work on the printer and add some documentation, but before... I'd like to know if there is any interest from the SymPy-dev side to add this tool in SymPy.

It would also be nice to have someone else testing this with more known functionals....

Saullo


2013/9/6 Aaron Meurer <asme...@gmail.com>

Aaron Meurer

unread,
Sep 6, 2013, 7:10:16 PM9/6/13
to sy...@googlegroups.com
Perhaps. We already have https://github.com/sympy/sympy/pull/2431. Can
it extend the behavior from there?

Aaron Meurer

Saullo Castro

unread,
Sep 7, 2013, 4:13:01 AM9/7/13
to sy...@googlegroups.com
I tried to clone https://github.com/sympy/sympy/pull/2431 but this is not merged yet. How can I clone from this pull request in order to work in it?

Thank you!


2013/9/7 Aaron Meurer <asme...@gmail.com>

Sergey B Kirpichev

unread,
Sep 7, 2013, 5:12:38 AM9/7/13
to sy...@googlegroups.com
On Sat, Sep 07, 2013 at 10:13:01AM +0200, Saullo Castro wrote:
> I tried to clone�[1]https://github.com/sympy/sympy/pull/2431�but this is
> not merged yet. How can I clone from this pull request in order to work in
> it?

Clone sympy first. Then, add remote repository you needed:
git remote add github-somenick g...@github.com:somenick/sympy.git
git fetch github-somenick

and check out the branch you want to work on:
git checkout -b you-name-it github-somenick/somebranch

PS:
Inspired by:
https://github.com/sympy/sympy/wiki/Development-workflow#wiki-cloning-sympy

Saullo Castro

unread,
Sep 7, 2013, 5:26:49 AM9/7/13
to sy...@googlegroups.com, skirp...@gmail.com
I created a fork of sympy in my account.
Now I don't know which branch to add in order to get this pull request.
For this case, which name should I use for github-somenick ? And for somebranch.

Sorry by these basic questions, but I have really no idea !

Aaron Meurer

unread,
Sep 7, 2013, 3:03:16 PM9/7/13
to sy...@googlegroups.com, skirp...@gmail.com
The workflow is that you clone a repo once, from the official github
(so in this case, sympy/sympy), and you add forks (including your own)
as remotes. So, if you haven't cloned yet

git clone g...@github.com:sympy/sympy.git
cd sympy

then add skirpichev as a remote

git remote add skirpichev g...@github.com:sympy/sympy.git

and download the code

git fetch skirpichev

and check out the code

git checkout skirpichev/3198-euler

This will checkout a "detached head" state. If you want to commit
additional changes to the remote branch, you need to create your own
branch.

git branch branchname

By the way, you can replace the ssh urls with https or git urls if you
want. It's recommended to use ssh for your own fork, though, if your
network allows it, because it's much easier and more secure.

Once you do have your own fork, you can do

git remote add github g...@github.com:yournick/sympy.git

(replace "yournick" with your nickname).

The names of the remotes are arbitrary, but it's easiest if you use
"github" for your fork and the person's username for other people's
forks.

Then, to push code to your fork, use

git push github branchname

Aaron Meurer

Saullo Castro

unread,
Sep 8, 2013, 3:06:47 AM9/8/13
to sy...@googlegroups.com
@Aaron, thank you very much for the explanation. I would have taken much longer to achieve this alone... we should post this as a question in StackOverflow since I haven't found it there so far...


2013/9/7 Aaron Meurer <asme...@gmail.com>
You received this message because you are subscribed to a topic in the Google Groups "sympy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sympy/cvOjJdEWprM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sympy+un...@googlegroups.com.

Aaron Meurer

unread,
Sep 8, 2013, 6:43:57 PM9/8/13
to sy...@googlegroups.com
The workflow I described is not the only way to do things, it's just
the way that we do things in this community (and most similar
communities on GitHub). But some projects use completely different
workflows (e.g., some projects push all their branches to the main
repo and don't use forks at all).

The best thing is to try to understand what each of the git commands
does, clone, remote add, fetch, checkout, branch, push, etc. If you
understand what all the commands actually do, then doing anything in
git is just a matter of breaking what you want to do into the relevant
commands.

Aaron Meurer

Saullo Castro

unread,
Sep 9, 2013, 9:31:50 AM9/9/13
to sy...@googlegroups.com
I've extended the:

test_euler.py

from Sergey's branch.
Unfortunately I did not manage to send him back a push request of the performed changes, so I created a temporary gist here:


@Sergey, could you have a look if your module handles this type of functionals. If not I want to put the ideas of this:
 
Into your module.

Thank you!


2013/9/9 Aaron Meurer <asme...@gmail.com>

Sergey B Kirpichev

unread,
Sep 9, 2013, 11:36:09 AM9/9/13
to sy...@googlegroups.com
On Mon, Sep 09, 2013 at 03:31:50PM +0200, Saullo Castro wrote:
> Unfortunately I did not manage to send him back a push request of the
> performed changes

Please, push your changes to some branch in your sympy's forked repo
on Github. Then navigate to your repository with the changes you want
someone else to pull. Select branch, and press the Pull Request
button, then new pull request. Choose my branch as base fork and
branch with your changes as head fork.

Some guide is in our wiki:
https://github.com/sympy/sympy/wiki/Development-workflow#wiki-create-a-patch-file-or-pull-request-for-github
(Yet, a bit outdated pictures, I think.)

> @Sergey, could you have a look if your module handles this type of
> functionals.

It seems, your lagrangian has a high-order derivatives, like this:
http://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation#Single_function_of_single_variable_with_higher_derivatives
So, no. The pr#2431 is for classical mechanics (no constraints), just
a handy hard-coded formula.
Reply all
Reply to author
Forward
0 new messages