0
$\begingroup$

I have a task to solve some system of equations with NSolve and print graph of it, depends on parameters.

Something like this (maybe it is not a good example and does not always have a solution, but it just for example).

x+y==a
x-y==b

and I need to plot 3D graph of y(a,b) and x(a,b). Let's assume that for any a and b my system has a solution. My Real system is very complicated and has some complicated functions which are calculated through NIntegrate[].

I managed to find a solution and with Table[] function generate array of all possible values in the form

{
{{a1,b1},{{x->x1,y->y1}}},
{{a2,b2},{{x->x2,y->y2}}}
...
}

or with numbers

{
{{0.1,0.1},{{x->1.5,y->2.5}}},
{{0.1,0.2},{{x->1.6,y->2.6}}}
...
}

Let's call it "myInitialSolution" It took just 10 seconds for me.

Later I tried to convert it to another format, which is good for Interpolation function.

I converted it with Table function like this

xArraySolution := Table[{myInitialSolution[[i]][[1]], 
      x /. myInitialSolution[[i]][[2]][[1]][[1]]]]}, {i, 1, maxPoints*maxPoints, 1}];

and the same for y. maxPoints - is how many point for x I have in initial solution. It gave me array like this

{
{{a1,b1},x1},
{{a2,b2},x2}
...
}

or with numbers like this

{
{{0.1,0.1},1.5},
{{0.1,0.2},1.6}
...
}

It took already 20 minutes! I do not understand why just to convert array it took so long? What I did wrong?

Later to be able to plot a smooth graph I applied Interpolation function on it like this

xSolution[a, b] := Interpolation[xArraySolution][a, b];

and after this just to calculate one point like this

xSolution[0.15, 0.15]

which returns me for example

1.55

it took 10 minutes just to calculate 1 number!!!

My questions are

  • why it so slow may be I am doing something wrong? Because I got all numbers in 10 seconds, and later just to rearrange them it took 20 minutes.

  • Looks like each time when I use my final function xSolution[a,b] Mathematica tries to solve system from the beginning. By I already have all numbers in memory. Why it is doing so?

  • Can I just copy somehow data from one array to another and make another array independent copy? Just to avoid running NSolve each time, when I need to calculate something. In my example I would like to copy data from myInitialSolution to xArraySolution completely independently. In other words it would be good to have xArraySolution as completely new in memory array. Of course if I make a copy and paste from keyboard it will work, but it is not a good solution :)

$\endgroup$
1
  • $\begingroup$ Yep, closer inspection does seem to suggest that improper use of SetDelayed all over the place is causing the slowdown. However, I do not see the code which makes the xArraySolution be generated so slowly. I can only make a wild guess, that you use SetDelayed in the definition of myInitialSolution as well, so every time you're running xArraySolution, you're solving the equations all over again. $\endgroup$
    – LLlAMnYP
    Jun 1, 2015 at 15:30

1 Answer 1

0
$\begingroup$

Very relevant link: What is the difference between := and =

EDIT The most important question and the answer to it:

Looks like each time when I use my final function xSolution[a,b] Mathematica tries to solve system from the beginning. By I already have all numbers in memory. Why it is doing so?

It is doing so, because you are using SetDelayed - := instead of Set - =.

myInitialSolution := Table[{vals, NSolve[equations, {x, y}], {vals, gridofabvalues}]

means that every time you call myInitialSolution you solve the system again.

myInitialSolution = Table[{vals, NSolve[equations, {x, y}], {vals, gridofabvalues}]

means you calculate the solution once and write the result to myInitialSolution. Every subsequent call to myInitialSolution just pulls the numbers from memory.

Remaining part of answer

I would recommend avoiding iterative constructs and doing something like this:

(* define the grid of a-b values *)
grid = Flatten[Table[{a, b}, {a, .1, 5, .1}, {b, .1, 5, .1}], 1]

(* get the desired form directly *)
xArraySolution = 
    Map[{#, x /. First@NSolve[x + y == #[[1]] && x - y == #[[2]], {x, y}]} &, grid]

(* interpolate the data *)
f = Interpolation[xArraySolution]

(* plot the result *)
Plot3D[f[a, b], {a, .1, 5}, {b, .1, 5}]

Result

However I also have a sneaking suspicion, that it is the SetDelayed in your definition of xArraySolution that is slowing stuff down. In fact, your definition of xSolution is also quite nasty. Because of the SetDelayed, when you define xSolution the way you do, the following happens: Mathematica calculates xArraySolution from scratch (because it is defined with SetDelayed, finds a complete interpolation of for all given values of a and b, gets an InterpolatingFunction and applies that to [a,b]. So it is as slow, as constructing your table, which, it seems, is the bottleneck in this code. Moreover, the function xSolution does not calculate the interpolation once and then evaluates it for different values of [a,b], it recalculates the interpolation every frickin' time it wants to get an answer for a new pair of [a,b]. So it would be impossible to plot.

Let's start afresh and get myInitialSolution in the form you have.

Again:

grid = Flatten[Table[{a, b}, {a, .1, 5, .1}, {b, .1, 5, .1}], 1]
myInitialSolution = 
    Map[{#, NSolve[x + y == #[[1]] && x - y == #[[2]], {x, y}]} &, grid]

{ {{0.1, 0.1}, {{x -> 0.1, y -> 0.}}}, {{0.1, 0.2}, {{x -> 0.15, y -> -0.05}}}, {{0.1, 0.3}, {{x -> 0.2, y -> -0.1}} ... }

Now we can do a simple transformation with Map again:

xArraySolution = 
    Map[{First@#, x /. First@Last@#} &, myInitialSolution]

Which returns:

{{{0.1, 0.1}, 0.1}, {{0.1, 0.2}, 0.15}, {{0.1, 0.3}, 0.2}, {{0.1, 0.4}, 0.25}, {{0.1, 0.5}, 0.3}...}

Then

xSolution = Interpolation[xArraySolution]
Plot3D[xSolution[a, b], {a, .1, 5}, {b, .1, 5}]

Which gives the same plot as above.

A very quick test shows, that if in the code above I replace myInitialSolution = ... with myInitialSolution := ... even your super-simple linear example equations are now evaluating till the end of time. More precisely, the evaluation of defining myInitialSolution is nearly instantaneous now, however when it is used elsewhere, specifically in converting it to the suitable form for Interpolation everything just dies.

$\endgroup$
1
  • $\begingroup$ Yes, Problem was with SetDelayed. I found it by myself searching google, but you give me much more usefull information. Thank you very much. $\endgroup$
    – Zlelik
    Jun 1, 2015 at 20:51

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.