39
$\begingroup$

I have been wrapping my head around this for a while now and I have not found a solution so far. I want to work with an arbitrary number of variables in Mathematica and use some built in functions. To make things more specific for starters I want to do the following. Define a sum with $n$ summands each containing a new variable x[i] (in the $i$-th summand):

sum[n_] = Sum[i x[i], {i, 1, n}]

Then I want to differentiate the expression with respect to some x[i] like:

D[sum[n], x[2]]

Mathematica returns $0$ instead of $2$. However if I supply a specific $n$ like:

D[sum[2], x[2]]

everything works fine. I thought about using Assumption for $n$, but with no success so far. How can I do that right?

$\endgroup$
7
  • $\begingroup$ Evaluating D[sum[n], x[2]] is essentially the same as evaluating D[Sum[n, y], x[2]], where y is value-free, which is nothing D recognizes as depending on x[2]. $\endgroup$
    – m_goldberg
    Dec 15, 2012 at 16:10
  • 2
    $\begingroup$ This question is closely related to and might even be considered a duplicate of this one $\endgroup$
    – m_goldberg
    Dec 15, 2012 at 16:25
  • 1
    $\begingroup$ Extending Mathematica to allow sums of symbolic length really would require extended it to allow lists of symbolic length; only then could one properly worry about differentiating such objects. But how to make a robust, general design for such an extension is hardly obvious and raises all sorts of issues, e.g.: Should Infinity to an acceptable value for n? What would the effect be upon processing speed for specific-length objects? $\endgroup$
    – murray
    Dec 15, 2012 at 17:41
  • 1
    $\begingroup$ I've changed your title to something more specific. please change it to something else if you think it's better $\endgroup$
    – acl
    Dec 15, 2012 at 19:39
  • 5
    $\begingroup$ For formal differentiation, what I've noticed is if it's in a tuxedo it's probably a guy, and if it's in a gown it's usually a gal. But this is only a rough guideline, and anyway times have changed. $\endgroup$ Dec 15, 2012 at 22:15

7 Answers 7

42
$\begingroup$

Here is the simplest answer:

sum[n_] := Sum[i x[i], {i, 1, n}]

x /: D[x[i_], x[j_], NonConstants -> {x}] := 
 KroneckerDelta[i, j]

D[sum[n], x[2], NonConstants -> x]

$\begin{cases} 2 & n>1 \\ 1-n & \text{True} \end{cases}$

The trick here is the use of the NonConstants option of the derivative operator. This then has to be combined with a definition stating that the x[i] are independent variables for the purposes of this differentiation (hence the KroneckerDelta on the second line).

Edit: more discussion

And here is another cool result, completely symbolic:

Assuming[m ∈ Integers, D[sum[n], x[m], NonConstants -> x]]

$\left( \begin{array}{cc} \{ & \begin{array}{cc} m & m\geq 1 \\ 0 & \text{True} \\ \end{array} \\ \end{array} \right)-\left( \begin{array}{cc} \{ & \begin{array}{cc} m & m>2\land m\geq n+1 \\ n+1 & m=2\land n=1 \\ \end{array} \\ \end{array} \right)$

This isn't easy to absorb, but it works if you check it with specific examples by doing

condition = %;

Simplify[condition /. m -> 10]

$\begin{cases} 10 & n>9 \\ 0 & \text{True} \end{cases}$

In summary, it's worth pointing out that a lot of symbolic differentiation tasks can be achieved by using either NonConstants specifications in D or conversely using Constants specifications in Dt.

$\endgroup$
9
  • $\begingroup$ This is really helpful. Thank you very much. $\endgroup$
    – Wizard
    Dec 22, 2012 at 17:03
  • $\begingroup$ It might be worth mentioning that when doing this with more than one variable (say $x$ and $y$), it is necessary to have them Sorted in the NonConstants rule for the UpValue of the variables, otherwise it won't find a match when trying to evaluate D (and leave it unevaluated). $\endgroup$ Jun 17, 2015 at 7:44
  • $\begingroup$ sorry if this a super newbie question, but why does it say $1-n$ for...true? :/ What does that condition even mean? $\endgroup$ Aug 7, 2015 at 19:58
  • $\begingroup$ @Pinocchio True is the entry that humans would call "otherwise" - it's the default alternative if none of the above holds. $\endgroup$
    – Jens
    Aug 7, 2015 at 20:05
  • $\begingroup$ @Jens I see what true means now (weird, the programmer could have just said otherwise in a print statement...). But, how is the derivative wrt x[2] be 1 - n for n < 1? for n<1 the sum doesn't even exist...so wouldn't technically it be the derivative of a non-existent sum (so zero), so the derivative of zero is zero? Or am I completely off? $\endgroup$ Aug 7, 2015 at 20:10
23
$\begingroup$

I did some computation of formal derivatives a while back which might be of interest in this context (though keep in mind that this is anything but bullet proof! it does work for the cases I bothered to check though).

Clear[a]; Format[a[k_]] = Subscript[a, k]

Let us say we have an objective function which is formally a function of the vector a[i]

Q = Sum[Log[Sum[a[r] Subscript[B, r][Subscript[x, i]], {r, 1, p}]/
    Sum[a[r] , {r, 1, p}]], {i, 1, n}]

Mathematica graphics

Let us define a couple of rules for formal differentiation as follows

Clear[d];
d[Log[x_], a[k_]] := 1/x d[x, a[k]]
d[Sum[x_, y__], a[k_]] := Sum[d[x, a[k]], y]
d[ a[k_] b_., a[k_]] := b /; FreeQ[b, a]
d[ a[q_] b_., a[k_]] := b Subscript[δ, k, q] /; FreeQ[b, a]
d[ c_  b_, a[k_]] := d[c, a[k]] b + d[b, a[k]] c
d[ b_ +  c_, a[k_]] := d[c, a[k]] + d[b, a[k]]
d[Subscript[δ, r_, q_], a[k_]] := 0
d[x_, a[k_]] := 0 /; FreeQ[x, a]
 d[G_^n_, a[k_]] := n G^(n - 1) d[G , a[k]] /; ! FreeQ[G, a]
 d[Exp[G_], a[q_]] := Exp[G] d[G , a[q]] /; ! FreeQ[G, a]

Unprotect[Sum]; Attributes[Sum] = {ReadProtected};Protect[Sum];

And a rule to deal with Kroneckers

ds = {Sum[a_ + b_, {s_, 1, p_}] :> Sum[a, {s, 1, p}] + Sum[b, {s, 1, p}],
      Sum[ y_ Subscript[δ, r_, s_], {s_, 1, p_}] :> (y /. s -> r),
  Sum[ y_ Subscript[δ, s_, r_], {s_, 1, p_}] :> (y /. s -> r),
  Sum[ Subscript[δ, s_, r_], {r_, 1, p_}] :> 1,
  Sum[δ[i_, k_] δ[j_, k_] y_. , {k_, n_}] -> δ[i, j] (y /. k -> i),
  Sum[a_ b_, {r_, 1, p_}] :> a Sum[b, {r, 1, p}] /; NumberQ[a],
  Sum[a__, {r_, 1, p_}] :>  Sum[Simplify[a], {r, 1, p}] }

Then, for instance, the gradient of Q with respect to one of the a[k] reads

grad = d[Q, a[k]]  /. ds // Simplify;

Mathematica graphics

Similarly the tensor of second derivatives w.r.t. a[k] and a[s] is given by

hess = d[d[Q, a[k]], a[s]] /. ds // Simplify

Mathematica graphics

As a less trivial example let us consider the 4th order derivatives of Q

 d[d[d[d[Q, a[k]], a[s]], a[m]], a[t]]; /. ds // Simplify

Mathematica graphics

For the problem at hand we check easily that

 Q = Sum[r a[r] , {r, 1, p}];

 grad = d[Q, a[k]] // Simplify;
 grad //. ds

returns k as it should

EDIT

This process can be made a bit more general, say, on this Objective function

  Q = 1/2 Sum[(Sum[a[r] Subscript[B, r, i][a[q]], {r, 1, p}] - 
      Subscript[y, i])^2, {i, 1, n}]

Mathematica graphics

which depends non linearly on a[k] via B.

All we need is to add a new rule for d

d[H_[a[q_]], 
  a[k_]] := (D[H[x] , x] /. x -> a[k] ) Subscript[δ, k, q]

Now we readily have

grad = d[Q, a[k]] // Simplify;
hess = d[d[Q, a[k]], a[s]];

grad //. ds

Mathematica graphics

hess /. ds // Simplify

Mathematica graphics

As a other example, let us look at a parametrized entropy distance,

 Q = -Sum[(Sum[a[r] Subscript[B, r, i], {r, 1, p}]/
  Subscript[y, i]) Log[(Sum[a[r] Subscript[B, r, i], {r, 1, p}]/
   Subscript[y, i])], {i, 1, n}]

Mathematica graphics

we can compute its Hessian while mapping twice the sum rule

 Map[# /. ds &, d[d[Q, a[k]], a[s]] /. ds]

Mathematica graphics

As a final example, consider a Poisson likelihood

 Q = Sum[Log[Exp[-a[k]] a[k]^Subscript[y, k]/Subscript[y, k]!], {k, 1, n}]

Mathematica graphics

so that

 grad = d[Q, a[k]] // Simplify

Mathematica graphics

and

  hess =d[d[Q, a[k]], a[s]]  /. ds // Simplify

Mathematica graphics

Of course these algebraic rules are not bullet proof but illustrate nicely the way mathematica handles new grammar.

$\endgroup$
4
  • $\begingroup$ @Nasser have you seen this? $\endgroup$
    – Mr.Wizard
    Dec 15, 2012 at 19:51
  • $\begingroup$ unfortunately, i can not replicate these results in Mathematica 10.2. I would be appreciative if someone could try to reproduce this and/or suggest edits. $\endgroup$
    – Eric Brown
    Sep 11, 2015 at 1:53
  • $\begingroup$ I also cannot replicate these results using Mathematica 11 $\endgroup$
    – MaPo
    Jan 26, 2017 at 15:01
  • 1
    $\begingroup$ I have added one rule to solve the pb on the last two example. It now works for Mathematica 10.3. $\endgroup$
    – chris
    Jan 26, 2017 at 19:18
9
$\begingroup$

Starting in M11.1, this works:

sum[n_] = Sum[i x[i],{i,1,n}];

D[sum[n],x[2]] //InputForm

Piecewise[{{2, n >= 2}}, 0]

$\endgroup$
4
  • $\begingroup$ I've got M11, and I still get a result of 0. $\endgroup$
    – clr66
    Jul 23, 2017 at 1:27
  • $\begingroup$ Works for me in Mathematica 11.1.1 on MacOS Sierra. $\endgroup$
    – Wizard
    Jul 24, 2017 at 15:13
  • $\begingroup$ @clr66 I should have said starting in M11.1. $\endgroup$
    – Carl Woll
    Jul 24, 2017 at 15:44
  • $\begingroup$ Finally managed to upgrade to M11.1.1 and attempted the following: Assuming[{1<=j<=n,Element[j,Integers]},D[Sum[i f[i],{i,1,n}],f[j]]] (* j *) So far, so good. However, I also get the following: Assuming[{1<=j<=n,Element[j,Integers]},D[Sum[i g[f[i]],{i,1,n}],f[j]]] (* Sum[i*KroneckerDelta[i, j]*Derivative[1][g][f[i]], {i, 1, n}] *) This answer is technically correct, although it would be nice to get a clean result of j g'[f[j]] Is there a way to get the KroneckerDelta to return this result? $\endgroup$
    – clr66
    Aug 2, 2017 at 19:34
6
$\begingroup$

One solution might be ...

Method 1.

Define some variables:

x = Table[Unique[], {5}];

Form the inner product and differentiate:

D[Inner[Times, x, Range@Length@x], x[[2]]]

2

Or if you prefer it in a functional form:

sum[n_] := Inner[Times, x[[1 ;; n]], Range@n] /; ( Length@x >= n)

D[sum[4], x[[3]]]

3

Method 2.

You could take a different approach, but you need to be aware that it leaks variables of the form {x1,x2,x3,...} out into the general context:

sum[n_] := Inner[Times, Symbol["x" <> ToString@#] & /@ Range@n, Range@n] 

sum[5]

x1 + 2 x2 + 3 x3 + 4 x4 + 5 x5

D[sum3[4], x3]

3

$\endgroup$
1
  • $\begingroup$ This is exactly what I was trying to avoid. The exact amount of variables should not have to be specified. $\endgroup$
    – Wizard
    Dec 22, 2012 at 17:04
4
$\begingroup$

I like image_doctor's solution better, but how about using Array and looking for the position using that index each time? Like this:

xx = Array[x, 10, 1];
sum[n_] := Times[List @@ xx , Range[10]]

sum[n]
(* {x[1], 2 x[2], 3 x[3], 4 x[4], 5 x[5], 6 x[6], 7 x[7], 8 x[8], 9 x[9], 10 x[10]} *)

Now

sum[n_] := Times[List @@ xx^4, Range[10]]
D[sum[n], xx[[5]]][[5]]
(*  20 x[5]^3 *)

and

sum[n_] := Times[List @@ xx, Range[10]]
D[sum[n], xx[[2]]][[2]]

(* 2 *)

It is kinda clumsy though. The problem, of course, is that one can't treat

enter image description here

as a single variable as we do on paper. P.S., I tried to see if one can do this in Maple and could not do it directly as you wanted. Had to do a hack as above. (But I do not know Maple much, though.)

$\endgroup$
1
  • 1
    $\begingroup$ Nasser, if it matters to you, your "gravatar" is changing along with your I.P. address. You can make it a fixed one by entering an email address in your profile. This email is only visible to moderators and furthermore it doesn't need to be a real one anyway. Also see: mathematica.stackexchange.com/q/13525/121 $\endgroup$
    – Mr.Wizard
    Dec 15, 2012 at 19:42
3
$\begingroup$

A possible solution is to use the fact that Mathematica can easily take the derivative of an actual sum, but has problems with the symbolic one. In order to take the derivative on j-th term of a sum, we extract from the sum few terms centered around j. The number of extracted terms is equal to 2*dj+1. There is one drawback of this solution that you can always differentiate on j-th term. This method works with subscripted variables as well.

s1 = Sum[p[k]*a[k + 1] + p[k + 1]*a[k], {k, 1, nn}];
derivSum[s0_, xj_, dj_] := Block[{k, j}, D[Sum[s0[[1]], {k, j - dj, j + dj}], xj]];
derivSum[s1, p[j], 4]
(* a[-1+j]+a[1+j] *)
$\endgroup$
2
$\begingroup$
$Version

(*  "11.1.1 for Mac OS X x86 (64-bit) (April 18, 2017)"  *)

sum[n_] = Sum[i x[i], {i, 1, n}];

Assuming[Element[{n, m}, Integers] && n >= m >= 1, D[sum[n], x[m]]]

(*  m  *)

Assuming[Element[{n, m}, Integers] && n >= 1 && m >= 1, 
 D[sum[n], x[m]] // Simplify]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.