Skip to content

Differentiate(x, n) returns raw chain-rule output where Differentiate(x) n times returns the answer #1002

Description

@Rafael-SOWNet

Measured on master at 5211ccd6. Not about constants — this is an ordinary variable.

var x = MathS.Var("x");
"x ^ 3".ToEntity().Differentiate(x, 2)                     // (0 * x ^ 2 + 2 * x ^ 1 * 1 * 3) * 1 + 0 * 3 * x ^ 2
"x ^ 3".ToEntity().Differentiate(x).Differentiate(x)       // 2 * x * 3

Same value, and one of them is an answer.

Why

The two overloads take different routes:

public Entity Differentiate(Variable variable)
    => Transformation.Differentiation(variable).ApplyOrKeep(this);

internal Entity DifferentiateOnce(Variable variable)
    => InnerDifferentiate(variable).InnerSimplified;      // <- the simplification

public Entity Differentiate(Variable x, int power)
{
    ...
        ent = ent.InnerDifferentiate(x);                  // <- straight to the raw form
    ...
}

Differentiate(Variable) goes through the transformation, which ends at DifferentiateOnce and calls InnerSimplified. Differentiate(Variable, int) calls InnerDifferentiate directly in its loop, so nothing is ever simplified — and because each iteration differentiates the unsimplified result of the last, the expression compounds: every 0 * and * 1 the chain rule produces is still there to be differentiated again on the next pass.

That is also why it is worse than a cosmetic difference. At power = 3 the input to the third differentiation is already the unreduced output of two, so the cost grows with the mess rather than with the derivative.

Not the first-power case

Differentiate(x, 1) is fine — one raw pass is what InnerDifferentiate is for, and there is nothing accumulated yet. It is power >= 2 that diverges, and power = 0 (returns the input) and power < 0 (integrates) are unaffected.

Fix

Use DifferentiateOnce in the loop, which is the method that exists for exactly this and is what the other overload reaches anyway.

Found while measuring #993, where "pi ^ 3".Differentiate(MathS.pi, 2) shows the same shape — but that one is about the constant, and this reproduces with any variable, so it is separate.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions