4
$\begingroup$

I need to take the derivative of a function that have a numerical integration on it. The variable in which the integration will be taken is not the same as the one in which the derivative will be taken, so I can take the derivative before integrating the expression. I have tried the following:

nfun[x1_?NumericQ, x2_?NumericQ] := NIntegrate[Cos[x1^x/x2], {x, 2, 3}]
tvar = {x1 -> 0.1, x2 -> 0.3};    
D[nfun[x1, x2], x1] /. tvar

And it worked pretty fine. But my real expression has multiple variables and multiple numerical integrations, so I would like to take a list of arguments as input. I also have to take one derivative for each variable. So I tried the following:

nfun1[arg : {_?NumericQ ..}] := NIntegrate[Cos[#1^x/#2], {x, 2, 3}] & @@ arg

But when I try:

D[nfun1[x1, x2], x1] /. tvar

It doesn't work...

I have tried what is proposed in here: Derivative after numerical Integration (2nd answer), but I couldn't get it to work Do you have any sugestions?

I hope I could express myself correctly


Edit: As Mark and Myke showed, the syntax in the second try is wrong, it should be:

D[nfun1[{x1, x2}], x1] /. tvar

But still not working :(

$\endgroup$
3
  • $\begingroup$ without evaluating your stuff one things that stands out is that your second definition is a one argument function that has as its arguments a list. Yet you are trying to take the derivative of a two argument function where the arguments are a sequence $\endgroup$ Commented Dec 24, 2015 at 1:47
  • $\begingroup$ Try this instead: nfun1[arg : _?NumericQ ..] := NIntegrate[Cos[#1^x/#2], {x, 2, 3}] &@arg; D[nfun1[x1, x2], x1] /. tvar. Does that work? $\endgroup$
    – march
    Commented Dec 24, 2015 at 2:21
  • $\begingroup$ I used Inactive[NIntegrate] , it worked very well :) $\endgroup$
    – Fábio
    Commented Jan 11, 2016 at 22:46

2 Answers 2

4
$\begingroup$

First note that your first solution generates a spurious complex part.

nfun[x1_?NumericQ, x2_?NumericQ] := NIntegrate[Cos[x1^x/x2], {x, 2, 3}]
tvar = {x1 -> 0.1, x2 -> 0.3};
D[nfun[x1, x2], x1] /. tvar // RepeatedTiming
(*  {0.17, -0.00527135 - 9.7792*10^-9 I}  *)

We will also see that it's rather slow to differentiate, too. This is because Mathematica is computing the derivative numerically, which causes the integral to be computed many times. This integral has a symbolic derivative, which can be used to speed up the calculation of the derivative.

Using Ifis an easy way to get the protection of NumericQ but still be able to differentiate the expression. (Update: I did have ConditionalExpression, which for some reason was working in my original session, but shouldn't have. It doesn't hold its arguments.)

nfun1[arg_List] := If[arg ∈ Reals, NIntegrate[Cos[#1^x/#2], {x, 2, 3}]] & @@ arg

There is no spurious imaginary part to the derivative and it is almost 50 times faster, too. (The Reals can be replaced with the Complexes.)

nfun1[{x1, x2}]
D[%, x1] /. tvar // RepeatedTiming
(*
  If[(x1 | x2) ∈ Reals, NIntegrate[Cos[x1^x/x2], {x, 2, 3}]]
  {0.0045, -0.00527132}
*)

Update: I had a function NEval was considerably faster than the ConditionalExpression "solution." The arguments to NEval consisted an expression expr to be evaluated when the rest of the arguments are numeric. There is also a special derivative rule, so that differentiating NEval simply differentiates expr. While one is naturally initially fond of all one's creations, there seems little need for it in this case. See edit history, if curious.

$\endgroup$
4
  • $\begingroup$ Thank you very much, Michael... I dont know what I am doing wrong, but when I try your code, it gives me the message: "The integrand Cos[x1^x/x2] has evaluated to non-numerical values for \ all sampling points in the region with boundaries {{2,3}}." $\endgroup$
    – Fábio
    Commented Dec 24, 2015 at 13:03
  • $\begingroup$ @Fábio Thanks for letting me know. I wasn't getting that before, but in a new session I do. I must have changed something. The update seems to work well, and actually it's just as fast as the cumbersome NEval solution, which I removed. (Let me know if you want it back and I'll put it in.) $\endgroup$
    – Michael E2
    Commented Dec 24, 2015 at 14:39
  • $\begingroup$ Thank you, Michael, it worked like a charm. It REALLY helped me. Anyway, any clue of why nfun1[arg : {_?NumericQ ..}] doesn't work, while nfun[x1_?NumericQ, x2_?NumericQ] does? $\endgroup$
    – Fábio
    Commented Dec 24, 2015 at 15:14
  • $\begingroup$ I don't know exactly. You can look at Derivative[{1, 0}][nfun1][List[0.1`, 0.3`]] // Trace and Derivative[1, 0][nfun][0.1`, 0.3`] // Trace and see that it just doesn't seem to try to do the numeric derivative when the argument to Derivative is a List (the case Derivative[{1, 0}]). I don't see a reason why it shouldn't work. Report it to Wolfram support and see what they say. -- BTW, the numeric derivative is both slower and less accurate, so in a way you're lucky it didn't work. :) $\endgroup$
    – Michael E2
    Commented Dec 24, 2015 at 16:38
4
$\begingroup$

The problem with your second expression is two-fold. First, to match your syntax, you need to evaluate

D[nfun1[{x1, x2}], x1] /. tvar

instead. Second, that still doesn't work, for this reason. With your expression,

D[nfun1[{x1, x2}], x1]

evaluates to

Derivative[{1,0}][nfun1][{x1,x2}]

and

D[nfun1[{x1, x2}], x1] /. tvar
(* Derivative[{1,0}][nfun1][{0.1, 0.3}] *)

which I think suggests what's going wrong, although I haven't exactly tracked down why that doesn't work.

In any case, this seems to work:

Clear[nfun1]
nfun1[arg : _?NumericQ ..] := NIntegrate[Cos[#1^x/#2], {x, 2, 3}] &@arg
tvar = {x1 -> 0.1, x2 -> 0.3};
D[nfun1[x1, x2], x1]
% /. tvar
(* Derivative[1,0][nfun1][0.1, 0.3] *)
(* -0.00527135-9.7792*10^-9 I *)
$\endgroup$
1
  • $\begingroup$ Thank you very much for your attention, march... I missed the syntax thing, but i had already tried that way... Your way works fine, and I may use that, but I would like my function to take a list as argument... $\endgroup$
    – Fábio
    Commented Dec 24, 2015 at 3:03

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.