Debugging Hints

Revision as of 22:30, 8 July 2009 by Lchrisman (talk | contribs) (hyperlink to Memory Usage Dialog)


Suppose your model gives an error during evaluation, or doesn't give plausible results. How can you figure out the problem? Debugging software is a deep subject.

In some ways, Analytica makes this much easier than conventional programming languages: First, because you can see the value of each variable very easily, just by selecting its node and clicking the Result icon (or control-R). Second, the "no side-effects" property of Analytica -- meaning that you can see how it is computed simply by looking at its Definition -- makes understanding how it works much simpler than conventional procedural languages.

Nevertheless,there are cases where debugging can be a challenge. Here are some tips.

Break up a complicated variable into simpler ones

Suppose you are getting an evaluation error within a variable V, or simply suspect there's a problem in its definition. If the definition is complicated -- more than a one-line expression -- it's often useful to break it up by creating a separate variable for each subexpression. For example, suppose you suspect an error in

Variable V 
Definition: IF g_run_mode = 'Deterministic' OR H_use_stoch_or_deter[H_r_d_or_lbd='R&D'] = 'Deterministic'
            THEN Linearinterp(H_r_d_years, H_deterministic_tpi, time - H_acceleration, H_r_d_years)
            ELSE BEGIN
                VAR x := G_interpolate_dists( H_bounded_tpi_distri, H_r_d_years, Time, H_variability_in_int);
                Linearinterp(Time, x, Time - H_acceleration, Time)
            END
            * H_sensit_factor( H_impro_params) 

You can decompose V into V_decomp using intermediate variables in this way:

Variable V1 := g_run_mode = 'Deterministic' OR H_use_stoch_or_deter[H_r_d_or_lbd='R&D'] = 'Deterministic'
Variable V2 := LinearInterp(H_r_d_years, H_deterministic_tpi, time - H_acceleration, H_r_d_years)
Variable X := G_interpolate_dists( H_bounded_tpi_distri, H_r_d_years, Time, H_variability_in_int)
Variable V3 := Linearinterp(Time, x, Time - H_acceleration, Time)
Variable V4 := H_sensit_factor( H_impro_params)
Variable V_decomp := (IF V1 
            THEN V2
            ELSE V3) * V4

Note that Variable X replaces the local variable X in the original Definition with a global X, now used in V3.

You can now look at each intermediate variable and see if looks right, which should be much simpler than trying to decode the original definition.

When creating a model, the question often arises about how much to decompose a complex calculation into separate variables, or combine many variables into one. If you had created the model originally using this decomposed version, it might have been simpler to understand and debug in the first place. On the other hand, using more variables makes it harder to understand at the higher level. Plus, since Analytica usually stores the value of each variable after computing it, the decomposed version results in saving six instead of one results -- using more memory.

There is a way to avoid the memory problem in Analytica 4.2, by preventing selected variables from saving the results into memory when they are not needed. See Controlling When Result Values Are Cached for details.

Tracing with the Memory Dialog

A key tool for tracking down bugs is tracing evaluation -- that is looking at the order in which variables and functions are evaluated.

Analytica 4.2 introduces a substantially expanded Memory Usage Dialog that helps here.

  1. Select Show Memory Usage from the Window menu.
  2. Check "Expanded View"
  3. Check "Show object being evaluated"

When you evaluate a variable, it will show the identifier of each variable or function as it is evaluated. During dynamic simulation, it also shows the value of Time for each evaluation.

Of course, these variables usually go by very rapidly -- too fast to follow them. But, if it takes an inordinately long time to evaluate a single variable, perhaps because it is an infinite loop, you will see it stuck on that variable. You can then click the Stop Computing button (or control-break) to interrupt evaluation. To look at the guilty variable, use Find... from the Object menu and type in its identifier.

Note: We recommend you don't leave "Show object being evaluated" checked during normal evaluation, since tracing can slow down evaluation noticeable.

Tracing in the Typescript

The Memory dialog only shows the current variable being evaluated. If it's a function, you often want to know where it was called from. You can do that in the Typescript. Press control-' (control comma) to open the Typescript window. Type in

  >Verbosity:6

to set the tracing verbosity -- i.e. the type of information it displays. Now, when you evaluate a variable, it shows a trace of each variable evaluated in the Typescript, for example:

Evaluating F_ind_gas_dmd[Time=2050] dloop=15142 .
Evaluating F_natgas[Time=2050] dloop=15142 .
Evaluating G_conversion_facto1.
Evaluating Check_for_price.
Evaluating G_uid_from_units.

Trace file or Photo

For a large model, the number of variable evaluations in the Typescript may be large, especially when multiplied by the number of Time periods doe a Dynamic model. The Typescript will only show the last 777 variables. You can save the entire trace to file by typing into the Typescript:

 Model_name>Photo "trace.log"

You may want to include a pathname into the file name. Then evaluate the variable you are interested in. When it finishes evaluation (or if you Stop computing), you should close the trace file by typing into the Typescript:

 Model_name>EndPhoto

You can now open the trace file in a text editor to search or analyze it.

Comments


You are not allowed to post comments.