Difference between revisions of "Repeated Parameter Forwarding"

Line 35: Line 35:
  
 
The three dots (which matches the three dots used when declaring a repeated parameter) indicates that we want each item in the computed result to be passed as one instance of the repeated parameter.  When you use this syntax, the expression following the three dots must produce a list or a 1-D array.
 
The three dots (which matches the three dots used when declaring a repeated parameter) indicates that we want each item in the computed result to be passed as one instance of the repeated parameter.  When you use this syntax, the expression following the three dots must produce a list or a 1-D array.
 +
 +
When you are looking at the examples on this page, be aware that the three dots are part of the expression -- they aren't being used to indicate that we've omitted something.
 +
 +
= Uses =
 +
 +
== Operating over all indexes of an array ==
 +
 +
Several built-in functions accept a repeated index parameter, so that more than one index can be passed when you are applying the operation to multiple dimensions at the same time.  The functions include [[Sum]], [[Max]], [[Min]], [[ArgMax]], [[ArgMin]], [[CondMax]], [[CondMin]], [[Average]], [[Product]], and [[Array]].  When operating over multiple indexes, you list the indexes explicitly, e.g.
 +
:<code>[[Sum]](A,I,J,K)</code>
 +
 +
There are times when you'd like to apply these operators to every index of an array.  You could be careful because doing so may violate the principle of array abstraction, which could limit the flexibility of your model.  But, there certainly are legitimate times to do this.  Parameter forwarding makes it easy, e.g.
 +
:<code>[[Sum]](A,...[[IndexesOf]](A))<code>
 +
 +
== Creating a constant array over computed dimensions ==
 +
 +
Sometimes it is useful to create a constant array over a set of indexes. You can do this using, e.g, <code>[[Array]](I,J,0)</code>, to create an array on indexes I and J having the value 0 everywhere.  But what if the set of indexes is computed?  Here is an example
 +
