Group Abstract Group Abstract

Message Boards Message Boards

0
|
3.8K Views
|
7 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Same code with involving integer takes longer time

Posted 2 years ago

Hello,

Np = 500;
a = 1;
b = 4.0;
h = (b - a)/Np;
x0 = a;
y[0] = 1;
Y = {{x0, y[0]}};
f[x_, y_] = -y*(x + 1) - Cos[x];
For[m = 0, m <= Np - 1, m++,
  xm = a + m*h;
  y[m + 1] = y[m] + h*f[xm, y[m]];
  AppendTo[Y, {xm + h, y[m + 1]}];
  ];
g2 = ListLinePlot[Y, PlotStyle -> Green, PlotRange -> All]

enter image description here

Np = 500;
a = 1;
b = 4;
h = (b - a)/Np;
x0 = a;
y[0] = 1;
Y = {{x0, y[0]}};
f[x_, y_] = -y*(x + 1) - Cos[x];
For[m = 0, m <= Np - 1, m++,
  xm = a + m*h;
  y[m + 1] = y[m] + h*f[xm, y[m]];
  AppendTo[Y, {xm + h, y[m + 1]}];
  ];
g2 = ListLinePlot[Y, PlotStyle -> Green, PlotRange -> All]

enter image description here

So, the only difference is in b, in that in the first case b=4.0, while in the second case b=4. In the first case the code runs quickly and displays the result, while in the second case, the code runs endlessly and does not display the result.

Can someone explain how exactly that .0 influences the running of the code so much?

Thank you.

POSTED BY: Cornel B.
7 Replies

Re proposed alternatives, Join, Append and the Flatten (if used in the loop) will all scale like AppendTo. For the example at hand, Table is the natural choice.

POSTED BY: Daniel Lichtblau
Posted 2 years ago

So, then that it is better to use whenever possible real numbers (with .0) than integer numbers, right?

I wouldn't say "whenever possible". I'd say it's better if you're going to use Plot or other plotting functions or if performance is important.

Well, then what should I use instead of AppendTo and For loop? Which equivalent functions are better to use?

Sometimes (at least for me) it's a matter of experimentation, and sometimes I'm surprised by what ends up being fastest. Maybe someone with deeper knowledge of the implementation details and performance issues could be more definitive, but instead of For, I would generally try

  • Map
  • Nest/NestList
  • NestWhile/NestWhileList
  • Fold/FoldList
  • FoldWhile/FoldWhileList
  • FoldPair/FoldPairList

Instead of AppendTo

  • list = Join[list, {newitem}]
  • list = Flatten[{list, newitem}]
  • list = Append[list, newitem]
  • list[[newindex]] = newitem

For that last one, just allocate the size you need for the list first, and then update by index rather than by appending. Sometimes special data structures (http://reference.wolfram.com/language/guide/DataStructures.html) work best for specific circumstances. I tend to just use the simplest thing (probably Map over a List is the most frequent followed by Nest) until I run into performance issues when scaling, at which point I try whatever seems promising depending on the expressions I'm working with. And sometimes For does actually make things faster. Maybe I should go look for a Wolfram training video on optimization.

POSTED BY: Eric Rimbey
Posted 2 years ago

A number expression like 4 is interpreted as an integer. Integers and fractions are not estimated, but are held as exact values, i.e. they have infinite precision. As long as all arithmetic operations being performed use integers or rationals, the arithmetic will be performed exactly, maintaining infinite precision.

Why does that matter? Well, set your Np lower (say 10) to reduce the time spent and then after the computation terminates, inspect Y. You'll see that it is a very complicated expression. This means time must be spent during the plot coming up with estimated values. Now, if you make any of your terms have finite precision, you'll see that Y is much simpler (it'll be all Real values).

If any part of an arithmetic expression has finite precision, then then result will too. How do you force finite precision? You can use N, or you could just change any of your terms to be Real instead of Integer. That's what the decimal point does. 4 is an Integer, but 4. is a Real. You could do this with a or b or pretty much anywhere else.

In general, finite precision calculations will go faster, because the representation is simpler and there are many algorithmic optimizations that are applied.

Side note, AppendTo is relatively inefficient and For loops can be as well, because they don't take advantage of the built-in optimizations for doing computations with lists. It might not matter in this example.

POSTED BY: Eric Rimbey
Posted 2 years ago
  1. So, then that it is better to use whenever possible real numbers (with .0) than integer numbers, right?

  2. Well, then what should I use instead of AppendTo and For loop? Which equivalent functions are better to use?

POSTED BY: Cornel B.
Posted 2 years ago
  1. Yes. It's very useful to know the precision of the data that you're using and how to alter that precision. Regular Wolfram users immediately recognize the difference between 4 and 4.0.

  2. In general, you will be far better off for this kind of work using functional programming than doing Fortran-style iteration with indexes. You may never need to build a table of results yourself -- simply pass your functionally-defined function to the built-in functions and let them handle the iteration for you. Functional programming is covered in online intro courses like Wolfram Language Basics: a 14-day hour-a-day presentation with homework. Live presentations of this material are available regularly at WolframU; one just completed last week. An archived version of the course lectures is available in https://www.wolfram.com/wolfram-u/wolfram-language-basics/ .

There is a 30-minute presentation solely on functional programming at https://www.wolfram.com/wolfram-u/catalog/dev001/ . I haven't gone through that presentation, but I'm sure it's high-quality if Wolfram has published it.

If you watch any of those videos, make sure to have a Wolfram Notebook open and work through examples. Pause is your friend. If you're on a Mac and a have a tool like TextSniper, you can pull live code straight off of the [paused] video presentation and paste it into a Notebook. I'm sure there are similar capture tools for other environments. Live courses provide Notebooks of the presentation material up front; snipes of code fragments are generally not necessary.

Your questions are very good. Wolfram is a well-designed environment for coding a vast variety of problems, and for coding them efficiently.

POSTED BY: Phil Earnhardt
Posted 2 years ago

Eric, the Notebook with a value of 4 is not failing in the loop. The loop completes; it's failing inside the ListLinePlot[] function. If you put a Print[] call immediately before the ListLinePlot, you'll see that the loop has completed executing. There's something funky about the way you're creating Y. I don't know how to run the debugger.

POSTED BY: Updating Name
Posted 2 years ago

Agreed. That’s why I mentioned the looping stuff as a side note.

POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard