3
$\begingroup$

I have a large simulation (1500 lines of code in different sections) and I would like to run the file using different combinations of input parameters without manually changing the parameters.

Say my simulation is a function of alpha, beta and gamma and I want to iterate all three variables from 1 to 10. Then with only little code that fits in one cell, the iteration could be easily done using

Do[someFunction[alpha,beta,gamma],{alpha,1,10},{beta,1,10},{gamma,1,10}]

This evaluates the function for all 1000 combinations of input parameters. However, I do not see how I can use Do for an entire Notebook, is there a way without merging it all into one cell and thereby losing the Notebook's structure?

An approach I have now tried for days is to open the Notebook from another Notebook and writing the parameters created by Do within that notebook into the main Notebook using NotebookWrite and then evaluating it using SelectionMove[nb,All,Notebook] and SelectionEvaluate[nb] (within that Do-Loop). However I encountered problems:

a) I think the problem might be that I need the other Notebook to write a list of value assignments such as HoldForm[{alpha=5,beta=5...} into the main Notebook, and NotebookWrite does not permit a list of assignments as its argument to be exported; converting it to Strings seems to be difficult to combine with the Do-Iteration. I tried Öskå's workaround solution but it didn't work for my Problem.

b) A main problem with evaluating it from another workbook seems to be that the Do-Iteration does not seem to wait until the rest of the Do-commands are evaluated. Means: It keeps entering new parameters before the evaluation of the main Notebook has finished (but I might be wrong here?).

I have tried many different ways to do it but I didn't find a solution, I'd really appreciate your help. Maybe there's a better and completely different solution or even a solution within the main Notebook.

Edit: More information on the problem

@Jens @Jagra Thank you big time for replying this fast.

My code would surely fit within a Do-Loop if it wasn't just this much code (with a structure). A Do-Loop must fit in one single cell; it may reference to values and functions defined outside the ´Do´-Command, but every line of code that is supposed be evaluated during the Loop must also be mentioned within the Do (at least by some symbol that represents a sequence of commands).

I have approx. 1500 lines of code and if possible, I don't want to name all of them in the Do even if it would work this way. Merging everything into one cell to put the Do around the entire NB is not my preferred option because my (many) section titles then get messy if they are marked as input.

My code is basically just transformations of simulated numbers and many different plots of the results:

μ=10;
ϕ=5;
θ=5;
κ=0.1;
γ=0.3;
iterationcount=20000;
lineardepreciation=10;
cashflow1=RandomVariate[NormalDistribution[μ,ϕ],iterationcount];
cashflow2=cashflow1(1+δ)+RandomVariate[NormalDistribution[0,θ],iterationcount];
cashflow3=cashflow2(1+δ)+RandomVariate[NormalDistribution[0,θ],iterationcount];
npv=-100+cashflow1/(1+κ)+cashflow2/(1+κ)^2+cashflow3/(1+κ)^3
earnings1=cashflow1-lineardepreciation;
earnings2=cashflow2-lineardepreciation;
earnings3=cashflow3-lineardepreciation;
PVE1=earnings1/(1+γ);
PVE2=earnings1/(1+γ)+earnings2/(1+γ)^2;
PVE3=earnings1/(1+γ)+earnings2/(1+γ)^2+earnings3/(1+γ)^3;
earningsPVmatrix=Transpose [{npv,PVE1,PVE2,PVE3}];

Hundreds of lines of code similar to this, altering these distributions, all depending on μ,ϕ,0,κ,γ and so on. Based on the results, 40 different plots are created and exported. This would surely fit within the Do, but then I lose my structure by different levels of Styles (title, section, subsection..which structure the problem). I now want to run the file with different combinations of parameters for my input variables μ,ϕ,0,κ,γ etc.

Should I fit all of this in one cell by referencing all the 1500 commands within the Do or is there another way?