:<code>[[Array]]( ...#[[SetDifference]]( \[[IndexesOf]](A), \[[IndexesOf]](B)), 0 )</code>
 +
So here we are going to create an array containing all the indexes of A that are not also indexes of B, such that all elements of the array start at 0.
 +
 +
== Forwarding a repeated parameter in a [[User-Defined Function|UDF]] ==
 +
 +
There are times when it is useful to wrap an existing function with a [[User-Defined Function]] that you create.  For example, if an existing function does 99% of what you want, but doesn't treat [[Null]] values the way you like, you might create your own variation.  The original function might have a bunch of parameters that you just simply want to forward to the original function. When the parameter being forwarded is a repeated parameter, you need to use the repeated parameter forwarding syntax.
 +
 +
The second parameter of the built-in [[SetDifference]] function is a repeated parameter. Suppose we wanted to make a variation that ignored empty strings (so that the result has no empty strings). We duplicate the parameter declaration for [[SetDifference]]
 +
 +
<pre>Function SetDifference2(originalSet : Reference OrNull atom; Remove : ...OrNull atom optional; ResultIndex : optional index;keepNull:boolean named atom=false)
 +
'''Definition:'''
 +
  var s1 := [[SetDifference]](originalSet,\([""]));
 +
  SetDifference(s1,...Remove,ResultIndex,keepNull)
 +
</pre>
 +
 +
''Note to self: The optionality of ResultIndex isn't going to work here.  Revisit this example.''
 +
 +
== Computing a set of decisions or constraints for [[DefineOptimization]] ==
 +
 +
The [[DefineOptimization]] function accepts a list of decision and constraint nodes as repeated parameters. If you decide to get fancy, you might decide to create an interface, or some logic, that computes which constraints or decisions should be active.  Repeated Parameter forwarding allows you to provide a computed list of decisions or constraints to the optimization declaration, e.g.
 +
 +
<code>[[DefineOptimization]](decisions: ...ActiveDecisions, constraints: ...ActiveConstraints, maximize: myObjective )<code>
 +
Note that although the two parameters normally look for object identifiers, here the identifier ActiveDecisions is actually the variable that computes which decisions to use (as a 1-D array or list), and not one of the decision nodes.  Similarly for ActiveConstraints.
 +
 +
= See Also =
 +
 +
* [[Function Parameter Qualifiers]]
 +
* [[IndexesOf]]

Revision as of 23:59, 10 April 2013

new to Analytica 4.5

Repeated parameter forwarding is a language extension that enables you to pass a list of computed results to a repeated function parameter. To understand repeated parameter forwarding, you must first understand repeated parameters, hence the Repeated parameters section of Function Parameter Qualifiers is a prerequisite to the content on this page.

Basic idea

Consider the following User-Defined Function:

Function TreeNode( X ; Children : ... )
Definition: Array(TreeNodeIdx,[X,\Children] )

where TreeNodeIdx is an index having two elements, e.g., ['value','children'].

The call TreeNode( 1, 2, 3, 4 ) is used to create this data structure:

SmallTree.png

The repeated parameter, «children», allows you to list as many children as you'd like, without having to make use of square brackets in the syntax. Hence, we could built a multi-level tree using:

TreeNode( 1, TreeNode(2,5,6), TreeNode( 3, 7,8,9, TreeNode(10,11,12,13) ), 4 )

MultiLayerTree.png

Now suppose you have some expression -- I'll just write F( ) -- that computes and returns a list of "nodes", and you want to create a tree node having this set of nodes as the children, with 7 as the root. Your expression doesn't know what F( ) will return, or even how many children it will return, but for illustration let's pretend it returns [1,2,3]. Your first attempt might be

TreeNode(a,F())

This produces an error, because you cannot pass a list value to a repeated parameter; however, logically what you are actually doing here is producing the wrong tree, which would actually be OneChildTree.png The call is providing one instance of the repeated parameter, hence one child node. The value of that child node is the list of values. What we really want is to be able to pass three instances of the «children» parameter to the function, basically

TreeNode(7, Slice(F(),1), Slice(F(),2), Slice(F(),3) )

This would be one way of doing it if we actually knew that F() would return 3 values, but part of the point here is that we can't assume we know how many items F() is going to return.

Repeated parameter forwarding solves the problem. To forward the result of F() to the repeated parameter, we preface it with three dots

TreeNode( 7, ...F( ) )

The three dots (which matches the three dots used when declaring a repeated parameter) indicates that we want each item in the computed result to be passed as one instance of the repeated parameter. When you use this syntax, the expression following the three dots must produce a list or a 1-D array.

When you are looking at the examples on this page, be aware that the three dots are part of the expression -- they aren't being used to indicate that we've omitted something.

Uses

Operating over all indexes of an array

Several built-in functions accept a repeated index parameter, so that more than one index can be passed when you are applying the operation to multiple dimensions at the same time. The functions include Sum, Max, Min, ArgMax, ArgMin, CondMax, CondMin, Average, Product, and Array. When operating over multiple indexes, you list the indexes explicitly, e.g.

Sum(A,I,J,K)

There are times when you'd like to apply these operators to every index of an array. You could be careful because doing so may violate the principle of array abstraction, which could limit the flexibility of your model. But, there certainly are legitimate times to do this. Parameter forwarding makes it easy, e.g.

Sum(A,...IndexesOf(A))

Creating a constant array over computed dimensions

Sometimes it is useful to create a constant array over a set of indexes. You can do this using, e.g, Array(I,J,0), to create an array on indexes I and J having the value 0 everywhere. But what if the set of indexes is computed? Here is an example

Array( ...#SetDifference( \IndexesOf(A), \IndexesOf(B)), 0 )

So here we are going to create an array containing all the indexes of A that are not also indexes of B, such that all elements of the array start at 0.

Forwarding a repeated parameter in a UDF

There are times when it is useful to wrap an existing function with a User-Defined Function that you create. For example, if an existing function does 99% of what you want, but doesn't treat Null values the way you like, you might create your own variation. The original function might have a bunch of parameters that you just simply want to forward to the original function. When the parameter being forwarded is a repeated parameter, you need to use the repeated parameter forwarding syntax.

The second parameter of the built-in SetDifference function is a repeated parameter. Suppose we wanted to make a variation that ignored empty strings (so that the result has no empty strings). We duplicate the parameter declaration for SetDifference

Function SetDifference2(originalSet : Reference OrNull atom; Remove : ...OrNull atom optional; ResultIndex : optional index;keepNull:boolean named atom=false)
'''Definition:''' 
   var s1 := [[SetDifference]](originalSet,\([""]));
   SetDifference(s1,...Remove,ResultIndex,keepNull)

Note to self: The optionality of ResultIndex isn't going to work here. Revisit this example.

Computing a set of decisions or constraints for DefineOptimization

The DefineOptimization function accepts a list of decision and constraint nodes as repeated parameters. If you decide to get fancy, you might decide to create an interface, or some logic, that computes which constraints or decisions should be active. Repeated Parameter forwarding allows you to provide a computed list of decisions or constraints to the optimization declaration, e.g.

DefineOptimization(decisions: ...ActiveDecisions, constraints: ...ActiveConstraints, maximize: myObjective ) Note that although the two parameters normally look for object identifiers, here the identifier ActiveDecisions is actually the variable that computes which decisions to use (as a 1-D array or list), and not one of the decision nodes. Similarly for ActiveConstraints.

See Also

Comments


You are not allowed to post comments.