Iterate


Iterate( initial, expr, until, maxIter, warn )

Iterates a computation until a termination condition (such as convergence) is satisfied, or until a maximum number of iterations is reached.

To use Iterate, the call to Iterate must occur at the top level of the definition (similar to how Dynamic must occur at the top level). The first parameter, initial, specifies the starting value for the iteration, and the second parameter, expr, specifies how the subsequent values are computed from the previous value. The second parameter, expr, can depend directly or indirectly upon the variable defined by Iterate, forming a recurrence.

The third parameter, until, specifies a termination condition. Iterate continues evaluating expr until all array elements returned by expr are non-zero (true), or until the maximum number of iterations specified by the optional fourth parameter is reached. If the fifth parameter is specified as true, a warning is issued if the maximum number of iterations is reached without full convergence.

Iterate is often used when the iteration should occur over a large portion of your model. For smaller loops that can be self-contained in a single definition, or that appear in User-Defined Functions, the While..Do construct is usually used instead.

Example

Market Equilibrary Diagram.jpg

In the model depicted, the manner in which the market price reacts to a imbalance between supply and demand is modeled. Given a Price, the supply and demand at that price are forecast, and then used to determine a market price at that supply/demand point. By iterating on Price, the steady-state market equilibrium price is computed. This iteration is accomplished by defining Price as:

Iterate( Price_Guess, Next_price, abs(Next_price-price)<0.01, 50 )

This iterates until the change in price is less than 0.01, or until 50 iterations are computed.

Iterating Multiple Variables

In some cases, you may have several variables that you need to update in each iteration. For example, you may wish to update estimates for both Price and Market_size at each iteration. When you do this, it is important that you have only one node defined using Iterate. You would NOT want to define both Price and Market_size using Iterate. Two instances of iterate in that fashion would specify two separate (and nested) iterations, which is not what is intended. Instead, what you need to do is group all variables into a single state representation. The components of that state are listed along an index.

Market Equilib Diagram2.jpg

In the above diagram, State_Index is defined as a list of labels:

State_index ↓
"Price"
"Market Size"

Initial_state is defined as a table:

Table(State_index)(Price_Guess,Market_size_guess)

and Next_State is similarly defined:

Table(State_Index)(Price_Guess,Market_size_guess)

and a single call to Iterate is present in State:

Iterate( Initial_state, Next_State, abs(state-next_state)<0.01, 50)

for convenience, Price and Market_Size break out the elements of State so that their identifiers can be used directly in expressions. For example, Price is defined as Price[State_Index='Price'].

The preceeding definitions assume that State and Market_size have the same dimensionality. For example, both may be scalars, or both contain exactly the same indexes. When iterating over multiple variables, this is not always the case. When the indexes may differ, then you should place each component inside a reference. The preceeding definitions would thus become:

Initial_state := 
   Table(State_index)(\Price_guess,\Market_size_guess)
Next_state := 
   Table(State_Index)(\Price_Guess,\Market_size_guess)
Price := 
   #State[State_index='Price']
Market_size :=
   #State[State_index='Market Size']
State :=
   Iterate( Initial_state, 
            Next_State, 
            abs(price-next_price)<0.01 and abs(market_size-next_market_size)<1, 
            50)

Note that \ and # are the reference and de-reference operators.

The method of gathering references to values into an array is a flexible method that generalizes to any number of variables.

Iterate with Dynamic

Iterate can be used in conjunction with Dynamic. Depending on the model structure, this can either result in an iteration within a dynamic loop, where the iteration to convergence occurs at each point in time, or it can result in a dynamic loop within an iteration, in which case the entire dynamic loop is computed to completion within each iteration.

(To do: provide some examples)

Interacting Iterate Functions

If you have two (or more) variables defined using the Iterate function, they should not be mutually dependent on each other. This case creates an ambiguity (for example, the result would depend on which was evaluated first), and results in an error message.

It is okay for one to be nested within the other, in which case the inner iteration runs to convergence during each iteration of the outer iterate. However, the need for nested iterations like this are rare. You should make sure that you don't intend to have a single iteration with multiple variables updated in the same iteration (see the earlier section on this page).

Iterate vs. While..Do

Iterate and While..Do are closely related, and both are often used for implementing convergence algorithms. When implementing an iterative algorithm in a User-Defined Function, you would normally use While..Do. However, in some situations you may develop a fairly sizeable influence diagram model, where you wish to iterate over the entire model. In that case, Iterate is very convenient, and may require only small modifications.

The While..Do construct requires its parameter, which determines when the loop terminates, to be atomic, while Iterate allows array-valued termination conditions, but continues until all cells are true.

There are a few other approaches to implementing iterations within Analytica. NlpDefine performs a full optimization search. The Solve and GoalSeek functions are similar, although scaled down somewhat in their sophistication. User-Defined Functions can be recursive, although the recursion depth is usually limited to 255, which can be a limiting factor. And to iterate over an existing model structure, While..Do can be used with WhatIf, or from a button script, While..Do can be used with assignment (often a useful way to iterate in very large scale sampling applications that exceed memory required for built-in Monte Carlo sampling). And of course, there is Dynamic.

See Also

Comments


You are not allowed to post comments.