Hi <@UGB1USA2J>, great question! It depends on wha...
# mathematics
b
Hi @Iaroslav Postovalov, great question! It depends on what you mean by "order" as the term is slightly overloaded. If you mean the order of partial derivative evaluation, then under some weak assumptions, the derivative operator is commutative. This result (see Clairaut-Schwarz) holds on all twice-differentiable functions. However, it is not necessarily true on all differentiable functions! I.e it is possible to have a continuously differentiable function whose partials are defined everywhere but the permuted partials are unequal ∂F²/∂x∂y ≠ ∂F²/∂y∂x. For some examples of continuously differentiable functions where the derivative operator is noncommutative, see Tolstov (1949, 1949). On the other hand, if by "order", you mean "higher order derivatives", then this is a slightly different (although related) question. In general, I find it is helpful to first write down a test case describing the behavior you expect, e.g.:
assertEquals(f.derivativeOrNull(mapOf(x to 2)), f.derivativeOrNull(mapOf(x to 1)).derivativeOrNull(mapOf(x to 1)))
. This helps to clarify what is meant by
derivativeOrNull(orders: Map<Symbol, Int>): Expression<T>
and suggests one possible implementation. Assuming you only care about
SFun
and
SVar
then it should be possible to define
derivativeOrNull
using
fold
, noting the above restrictions on evaluation order. More generally, due to the semantics of mixing partial derivatives, depending how
Map
is implemented, you cannot assume
f.derivativeOrNull(mapOf(y to 1)).derivativeOrNull(mapOf(x to 1)) == f.derivativeOrNull(mapOf(x to 1, y to 1))
without knowing more about the function under differentiation. To implement
derivativeOrNull
correctly, you would need a data structure whose traversal order preserves the semantics of the end-user program. Although it is possible to implement something like
OrderPreservingMap
, I would just use
List<Symbol>
. Then your implementation becomes cleaner:
Copy code
public override fun derivativeOrNull(orders: List<Symbol>): Expression<T> = 
    orders.map { MstAlgebra.symbol(it.identity).toSVar(proto) }
      .fold(mst.toSFun(proto)) { result, sVar -> result.d(sVar) } // This will produce Derivative(...Derivative(mst.toSFun(proto))...)
      .invoke() // Do you want to evaluate it?
      .toKMathExpression()
i
Of course, I meant higher order derivatives. Thanks
b
I updated the solution a bit and added a possible implementation for
derivativeOrNull
. After thinking about it, I think maybe you want
orders
to be
List<Symbol>
In your case, it seems like the order of evaluation and higher order differentiation are not separate issues but related, i.e. how you traverse the `Symbol`s depends on the order of evaluation
Also, I have removed the
proto
structure in
0.3.7
, added a comment to kmath#150
i
@breandan so, in your signature {x:2, y:1} is [x, x, y]?
@altavir can we change the signature of
derivativeOrNull
? @breandan’s List<Symbol> input looks clearer, at least for KG integration
a
It is possible. The list variant is probably more universal since commutativity is not guaranteed in general and it looks better from the user side API. I will think about it a little more.
b
{x:2, y:1} could be [x, x, y] or [y, x, x] or [x, y, x], it depends on how
Map
is implemented but is ambiguous without additional structure
i
I got it.
a
I thought about it a little and this notation seems to simlify several things without any obvious drawbacks. So I will make the change.