Difference between revisions of "Self-Indexed Arrays"

(tutorial on list definitions)
Line 63: Line 63:
 
  Join( IndexValue(X), X, "," )
 
  Join( IndexValue(X), X, "," )
 
yielding ''"one,two,three,four"''.
 
yielding ''"one,two,three,four"''.
 +
 +
= Copy Index =
 +
 +
Using the X variable defined above, suppose we wish to define an index, J, having the same values that X has.  We now have two choices - should this new index be composed of X's index values, i.e., ['one','two','three','four'], or of X's result values, i.e., [15,12,13,8]?  Either is possible:
 +
 +
CopyIndex( X )            --> [15,12,13,8]
 +
CopyIndex( IndexValue(X) ) --> ['one','two','three','four']
 +
 +
Note: There are several alternative ways of copying the index value.  The [[IndexValue]] function is new to Analytica 4.0, but for earlier versions one could use
 +
Subset( Array(X,1) )      --> ['one','two','three','four']
  
 
= List Definitions =
 
= List Definitions =
Line 76: Line 86:
 
[[image:Cash_flow_stmt_result.jpg]]
 
[[image:Cash_flow_stmt_result.jpg]]
  
---------------------------
+
Side note: When Analytica displays a self-indexed result, and the self-index is composed of object identifiers, then Analytica uses separate number formats for each row (or column if pivoted), taking the number format for the corresponding row from the identifier that appears in the self-index.  This provides a capability to format each row of a table differently.
 
 
In Analytica, an object may have separate values for each of the following:
 
* Mid value
 
* Sample value
 
* Index value
 
 
 
When you use an identifier in an expression, Analytica knows which type of value to retrieve or compute based on context -- a combination of where the identifier is used in the syntax, and the current [[Evaluation Modes|evaluation mode]].
 
 
 
Syntactically, Analytica expressions appear in value contexts and index contexts.  For example, in the expression
 
Sum(A,I)
 
the identifier A appears in a value context, and I appears in an index context.  From this context, Analytica knows whether it is accessing the computed value, or the index value.
 
 
 
In a value context, the [[Evaluation Modes|evaluation mode]] determines whether the Mid value or Sample value is being computed or retrieved.  See [[Evaluation Modes]] for more details.
 
 
 
Many objects in an Analytica model, if not most objects, do not have index values different from their main (mid/sample) values.  However, there are several ways in which a variable might end up with an index value different from its main value:
 
* Self-Index tables:  If you select "Self" as an index for a table, the row-headers become the index value, the body cell expressions determine the main value.
 
* List definition containing identifiers or expressions: If you define a variable or index as a list of identifiers, for example [I,J,K], then the index value is a list of [[varTerm]]s, while the evaluated value is a 3-D array indexed by I, J, and K.
 
* List-domain: When a variable contains a list-domain or index-domain, its computed value may be different from its domain.  In this case, the domain serves as the index value.  Domains as indexes often serve as indexes for [[DetermTable]]s and [[ProbTable|Probability Tables]].
 
  
 +
The value of IndexValue(Cash_flow_statement) in this example is composed of a list of [[varTerm]]s, essentially handles to Analytica objects.  In advanced Analytica modeling, these varTerms can be utilized for meta-level inference and button scripting (performing inference about the model itself).  Meta-level inference is beyond the scope of the current article, but we point this out for readers who may already be at this level of expertise. 
  
Occassions may arise when you wish to access a different value of an object than the one implied by the expression context.  Each type value can be accessed using:
+
= Self-Indexes from the Domain =
* [[IndexValue]](X) : returns the index value of X
 
* [[Sample]](X) : Evaluates and returns the sample value of X
 
* [[Mid]](X) : Evaluates and returns the mid value of X
 
