Array Functions and Operators

Revision as of 10:35, 27 November 2006 by Fredbrunt (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

(Up to Detailed Analytica Documentation)

PositionInIndex

PositionInIndex is the positional equivalent of SubIndex.

PositionInIndex(A:Array[I] ; U : atomic ; I : IndexType )

Finds u in A and returns the integer position of the value along I. If there are duplicates, the largest such position is returned. PositionInIndex may be necessary when I contains or may contain duplicates, in which case SubIndex isn't sufficient, and without PositionInIndex, there is no easy workaround.

The @ Operator

When applied to an index, the @ operator returns the position of each element. @I is the 1-D array [1,2,3,4,...] indexed by I. This is equivalent to Cumulate(1,I), but much more convenient.

The syntax A[@I=x] is a shorthand for Slice(A,I,x), just as A[I=x] is a shorthand for Subscript(A,I,x).

If I and J are indexes of the same length but different elements, and A is indexed by I, you can re-index I by J using A[@I=@J]. This is a bit more convenient than Slice(A,I,Cumulate(1,J)).

To lookup the position of a single element in an index, use @[I=x]. This quietly returns 0 if x is not in I. The test @[I=x]>0 returns True if the element x is in I, False if not.

The convenient subscripting syntax, A[I=x], is very convenient when you are dealing with your own indexes inside variable nodes. You know if two indexes have the same elements, and therefore if you can reindex using A[I=J]. However, when creating user-defined functions, you often want to avoid making strong assumptions about what the element values of an index are. You end up with a more flexible function if you only make assumptions about the length of indexes, and not their contents. In these situations, positional operations result in more flexible functions. Furthermore, if you need to create functions that work when there are duplicate elements, than again, positional operations are necessary. The @ operator tremendously shortens and simplifies functions that manipulate arrays positionally. While you have to know what the @ operator does, @I is no more obtuse than Cumulate(1,I) -- a trick used regularly and quite mysterious to someone who hasn't seen it previously.

Set Slice Assignment

You can now assign a value to a single slice of a local variable using syntaxes:

A[I=x] := v

A[@I=n] := v

Subscript(A,I,x) := v

Slice(A,I,n) := v

This is only allowed if A is a local variable. The assignment operation may increase the dimensionality of A, since the new value for A will include I, as well as any dimensions appearing in x, n, or v. If x and v, or n and v, share a dimension, then the dimensions are aligned and essentially multiple slices are assigned simultaneously. The assignment avoids making internal copies of the array values when possible. Since arrays and parts of arrays can be shared amongst values, copies or partial copies must sometimes be made when a slice assignment is evaluated. However, once the copy is made on the first such assignment, that portion of the array is usually no longer shared, so successive assignments are highly efficient and don't need to make excessive copies. This efficiency makes the implementation of many algorithms plausible in Analytica that may not have been previously.

As with full assignment, side-effects are not allowed, so slice assignment can only be performed on a local value.

Subscript [I=x] operator

As of Analytica 3.2, [I=x] now acts as an operator, and can follow any expression. Previously it could only augment a variable identifier. As an expression, it can follow an expression such as (A+B)[I=x], or a function call f(A,B)[I=x], or even another subscript: A[I=x][J=y]. This operator has the highest precedence of any operator except the dot operator. So A^B[I=x] is A^B[I=x], etc., but A.I[I=x] is (A.I)[I=x].

The dynamic time offset variation, [Time-k], still only associates with a variable identifier. Thus, an expression such as (A+B)[Time-k] would not be accepted. You would have to write A[Time-k] + B[Time-k], at which point Analytica would recognize the dependence from A and B as a dynamic dependency, and render the corresponding arrow in gray.

Rank

Rank(X : all Vector[I] ; I : optional Index ; type : optional atomic numeric=-1)

The rank function has been extended with an optional type parameter, which may take the following values:

  • -1 = lower-rank (default)
  • 0 = mid-rank
  • 1 = upper-rank

The rank type determines how values in X that occur multiple times are ranked. For example, if the value x=5 occurs 6 times, and there are 3 other values in X that are less than 5, then x=5 appears in the sort-order at positions 4,5,6,7,8, and 9. The lower-rank of x=5 is 4, the upper-rank of x=5 is 9, and the mid-rank is 6.5.

ArgMin, ArgMax

New to 4.0: The ArgMin function, and the ability to return coordinate over multiple indexes.

ArgMin( R : vector[I] ; I : ... optional IndexType ; position : optional boolean )
ArgMax( R : vector[I] ; I : ... optional IndexType ; position : optional boolean )

Example usages:

ArgMin( R:Cost, I:Bid )
ArgMax( R:Profit, I: UnitPrice, InvestmentLevel, DoTest )
ArgMax( R:OneDArr )      /* Not recommended */

When only one index is provided (or when no index is provided but the parameter is 1-D), returns the index value at which the smallest (ArgMin) or largest (ArgMax) value of R occurs. In the event of ties, the element occuring closest to the end of index I is returned. (This functionality is unchanged from 3.1)

When more than one index is specified, returns a coordinate at which the smallest (ArgMin) or largest (ArgMax) value occurs. The coordinate is a 1-D array indexed by a local index having the name .Dim. The elements of the local index are the index names, and the value of the result is the element from that index.

By default, ArgMax and ArgMin return the index element(s). A positional dual is provided, in which the index position (rather than index element) is returned. For example:

 ArgMax( R : Profit, I : UnitPrice, position : true )

returns the 1-based position in I, rather than the actual price. If an index might contain duplicate values, it may be necessary to use positions rather than elements to avoid ambiguities.

CondMin, CondMax

Present in 3.1, but not documented.

CondMin( X, cond, I )
CondMax( X, cond, I )

CondMin returns the smallest value in X along I in which the corresponding condition, cond, is not false. If cond is false everywhere along I, returns -INF.

CondMax returns the largest value in X along I in which the corresponding condition, cond, is not false. If cond is false everywhere along I, returns INF.

Area

The full declaration for Area is now:

Area( R : Numeric[J] ; I : ascending Numeric[J] ; X1,X2 : opt numeric atomic ; J : opt hidden IndexType = I )

With J not specified, I can be an index with numeric ascending values, or it can be a self-indexed array with arbitrary index values but with numeric ascending values along Self.

The J parameter also makes it possible to have an arbitrary X array:

Area( Y, X, J: In1)

where X and Y are arrays indexed by J (X must be ascending along J).

Some notes: J is hidden from the user, since the main concern was fixing several bugs with the function while maintaining backward compatibility. However, as the above example shows, it can be useful. The second parameter is named I for legacy reasons, but it would be better named X with the J parameter named I. Consider this change when updating manuals.

Another difference relative to 3.1 is that X2 (upper bound) can be specified while not specifying X1 (lower bound). So, for example, you could find the area up to a given point, e.g.:

var dens := Pdf(Ch1);
Area( dens, dens.Step, X2:x )
Comments


You are not allowed to post comments.