Multidimensional input to a function

8.87K viewsScripting
0

Hi.

I am trying to define a simple function using scripting:
* Inputs: a list of elements, for instance item:id[first]..item:id[last]
* Output: any function of the whole elements (sum for instance)

How should I declare the input in the script of the function?

Under Java, I would have declared as input of my method “test” an array of doubles (“input”) containing the values “item:id[first]..item:id[last]” and written:

double test( double[] input ){
int numberItems = input.length;
double result = 0;
for( int i=0 ; i<numberItems ; i++){
result = result + input[i];
}
return result;
}

Thank you.

Julien

0

Hi Julien,

Your example works because Quantrix automatically evaluates the range that you specify in your formula, and generates a linear array containing all the values in that range – which is in turn passed as the argument to the function. The function itself sees only a one-dimensional array. You would not, for example, be able to access the array values in a two-dimensional way like:

[code:xf1it9sy]
for (int i = 0; i < inputData.length; i++)
for (int j = 0; j < inputData[0].length; j++)
output += inputData[i][j];
[/code:xf1it9sy]

One consequence of this is that if you wanted to write a function that could process the data in a way that incorporated knowledge of its original dimensions, you would not be able to do so unless you passed those dimensions as separate arguments. Nevertheless, this is a pretty handy workaround and would probably be useful in many cases.

-Ben

0

It is actually possible to give multidimensional arrays as input of a scripted function. They have though to be declared as double[], not double[][].

[quote="Ben G":27021kax]Hi Davide,

Currently, Quantrix does not support multi-dimensional arrays as function parameters. It might be possible to change this, but I think it would be wise to first investigate more fully what you want to accomplish and see if there is an alternative approach that is efficient under the current implementation. Is it possible to provide a model that gives a concrete illustration of the data you are working with and what you want the outcome to be?

Thanks,
Ben[/quote:27021kax]

0

Hi Simon,

It will call it every time, unfortunately. It is hypothetically possible to offer caching for scripted functions, but I’m not aware of any current plans to do so. However, I’ll pass this up the chain so that the issue will at least be on the radar in case we hear more requests for it in the future.

Regards,
-Ben

0

I’ve been working on a situation similar to one shown by Ben here:
[quote="Ben G":2pzxh544]
…although Quantrix will let you return a list from a scripted function, it does not generally know what to do with it. … for the time being if you want to populate a range correctly based on the result of this function, you will need to write another scripted function that parses out the correct value at each index in the range

[font=”Courier New”]SORTED PRICE = chooseFromList(#SORTED UNIT; sort( WAREHOUSE::PRICE ; WAREHOUSE::QUANTITY ; 1 ))[/font]

[/quote:2pzxh544]

My question is whether the function [b:2pzxh544]sort()[/b:2pzxh544] will get called for every cell to be filled, or is the Quantrix function parser clever enough to only call it once? In my case the equivalent function to sort() is heavy and I really only want to call it once. My alternative is to run it in a script and write the results to a matrix of “working storage” but that is less clean from a user perspective.

Thanks

Simon

0

Hi Davide,

No problem; I’ve been a little delayed myself. Thanks for the follow-up. Glad you were able to resolve it.

Ben

0

I Ben,
sorry for the delay in the feedback to you answer; I took a different direction and now things work.

Thanks,
Davide

0

I attached to the post an example of application where a matrix would be needed as input: stochastic dynamic programming, an optimization method developed by Bellman.

The needed inputs are:
1. Stages (time steps)
2. States that can be taken by the studied system
3. Control variables (decisions on the system)
4. Perturbations (random variable)
5. Probabilities that a perturbation takes a given value knowing the state of the system at the beginning of the stage

In the model attached, the probabilities are included in the script. But how to make them an input of the function?

Best regards,

julien

0

Hi Davide,

Currently, Quantrix does not support multi-dimensional arrays as function parameters. It might be possible to change this, but I think it would be wise to first investigate more fully what you want to accomplish and see if there is an alternative approach that is efficient under the current implementation. Is it possible to provide a model that gives a concrete illustration of the data you are working with and what you want the outcome to be?

Thanks,
Ben

0

Here is an additional comment to Panizza’s question.

In the model attached to this post, I have a function testArray, which input is an array double[]. No problem, the function appears in the menu function.

A second function, testMatrix, has for input a matrix double[][]. The scriped function does not appear in the function menu.

Best regards,

Julien

0

Hi,
working on a similar topic, but in a more general way, I have a multidimensional range as input for a function (for instance “Matrix1::” where Matrix1 has more than 2 categories, so that the range is a “matrix” not an array); in the function the range is translated in an array of values, but it is not clear for me the iteration order used to get the array .In QAPI there was a cellIterator, with a default known iteration order, how can I get the iteration order in this context?

Thanks,
Davide

0

Ben,

Many thanks for your very, very helpful explanation. This opens many new opportunities when developing user defined functions.

Dominik

0

Thank you all for the answers.

Julien

0

Hi All,

It is okay to return a list from a scripted function (with a catch – see below). The #SCRIPT message Julien is seeing in the attached model is due to a runtime error caused by a bug in the sort function, and is unrelated to the list issue.

[code:119y4v1b]
//Second ‘sortedQuantity’ should be ‘numberItems’
def double[] sortedQuantity = new double[sortedQuantity]
[/code:119y4v1b]

Now, although Quantrix will let you return a list from a scripted function, it does not generally know what to do with it. In the default case, it will simply iterate over the cells in the range you are trying to assign to and populate each one with the first element in the list. Setting aside the question of whether or not this is the correct behavior, for the time being if you want to populate a range correctly based on the result of this function, you will need to write another scripted function that parses out the correct value at each index in the range, like so:

[code:119y4v1b]
double chooseFromList(int index, double[] list)
{
return list[index – 1]
}
[/code:119y4v1b]

I’ve attached a modified version of Warehouse.model that includes a fix to the sort function and a chooseFromList function, and has the formulae adjusted to achieve what (I think) Julien was after.

-Ben

0

Hi Julien,

I am not sure if this is true but so far I wasn’t able to use double[] as the return type of a function.

@Quantrix developers: Is this true? How can we use an array as a result of a user defined function?

Many thanks for clarification.

Dominik

0

Thank you for these answer elements. I learned there is actually no problem defining an array as input in a scripted function.

But why does the (ugly) script I posted return “#SCRIPT”? I get the same error in the attached model, where a sorting function is scripted. Does it come from the “for” structure?

Julien

0

Hi Julien,

Your are doing the most right.

Just write a function like this (a very simple example):
[code:1myxkbs2]

double my_sum(double[] numbers)
{
double sum = 0

for(double number : numbers)
sum += number
return sum
}
[/code:1myxkbs2]

Then you can use this function formulas like these:
[list:1myxkbs2]
‘Sum Values (items 4 to 8)’ = my_sum(Matrix1::Values:Item4 .. Values:Item8)
[/list:u:1myxkbs2]
[list:1myxkbs2]
Sum all = my_sum(Matrix1::Values)
[/list:u:1myxkbs2]

The clue is that you can define the range (or dimension) of the input in a Quantrix formula.

Take the attached model and play around with it.

Is this what you are looking for?

Regards,
Dominik