$\endgroup$
  • $\begingroup$ Could you explain why you can't modularize the code of the other notebook and put it into the current notebook doing the Do loop evaluation? That's the sane way to proceed under any normal circumstances. You could also look up Import. $\endgroup$ – Jens Jul 24 '16 at 16:06
  • $\begingroup$ Your Do[] command can be replaced by a Table[], which is the preferred method. $\endgroup$ – Feyre Jul 24 '16 at 16:07
  • $\begingroup$ @Jens right now there's only one large Notebook. I don't want to put everything into one cell in order not to lose the notebook's structure. If I tell the ´Do´ to evaluate all the Notebook's commands, I would have to put 1500 commands into it... did I get you right? $\endgroup$ – andreas Jul 24 '16 at 16:43
  • 2
    $\begingroup$ Hard to know without more information, but this sounds like a job for a Package $\endgroup$ – Jagra Jul 24 '16 at 17:32
  • 1
    $\begingroup$ related mathematica.stackexchange.com/q/66159/2079 $\endgroup$ – george2079 Jul 24 '16 at 22:34
5
$\begingroup$

Indeed, the existing notebook can be called repeatedly from another notebook, which iterates over the desired parameters, passing them to the existing notebook, which then passes the answers back to the calling notebook, which records them. For instance, begin the calling notebook with

Dynamic[{loop, linked`vdtdz}]
distab = {}; Dynamic[distab // TableForm]
Dynamic[return]

which displays a local loop variable, a variable vdtdz (in the context linked shared between the two notebooks; otherwise, the two notebooks have different contexts to avoid inadvertent cross-talk), the array of returned answers distab, and graphics from the called notebook (which change with each call and can be used to examine on the fly whether the results in the called notebook are reasonable).

Next, repeatedly call the notebook with variable vdtdz and record returned answers maxai.

Do[linked`vdtdz = 0.1 loop; linked`$callingNotebook = EvaluationNotebook[];
return = NotebookEvaluate[$UserDocumentsDirectory <> 
    "/Mathematica/PSTD_Solve.nb"];
distab = Append[distab, linked`maxai], {loop, 8, 10}]

The called notebook contains as its first line,

linked = ValueQ[linked`$callingNotebook]; Clear[linked`$callingNotebook]

which determines and records whether the called notebook has actually been called or is running independently. Later, the called notebook incorporates the passed variable,

vdtdz = If[linked, linked`vdtdz, 1.0]

if it was, in fact, called. Otherwise, it runs with a default value, here 1.0. (Any number of variables can be passed in this way.) The final line in the called notebook is

If[linked, linked`maxai = kout[[1, 4]]; Grid[{{grow3D, growContour}}]]

which passes a single numerical value to the calling program (if it was, in fact, called) and also passes graphics that is displayed as return in the calling notebook. (Any amount of information can be returned by either of these two ways.)

In summary, the called notebook can run independently or it can be called repeatedly by the calling notebook. The called notebook also can record information to files that it writes to disk.

Below is a screen shot of the final appearance of the calling notebook. The array of three elements is the set of desired answers from three calls to the called notebook, and the two graphics below merely show that the called program is running properly (or not).

enter image description here

I routinely use the approach described here, and it seems broadly applicable.

$\endgroup$
  • $\begingroup$ @bbodfrey that's exactly it! just great... and it works with more than one variable by just stating Dynamic[{loop1, linked[Mu]}]` and Dynamic[{loop2, linked[Delta]}]` and changing the other corresponding parts in the two NBs. bbodfrey = hero! $\endgroup$ – andreas Jul 25 '16 at 15:02
  • $\begingroup$ @andreas Last year, I was confronted with exactly your problem and was able to develop a solution from parts of other answers, such as this. It was a pleasure to be able to share it with you. Thanks for accepting the answer. Best wishes. $\endgroup$ – bbgodfrey Jul 25 '16 at 15:10
  • $\begingroup$ @bbgodfrey Thanks for this solution. This is exactly what I needed. Although I don't need that last line in the called notebook, I was wondering what it really refers to. I don't see kout, grow3D nor growCounter anywhere else in the code. Could you please explain? Best $\endgroup$ – Karim Mar 13 '18 at 8:23
  • $\begingroup$ @Karim These three variables (a real number and two graphics) are items returned by the called notebook to the calling notebook. If you have no variables to return, you can delete the corresponding code entirely. Otherwise, replace those variables in the code by the names of the variables that you want to return. $\endgroup$ – bbgodfrey Mar 13 '18 at 14:55
  • $\begingroup$ @bbgodfrey Thanks! $\endgroup$ – Karim Mar 14 '18 at 8:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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