9

I have a (hopefully small) problem with some numerical integration algorithm, more specifically I want to integrate the imaginary part of a complex valued function, e.g. f[u_]:=Exp[-iuK] with $K\in\mathbb{R}$. As mentioned I am only interested in Im[f], in the example -Sin[u K].

Now if I integrate with Mathematica

NIntegrate[f, {s, Min[roots[[ 1 ]], roots[[ 2 ]]],
                Max[roots[[ 1 ]], roots[[ 2 ]]]}, AccuracyGoal->aGoal, 
                PrecisionGoal->pGoal, WorkingPrecision->wPrecision ];

I get two different results depending on f:

  1. if I use -Sin[u K], it returns somenumber
  2. if I use Im[f], it returns a list { somenumber } Those two have to be treated differently and that crashes my program. I have a few questions:

Why does Mathematica sometimes return lists, and sometimes values? How can I distinguish between a list and a value, i.e.

If xyz is a list then 
  do something 
else 
  do something else
end

Any other ideas how one could avoid these different return "types"? The manual and anything I found hasn't been useful so far.

Brett Champion
  • 20,779
  • 2
  • 64
  • 121
user13655
  • 377
  • 1
  • 8
  • 4
    I'm trying to understand why NIntegrate is returning a List in one case, and a simple value in another. So, what are you using for roots? – rcollyer Mar 01 '12 at 19:34
  • 1
    I cannot reproduce this behavior. E.g., Clear[f]; f[u_] := Exp[-I u]; NIntegrate[Im[f[s]], {s, 0, 1}] works just fine (returning a Real value). – whuber Mar 01 '12 at 21:04
  • NIntegrate will return a list when its argument is a list. Therefore I suggest you investigate under what circumstances your f is a list. With your example code, one way this could happen is if K is sometimes a list. – Andrew Moylan Mar 02 '12 at 06:34
  • The simple example I gave doesn't reproduce the error, that's true. Probably some input arguments of NIntegrate cause the behavior, however, I'll use one of the answers below. Thank you all! – user13655 Mar 02 '12 at 08:48

5 Answers5

17

Generally speaking, you can recognize a list because it'll have List as its Head. For example:

Head[{1,2,3}]

will return List.

For your example conditional where you want to change what you do based on the Head of the resulting expression, you can use Switch, such as in:

Switch[result,
       _List, what you want to do with a list,
       _, what you want to do otherwise]

A pattern of the form _List means "only match expressions with the head List. The next pattern, _, means "match an expression with any head". Mathematica stops in a Switch at the first match, so List will be preferred over "anything else".

sblom
  • 6,453
  • 3
  • 28
  • 45
  • 1
    I need to remember that syntax. I keep using Head[result]===List.... yours is much nicer. – tkott Mar 01 '12 at 21:06
11

It is useful to write functions that can handle expressions in several different forms.

Here is a function that will return 1 plus a numeric argument, or 1 plus the first element of a list, if it is given a list.

f[n_?NumericQ] := n + 1
f[{n_?NumericQ, ___}] := n + 1

This can also be written in one line using Alternatives:

f[n_?NumericQ | {n_?NumericQ, ___}] := n + 1

When using Alternatives the possibilities will be checked in the explicit order you give.
When using separate lines Mathematica attempts to intelligently order the rules by specificity.

Usage:

f[Pi]
1 + Pi
f[{1, 2, 3}]
2
f["bird"]
f["bird"]

You can use the same syntax for Replace rules if you do not want to create a function.

Pi /. n_?NumericQ | {n_?NumericQ, ___} :> n + 1

{1, 2, 3} /. n_?NumericQ | {n_?NumericQ, ___} :> n + 1
1 + Pi

2

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
10

How about putting the results in a list and then removing unneeded braces.?

a = 76.5
b = {4, 5, 12.3}
Flatten[{a}]
Flatten[{b}]

lists

That way you are always dealing with a list of values.


Or simply place braces around numbers (that are not already in a list):

If[NumericQ[x], x = {x}]
DavidC
  • 16,724
  • 1
  • 42
  • 94
7

Some functions are intermittent about whether they wrap their results in a list. I'm not sure about NIntegrate, but Reap (for example) certainly does. For purposes of discussion, let's define such a function:

g[x_] /; OddQ[x] := {10 x}
g[x_] := -x

g[1]

{10}

g[2]

-2

We can define h to automatically "unwrap" resulting lists like this:

h[x_] := g[x] /. {n_} :> n

h[1]

10

h[2]

-2

Table[h[x], {x, 0, 10}]

{0, 10, -2, 30, -4, 50, -6, 70, -8, 90, -10}

Also, ListQ can be used to distinguish lists from other value types:

ListQ[1]

False

ListQ[{1}]

True

WReach
  • 68,832
  • 4
  • 164
  • 269
2

Alright, I figured out my mistake - as Mathematica distinguishes between different bracket types, one shouldn't confuse () and {}, as I did in a part of my calculations. Sorry for the puzzlement.

user13655
  • 377
  • 1
  • 8