* domain of X : Returns the domain of X.
 
  
= Note About Future Changes =
+
When the domain attribute contains an explicit list, either a list of expressions, list of labels, or index-domain, Analytica treats the domain value as the variable's self-index.  This is often used when defining a [[Choice]] definition, [[DetermTable]] or [[ProbTable]] definition.  For example, in a ProbTable, the main value (usually the [[Sample]]) is the randomly-sampled set of values, but the [[IndexValue]] for the variable is the set of all possible values.
  
Currently, when an object has a list-valued or index-valued domain, that domain becomes the variable's index value.  This is a functionality we expect to change in future Analytica releases, so we encourage you to avoid relying too heavily on this.
+
The domain values can also be accessed using:
 +
domain of X
  
We will ensure that in the future, [[ProbTable]]s and [[DetermTable]]s that are indexed by domains continue to function as such.  
+
It should be noticed that the treatment of the domain value as a self-index value is a functionality that Lumina plans to eventually eliminate.  If you wish to refer to the domain value of a variable, it is preferable to use "domain of X" rather than IndexValue(X) to ensure forward compatibility with future releases of Analytica.
  
However, we intend for the index value to be determined ultimately by the definition of the variable, and possibly different from the [[domain].  In the future, (domain of X) can serve as an index, and in the future may be different from IndexValue(X).  A multi-select Choice list will be a future example.
+
The use of the domain in a [[Choice] definition, or to index a [[DetermTable]] or [[ProbTable]] will continue to be valid in future releasesHowever, when the changes we envision are eventually enacted, we could allow for the possibility of a multi-select Choice control, for example.  In such a case, the main and index values could be a subset of the domain value.
  
This future change is mentioned here, now, since it could impact backward compatibility later.
+
Note: Few models utilize the domain of a variable as a self-index outside their use of Choice(Self,n), DetermTable or ProbTable, so this change only impacts models that do fairly usual things.

Revision as of 00:10, 20 February 2007

This page introduces you to the concept of Self-Indexed Arrays in Analytica.

In Analytica arrays are dimensioned by indexes. Most commonly, an index is created and defined using an index object. An index object appears on an influence diagram with the the following node shape:

IndexNode.jpg

However, variable nodes can also serve as indexes for arrays. For example, a variable defined as a list can serve as an index. Occassionally, some variables can be made to serve double-duty -- acting as an index, and at the same time evaluating to a value (usually an array value). These are called self-indexed variables (or self-indexed arrays), and their main value and their index value can be different.

Self-indexed variables arise, or can be created in several different ways.

Self-Indexed Tables

( to do: insert follow-along steps for creating a self-indexed table )

Let's create a self-indexed table.

First, drag a variable node to the diagram and name it X. Press the Expr.jpg button on the toolbar to edit the definition and select "Table" from the definition type dropdown:

CreateTable.JPG

In the index chooser dialog, select the "X (Self)" index and press OK.

SelectSelfIndex.jpg

You have now just created an edit table with a self index.

SelfIndexedTable.jpg

Notice that the row-index is X, and the edit table itself is for X. Here the row headings are the index values for X, the table body cells hold the main value for X. Next, fill in both the self-index value and the body cells with values, as follows.

SelfIndexedTable2.jpg

Notice that the self-index values may be different from the variable's main value.

Expression Context

When a variable has both a main value and an index value, what happens when its identifier is used in an expression? (Side note: In general, a variable may have a Mid value and a probabilistic, or sample, value. See Evaluation Modes for more detail. Here we refer to either of these as the main value.)

As it turns out, Analytica can determine whether to use the main value or the index value based on the context in which the identifier appears. A simple example is this:

Sum( X, X )

This expressions sums the value of X along the X index. So, when X is a self-indexed variable, the main value is used for the first parameter, and its self-index value is used for the second parameter.

In general, the parameters of a function (whether built-in or user-defined) are declared using various Function Parameter Qualifiers. When a parameter is declared using the IndexType qualifier, then identifiers passed for that parameter are interpreted as indexes. Parameters that are declare otherwise are interpreted as values. (Note: There are further subtleties involved when a parameter is declared as a VariableType, which are beyond the scope of this introduction).

The IndexType qualifier

When you define your own user-defined function (UDF), you might declare a parameter to be an index. This creates a local variable that is an alias for the index that is passed in. If this local variable is used in a value context, the index value (and not the main value) is used. So, for example, consider the following function:

JoinIndex.jpg

Suppose, using the self-indexed array defined earlier, we call this function using:

JoinIndex( X ) 

The result obtained is:

"one,two,three,four"

Compare this to what we would get by evaluating, Join( X,X,',' ), which results in "15,12,13,8".

Three special functions exist to explicit control which value to use from within an expression. These are applicable to expressions being evaluated in a value context. These are: Mid, Sample and IndexValue. The Mid and Sample functions provide access to the main values of the variable (see Evaluation Modes for the distinction), while the IndexValue function returns the index value. Using the IndexValue function, we could for example join the index value of X using

Join( IndexValue(X), X, "," )

yielding "one,two,three,four".

Copy Index

Using the X variable defined above, suppose we wish to define an index, J, having the same values that X has. We now have two choices - should this new index be composed of X's index values, i.e., ['one','two','three','four'], or of X's result values, i.e., [15,12,13,8]? Either is possible:

CopyIndex( X )             --> [15,12,13,8]
CopyIndex( IndexValue(X) ) --> ['one','two','three','four']

Note: There are several alternative ways of copying the index value. The IndexValue function is new to Analytica 4.0, but for earlier versions one could use

Subset( Array(X,1) )       --> ['one','two','three','four']

List Definitions

A second way that index values often arise in Analytica is by defining a variable as a list of identifiers, or as a list of expressions. This is often very convenient when creating a report, bringing several results together in a single table view.

Cash flow stmt definition.jpg

The variable shown in the preceding screenshot is defined as a list of identifiers. When this variable is evaluated, it has both a self-index (the list of identifiers) and a value, obtained by evaluating each of the variables appearing in the table and joining them into a single array.

In this model, most of the variables appearing in the list evaluate to a result that is indexed by Time. Therefore, the value obtained is two-dimensional, indexed by itself (Cash_flow_statement) and by Time.

Cash flow stmt result.jpg

Side note: When Analytica displays a self-indexed result, and the self-index is composed of object identifiers, then Analytica uses separate number formats for each row (or column if pivoted), taking the number format for the corresponding row from the identifier that appears in the self-index. This provides a capability to format each row of a table differently.

The value of IndexValue(Cash_flow_statement) in this example is composed of a list of varTerms, essentially handles to Analytica objects. In advanced Analytica modeling, these varTerms can be utilized for meta-level inference and button scripting (performing inference about the model itself). Meta-level inference is beyond the scope of the current article, but we point this out for readers who may already be at this level of expertise.

Self-Indexes from the Domain

When the domain attribute contains an explicit list, either a list of expressions, list of labels, or index-domain, Analytica treats the domain value as the variable's self-index. This is often used when defining a Choice definition, DetermTable or ProbTable definition. For example, in a ProbTable, the main value (usually the Sample) is the randomly-sampled set of values, but the IndexValue for the variable is the set of all possible values.

The domain values can also be accessed using:

domain of X

It should be noticed that the treatment of the domain value as a self-index value is a functionality that Lumina plans to eventually eliminate. If you wish to refer to the domain value of a variable, it is preferable to use "domain of X" rather than IndexValue(X) to ensure forward compatibility with future releases of Analytica.

The use of the domain in a [[Choice] definition, or to index a DetermTable or ProbTable will continue to be valid in future releases. However, when the changes we envision are eventually enacted, we could allow for the possibility of a multi-select Choice control, for example. In such a case, the main and index values could be a subset of the domain value.

Note: Few models utilize the domain of a variable as a self-index outside their use of Choice(Self,n), DetermTable or ProbTable, so this change only impacts models that do fairly usual things.

Comments


You are not allowed to post comments.