Closed ocots closed 6 months ago
Very nice. Not sure to understand the "order" you introduced. (Seems to me that composing brackets in readable, and enough for applications.) One could alternatively define a macro so that
@Lie F10001
computed
Lie(F1, Lie(F0, ..., Lie(F0, F1)...)
(And similarly for Poisson brackets, e.g. Lie bracket and lifts.)
NB. A bit confused by your notations as
[X,Y] = X\cdot Y-Y\cdot X = \mathrm{ad}_X (Y) (\neq X\cdot Y).
Ok I will make a pass on the notations. I used Ad
since it was already existing.
The name order
is not good I guess, I will find something else or remove it. The idea was to give all the vector fields to the function Lie
, and then, composed them to make Lie brackets by giving something like F10001
but I have chosen to give the indices of the vector fields in the function.
F10 = Lie(F0, F1, F2, order=(2, 1))
F10001, F21, F201 = Lie(F0, F1, F2, orders=((2, 1, 1, 1, 2), (3, 2), (3, 1, 2))
F1
is at the second place while F0
is at the first one so to compute F10
you give the "order" (2, 1)
. I started from 1
since you can also write (you can switch places or have different names):
F10 = Lie(F2, F1, F0, order=(2, 3))
XY = Lie(X, Y, Z, order=(1, 2))
And I had introduced labels if giving the index was no so clear.
I guess I can write you macro which calls my function. Do you prefer:
@Lie F10001
@Lie F21
@Lie F201
or
@Lie F10001, F21, F201
Some changes:
# lift
H = Lift(X) # H(x, p) = p⋅X(x)
# directional derivatives
Der(X, f)(x) = (X⋅f)(x) = Lie(X, f)(x) # = f'(x)⋅X(x)
Der(X, Y)(x) = (X⋅Y)(x) # = JY(x) X(x)
# Lie brackets
Lie(X, Y) = ad(X, Y)= X⋅Y-Y⋅X # = [X, Y]
Lie(X, Y, Z, sequence=(1, 3)) # = [X, Z]
Lie(X, Y, Z, sequence=(1, 3, 2)) # = [[X, Z], Y]
Lie(X, Y, Z, sequences=((1, 3), (1, 3, 2))) # = [X, Z], [[X, Z], Y]
Lie(X, Y, Z, sequence=(:X, :Z)) # = [X, Z], if the vector fields have labels
@Lie F012 # F012 = [[F0, F1], F2]
But I don't manage to write a macro to compute several brackets in one line:
@Lie F01, F12, F101
Here is the macro for one bracket:
function _Lie(expr::Symbol)
v = split(string(expr))[1]
@assert v[1] == 'F'
uni = sort(unique(v[2:end]))
vfs = Tuple([Symbol(:F, n) for n ∈ uni])
seq = [parse(Integer, c) for c ∈ v[2:end]]
sequence = Tuple([findfirst(v->v==s, parse.(Integer, uni)) for s ∈ seq])
code = quote
$expr = Lie($(vfs...), sequence=$sequence)
end
return code
end
macro Lie(expr::Symbol)
esc(_Lie(expr))
end
and this for several:
macro Lie(expr::Expr)
@assert hasproperty(expr, :head)
(@assert(s isa Symbol) for s ∈ expr.args)
dump(expr)
eval.([_Lie(s) for s ∈ expr.args])
end
But I want to remove eval
. Any help?
@ocots not sure about what you want to do but: regarding eval
, you should be able to write your loop inside the generated code.
You want to compute several brackets to save time, right? Since, for instance, you need $F{01}$ to compute $F{001}$?
It was just to compute several brackets in one line with one call to @Lie
. Not very useful.
Instead, I suggest this:
XY = @Lie [X, Y]
F = @Lie [[X, Y], [[X, Y], Z]]
To compute any Lie bracket.
ouh, nice shot mr @ocots! I did not even thought of macro to access [ ] brackets. Well done. Same for Poisson, BTW.
To sum up, I have:
# lift
H = Lift(X) # H(x, p) = p⋅X(x)
# directional derivatives
Der(X, f)(x) = (X⋅f)(x) = Lie(X, f)(x) # = f'(x)⋅X(x)
Der(X, Y)(x) = (X⋅Y)(x) # = JY(x) X(x)
# Lie brackets
Lie(X, Y) = ad(X, Y)= X⋅Y-Y⋅X = @Lie [X, Y] # = [X, Y]
F = @Lie [[X, Y], [[X, Y], Z]]
@Lie F012 # F012 = [[F0, F1], F2]
I have removed "sequence" and "labels".
Go to Poisson!
todo: remove Der(X,Y)
and check Lie(X, Y)
with the real intrinsic order 2 definition.
Yes:
@test ((@Lie [ X, Y ])⋅f)(x) == ((X⋅(Y⋅f))(x) - (Y⋅(X⋅f))(x)
Test passed:
@testset "intrinsic definition" begin
X = VectorField(x -> [x[2]^2, -2x[1]*x[2]])
Y = VectorField(x -> [x[1]*(1+x[2]), 3x[2]^3])
f = x -> x[1]^4 + 2x[2]^3
x = [1, 2]
# check real intrinsic order 2 definition of Lie bracket
Test.@test ((@Lie [ X, Y ])⋅f)(x) == ((X⋅(Y⋅f))(x) - (Y⋅(X⋅f))(x))
end
Ok what we have now:
# lift
H = Lift(X) # H(x, p) = p⋅X(x)
# directional derivatives
Lie(X, f)(x) = Der(X, f)(x) = (X⋅f)(x) # = f'(x)⋅X(x)
# Lie brackets
Lie(X, Y) = ad(X, Y) = @Lie [X, Y] # = [X, Y]
F = @Lie [[X, Y], [[X, Y], Z]]
@Lie F012 # F012 = [[F0, F1], F2]
Still WIP.
@BaptisteCbl About the file differential_geometry.jl
of the branch diff-geometry
.
Some updates have to be done and some features have to be added.
@Lie F012
Since we can compute any Lie bracket simply doing
F012 = @Lie [[F0, F1], F2]
the macro
@Lie F012 # F012 = [[F0, F1], F2]
is not useful anymore. This part of the code should be removed and the unit tests must be updated:
# type
const Sequence = Tuple{Vararg{Integer}}
# default value of a sequence of vector fields to compute one Lie bracket
__fun_sequence(Xs::VectorField...) = Tuple(1:length(Xs))
#
function _Lie_sequence(Xs::VectorField{td, sd}...; sequence::Sequence=__fun_sequence(Xs...))::VectorField{td, sd} where {td, sd}
# check length of Xs
length(Xs) < 2 && throw(IncorrectArgument("Xs must have at least two elements"))
# check length of sequence
length(sequence) < 2 && throw(IncorrectArgument("sequence must have at least two elements"))
# check if the elements of sequence are contained in 1:length(Xs)
for o ∈ sequence
o < 1 && throw(IncorrectArgument("sequence must contain only positive integers"))
o > length(Xs) && throw(IncorrectArgument("sequence must contain only integers less than or equal to the length of Xs"))
end
#
if length(sequence) == 2
return Lie(Xs[sequence[1]], Xs[sequence[2]])
else
return Lie(_Lie_sequence(Xs..., sequence=sequence[1:end-1]), Xs[sequence[end]])
end
end
macro Lie(expr::Symbol)
# split symbol into substrings
v = split(string(expr))[1]
# check if the first character is 'F'
@assert v[1] == 'F'
# get the unique numbers in the symbol
uni = sort(unique(v[2:end]))
# build the tuple of needed vector fields
vfs = Tuple([Symbol(:F, n) for n ∈ uni])
# build the sequence to compute the Lie bracket
user_sequence = [parse(Integer, c) for c ∈ v[2:end]] # conversion to integer
sequence = Tuple([findfirst(v->v==s, parse.(Integer, uni)) for s ∈ user_sequence])
# build the code
code = quote
$expr = _Lie_sequence($(vfs...), sequence=$sequence)
end
return esc(code)
end
Then, I have defined
which should be updated according to the new parameterization of functions, cf. this comment.
Remark. The Hamiltonian structure must be <: AbstractHamiltonian
.
Then, we need to had the Poisson bracket of two AbstractHamiltonian
, according to
function Poisson(f, g)
function fg(x, p)
n = size(x, 1)
ff = z -> f(z[1:n], z[n+1:2n])
gg = z -> g(z[1:n], z[n+1:2n])
df = ctgradient(ff, [ x ; p ])
dg = ctgradient(gg, [ x ; p ])
return df[n+1:2n]'*dg[1:n] - df[1:n]'*dg[n+1:2n]
end
return fg
end
See Poisson bracket Wikipedia.
Remark. If the two Hamiltonians are lifts of vector fields, then, there is a relation between the Poisson bracket of the Hamiltonians and the Lie bracket of the associated vector fields, cf. ici (not the best ref.).
Hi ! I have made some of the changes in this branch of my fork but it is not finished, I need to add the macro for Poisson (the classic function works) and add tests for it. Also Lift is broken for now because of the update from the original diff-geometry branch to the develop version of CTBase. I'll finish it as soon as possible.
@ocots @BaptisteCbl Hi! Curly brackets { , }
that are the standard notation for Poisson brackets are also available via macros, so it is possible to do the same as Olivier did for Lie ones:
julia> @dump { f, g }
Expr
head: Symbol braces
args: Array{Any}((2,))
1: Symbol f
2: Symbol g
julia> @Poisson { f, { f, g } }
Hi, I have added the macro for Poisson and some tests. But before making the pull request I have a question.
I still don't know how to handle the variables of the non-fixed functions (VectorField
and directional derivative for Lie and AbstractHamiltonian
for Poisson), so there is no support for these non-fixed functions at the moment.
Does having a Poisson bracket of a variable dependent Hamiltonian have any meaning ? If so, does it have to be treated like the time variable of non autonomous functions ?
It has a meaning to compute Lie or Poisson brackets for functions depending on parameters such as a Variable. However we do not differentiate wrt the parameter. Maybe you can use args...
.
It has a meaning but it does not change anything in the computation to have a Variable.
However, for non autonomous vector fields or Hamiltonians, we should compute the partial derivative with respect to time in the Lie and Poisson brackets.
@jbcaillau what do you think?
@BaptisteCbl We can speak about that around 15:30 on discord if you want.
Yes I would like to, thank you. I sent you a request on Discord but if you want to do it on other platform I'm okay too.
Discord is fine.
I need 10''. Do you find me on discord?
Yes, I sent you a friend request and a message.
I can't see it: ocots#3541
@ocots @BaptisteCbl Hi guys, I would say yes: for time dependent functions, it makes sense to include time as an additional variable (for differentiation).
@BaptisteCbl I think you can abort the idea to add partial derivatives with respect to time in the Lie derivative, bracket and Poisson bracket. It seems difficult to have something consistent.we will see with use cases later.
@BaptisteCbl I think you can abort the idea to add partial derivatives with respect to time in the Lie derivative, bracket and Poisson bracket. It seems difficult to have something consistent.we will see with use cases later.
@ocots don't you have an example (irrigation thing...) with time dependent vector fields? it is good to start from a use case an check what kind of computation you need in this setting.
Actually, we need to differentiate in my use cases:
t -> g(t, x(t)) # state constraint
t -> H1(t, x(t), p(t)) # switching function
If we have:
ẋ(t) = F₀(t, x(t)) + u(t) F₁(t, x(t)) # the dynamics
H(t, x, p, u) = H₀(t, x, p) + u H₁(t, x, p) # the pseudo-Hamiltonian
g(t, x) ≤ 0 # the state constraint
We may need to compute:
t -> ∂ₜg(t, x(t)) + ∂ₓg(t, x(t))⋅ẋ(t)
t -> ∂ₜH₁(t, x(t), p(t)) + ∂ₓH₁(t, x(t), p(t))⋅ẋ(t) + ∂ₚH₁(t, x(t), p(t))⋅ẋ(t)
which is given for the moment by:
t -> ∂ₜg(t, x(t)) + Lie(F₁, g)(t, x(t))
t -> ∂ₜH₁(t, x(t), p(t)) + Poisson(H₀, H₁)(t, x(t), p(t))
But I have no example for the Lie bracket of two vector fields.
Considering
(X⋅f)(x) = f'(x)⋅X(x)
(X⋅f)(t, x) = ∂ₜf(t, x) + ∂ₓf(t, x)⋅X(t, x)
It seems difficult in the non-autonomous case to keep properties like the following ones if we add partial derivatives.
[X, Y]⋅f = (X∘Y - Y∘X)⋅f
{f,g}(t, z) = p⋅[X,Y](t, x)
if
f(t, z) = p⋅X(t, x)
g(t, z) = p⋅Y(t, x)
z = (x, p)
But somehow, we could add a state variable whom dynamics is ṫ = 1
and retrieve an autonomous system. For the Lie derivative, it is exactly what we want. I don't know what happens for the Lie bracket but it should be fine. I am more embarrassed with the Poisson bracket since one dual variable is missing.
@ocots Yes: adding the time as an additional state should work (there is indeed an associated dual variable, $p_t$). A good test is to write things for this example and check whether it remains user friendly, both from the mathematical and coding sides.
Attention, les calculs sont FAUX et d'un point de vue pratique, on n'a pas intérêt à mettre les dérivées partielles par rapport au temps car à la fin on veut calculer le contrôle et on aura toujours à calculer deux crochets et une seule dérivée partielle par rapport au temps.
Pourquoi pas fournir 3 fonctions : ∂ₜ
, ∂ₓ
et ∂ₚ
.
@BaptisteCbl Actually, it is ok. You can code the non-autonomous case with partial derivatives wrt time.
Let X
being a vector field and f
a differential function. We define
(X⋅f)(t, x) = ∂ₜf(t, x) + ∂ₓf(t, x)⋅X(t, x) # Lie derivative of f along X
[X, Y]⋅f = (X∘Y - Y∘X)⋅f # Lie bracket of X and Y
Then,
([X, Y]⋅f)(t, x) = ∂ₓf(t, x)⋅(∂ₜY(t, x)+∂ₓY(t, x)⋅X(t, x) - (∂ₜX(t, x)+∂ₓX(t, x)⋅Y(t, x)))
which is ok since there is no order 2. We thus define
(X ⅋ Y)(t, x) = ∂ₜY(t, x) + ∂ₓY(t, x)⋅X(t, x) = Y'(t, x)⋅(1, X(t, x))
so that
[X, Y] = X ⅋ Y - Y ⅋ X
For the Poisson bracket, we denote by F
the Hamiltonian vector field associated to f
, a Hamiltonian now (I cannot write arrows). So:
F(t, z) = (∂ₚf(t, z), -∂ₓf(t, z)) # f(t, z) a non-autonomous Hamiltonian and F its Hamiltonian vector field
We define the Poisson bracket as:
{f, g} = F⋅g # the Lie derivative of g along F
Like this we have what we want since
{f, g}(t, z) = ∂ₜg(t, z) + ∂_z g(t, z)⋅F(t, z)
and let consider for instance that we want to differentiate wrt time t -> g(t, z(t))
with ż(t) = F(t, z(t))
. We get
dₜ g(t, z(t)) = ∂ₜg(t, z(t)) + ∂_z g(t, z(t))⋅ż(t) = {f, g}(t, z(t))
The only thing that changes is the following. Assume that
f(t, z) = p⋅X(t, x)
g(t, z) = p⋅Y(t, x)
Then,
{f, g}(t, z) = p⋅([X, Y](t, x) + ∂ₜX(t, x))
if I have not made a mistake.
Ok, thanks ! I'll try to implement it in #85.
@ocots Seems OK and in line with what you previously said, i.e. adding $t'(s)=1$ with $s$ a new time. Some thoughts:
I suppose that subtyping + dispatch à la {<:TimeDependence}
might do the job.
We can reuse code since we can compute Poisson bracket from Lie derivative.
Don't know if it is a good idea to use the autonomous case.
hello mr @ocots!
👋
mollo on coconut milk for breakfast, please 🤭
Et les mangues, excellentes 😁
Recap of what we will have:
Let X
being a vector field and f
a differentiable function. We define
(X⋅f)(t, x) = ∂ₓf(t, x)⋅X(t, x) # Lie derivative of f along X
[X, Y]⋅f = (X∘Y - Y∘X)⋅f # Lie bracket of X and Y
∂ₜ(f) = ∂ₜf
Then,
([X, Y]⋅f)(t, x) = ∂ₓf(t, x)⋅(∂ₓY(t, x)⋅X(t, x) - (∂ₓX(t, x)⋅Y(t, x)))
We thus define
(X ⅋ Y)(t, x) = ∂ₓY(t, x)⋅X(t, x)
so that
[X, Y] = X ⅋ Y - Y ⅋ X
For the Poisson bracket, we denote by F
the Hamiltonian vector field associated to f
, a Hamiltonian now (I cannot write arrows). So:
F(t, x, p) = (∂ₚf(t, x, p), -∂ₓf(t, x, p)) # f(t, x, p) a non-autonomous Hamiltonian and F its Hamiltonian vector field
We define the Poisson bracket as:
{f, g} = F⋅g # the Lie derivative of g along F
and let consider for instance that we want to differentiate wrt time t -> g(t, x(t), p(t))
with ż(t) = F(t, z(t))
, z=(x,p)
. We will write
∂ₜ(g)(t, x(t), p(t)) + {f, g}(t, x(t), p(t))
@ocots One quick remark on this:
Regarding Lie derivatives, the idea is to differentiate $f
$ along an integral curve of the nonautonomous vector field, $\dot{x}(t) = X(t, x(t))$, so
\mathrm{d}/\mathrm{d}t (f(t, x(t))) = \partial_t f(t, x(t)) + \partial_x f(t, x(t)) \cdot X(t, x(t)).
Which is coherent with adding a new time $\mathrm{d}t/\mathrm{d}s = 1$ and extending the vector field.
Yes but in practice we do not want this to be automatic. I can explain on phone.
💩
I think we can close this issue. We will talk about it :-)
If we have a constraint c(t, x(t)) = 0
with a dynamics ẋ(t) = F₀(t, x(t)) + u(t) F₁(t, x(t))
, then, to compute the control we will compute
dₜc(t, x(t)) = ∂ₜc(t, x(t)) + ∂ₓc(t, x(t))⋅ẋ(t)
= ∂ₜc(t, x(t)) + ∂ₓc(t, x(t))⋅(F₀(t, x(t)) + u(t) F₁(t, x(t))) = 0
that is
0 = ∂ₜc + F₀⋅c + u F₁⋅c
so we do not want to have (X⋅f)(t, x) = ∂ₜf(t, x) + ∂ₓf(t, x)⋅X(t, x)
since otherwise we would have twice ∂ₜc
.
I see your point. We discuss it this Friday in Marseille. Keeping the issue open.
@ocots @BaptisteCbl One more thing: looks a bit redundant to write
@Poisson { f, g }
@Lie [ X, Y ]
...
Maybe better to use a single macro (@Lie
?) with different brackets / symbols for different operations:
@Lie { f, g }
@Lie [ X, Y ]
@Lie X ⋅ f
Coherence is the master word for me and if brackets/curly_brackets are not significient, then keep only one option:
@Poisson {H0, H1} + @Lie {F0, F1}
or
@Poisson [H0, H1] + @Lie [ F0, F1]
or
@Poisson (H0, H1) + @Lie (F0, F1)
or
@Poisson H0, H1 + @Lie F0, F1
but do not make it confusing for end users…..
(why not : @Poisson { [ (H0), (H1)] } and @Lie F0 / F1 ????
On 7 Jun 2023, at 23:20, Jean-Baptiste Caillau @.***> wrote:
@ocots @BaptisteCbl One more thing: looks a bit redundant to write @Poisson { H0, H1 } @Lie [ F0, F1 ] ... Maybe better to use a single macro @.?) with different brackets / symbols for different operations: @Lie { H0, H1 } @Lie [ F0, F1 ] @Lie F ⋅ g — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.>
— Jean-Luc Szpyrka
Hello nightly @j-l-s ! Actually, it is exactly the point: { , }
and [ , ]
are distinct notations for distinct computations. The first one is for Poisson brackets of (scalar valued) functions, while the second is for Lie brackets of vector fields. (And the third notation F ⋅ g
is for yet another computation...) Prefixing with a macro is just a convenient way (👍🏽 @ocots) to redefine brackets (which is not allowed otherwise). But then, only one macro @foo
is enough. And since all three computations are, in some general sense, "Lie derivatives", it makes sense to call the macro @Lie
(instead of @foo
).
@jbcaillau I have introduced more operations to compute controls, multipliers associated to state constraint of order 1, 2 and more, but also to compute singular arcs of any order.
For the moment, I have:
Lift(X)
returns a HamiltonianAd(X, f)
orX⋅f
andAd(X, Y)
orX⋅Y
I will add of course Poisson brackets.
I need some validation for the syntax and possibilities. I present in the autonomous case but it works also in the non-autonomous case and in both vectorial and scalar cases.
Lifts
From a
VectorField
:or in 2D:
From a function it works also:
H = Lift(x -> 2x)
.Lie derivatives
Between two vector fields.
You can also do:
Lie brackets
You can use the argument
order
to specify the bracket you want. For instance, let us considerThen,
is equivalent to
We can also compute:
If you want several Lie brackets of different lengths, you can do
or for others
Note that it is not so practical to give the orders like that so I have introduced the possibility to give labels:
Then, you can do