Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.

 View Only
  • 1.  Initiating sets of tuples which contain arrays

    Posted Mon November 02, 2020 10:51 AM
    Hi there

    I'm working in OPL and am struggling to initiate a set of tuples where the tuple contains an array. I have Googled and read the OPL help files / manual, but can't find anything.

    There is a set of tuples, Processed_Data, that I need to fill with data. The Processed_Data tuple contains an array:

    {string} Factors = {"a","b","c"}; tuple T_2 { key int i; int a[Factors]; }; {T_2} Processed_Data = ​
    However the input data has to come from a CSV and so has this format:

    tuple T_1 { key int i; int a; int b; int c; }; {T_1} Input_Data = {<7,3,4,9>, <8,2,3,5>, <9,1,2,7>};​
    I need to derive the Processed_Data from the Input_Data and I can't see how to do this.

    I assume / hope that it will be something like this:

    {T_2} Processed_Data = {XXXXX d.i, XXXXX f=="a" ? d.a : f=="b" ? d.b : d.c XXXXX f in Factors XXXXX d in Input_Data}; ​


    I have tried this:

    {T_2} Processed_Data = {<d.i, [f : f=="a" ? d.a : f=="b" ? d.b : d.c | f in Factors]> | d in Input_Data};
    and this:

    {T_2} Processed_Data = {<d.i, <d.a, d.b, d.c>> | d in Input_Data}; ​
    but these were more wishful thinking than likely attempts and they don't work.

    I thought about using an intermediate variable Temp, the initiation of which does work:

    {int} Input_Data_i = {idata.i | idata in Input_Data}; int Temp[Input_Data_i][Factors] = [i : [f : (f=="a" ? a : f=="b" ? b : c)] | f in Factors, <i,a,b,c> in Input_Data]; ​
    but I then can't see how to get this 2-dimensional array into the T_2 tuple set.

    I imagine that this can worst case be done in ILOG Script, but I would prefer to do it in pure OPL if possible.

    If anyone is able to suggest anything on this it would be very much appreciated.

    Thanks
    Andrew

    ------------------------------
    Andrew Bullock
    ------------------------------

    #DecisionOptimization


  • 2.  RE: Initiating sets of tuples which contain arrays

    Posted Mon November 02, 2020 11:33 AM
    Hi,

    could

    Turn a tuple set into a 2D array

    in

    https://www.linkedin.com/pulse/tips-tricks-opl-cplex-alex-fleischer/

    help ?

    regards

    ------------------------------
    ALEX FLEISCHER
    ------------------------------



  • 3.  RE: Initiating sets of tuples which contain arrays

    Posted Tue November 03, 2020 05:24 AM
    Alex

    Thanks for the speedy reply.

    The Turn a tuple set into a 2D array is similar but kind of the other way around.

    The biggest issue for me in the original problem is knowing the syntax for initiating an array inside a set of tuples. I really can't see how to do it. Any ideas?

    Also I've noticed that with this forum, when I insert code, it subsequently turns red and loses it's line breaks (see above). What's the right way to insert OPL code in this forum (e.g. which code type should be selected from the dropdown for OPL, etc.) so that it continues to look correct?

    Thanks
    Andrew

    ------------------------------
    Andrew Bullock
    ------------------------------



  • 4.  RE: Initiating sets of tuples which contain arrays

    Posted Tue November 03, 2020 07:56 AM
    Hi,

    let me apply what I shared with you to your example:


    tuple T_1 { key int i; int a; int b; int c;};
    {T_1} Input_Data={<7,3,4,9>,<8,2,3,5>,<9,1,2,7>};

    {string} Factors = {"a","b","c"};
    tuple T_2 { key int i; int a[Factors]; };

    {int} I={e.i | e in Input_Data};
    int ar[i in I][f in Factors]=(f=="a")
    ?item(Input_Data,<i>).a:((f=="b")
    ?item(Input_Data,<i>).b:
    item(Input_Data,<i>).c);

    int temp[Factors];

    {T_2} Processed_Data;

    execute
    {
    for(var i in I) Processed_Data.add(i,temp);

    for(var p in Processed_Data)
    {
    for(var f in Factors) p.a[f]=ar[p.i][f];
    }

    writeln(Processed_Data);
    }


    gives


    {<7 [3 4 9]> <8 [2 3 5]> <9 [1 2 7]>}

    ------------------------------
    ALEX FLEISCHER
    ------------------------------



  • 5.  RE: Initiating sets of tuples which contain arrays

    Posted Wed November 04, 2020 05:45 AM
    Alex

    As ever you are the master! Thank you for this.

    I was hoping that there was a way to do this in pure OPL but I cannot find the syntax to access the array in the tuple set.

    My only comment is that instead of:

    {int} I={e.i | e in Input_Data};
    int ar[i in I][f in Factors]=(f=="a")?item(Input_Data,<i>).a:((f=="b")?item(Input_Data,<i>).b:item(Input_Data,<i>).c);

    you could do:

    int ar[{e.i | e in Input_Data}][Factors] = [i : [f : (f=="a" ? a : f=="b" ? b : c)] | f in Factors, <i,a,b,c> in Input_Data];

    which is maybe easier to read.

    So in general is it possible from OPL to initiate an array as part of a tuple within a set or do you always have to use ILOG Script?

    Thanks
    Andrew

    ------------------------------
    Andrew Bullock
    ------------------------------



  • 6.  RE: Initiating sets of tuples which contain arrays

    Posted Wed November 04, 2020 09:13 AM
    Edited by System Admin Fri January 20, 2023 04:48 PM
    Hi,

    even 

    {string} Factors = {"a","b","c"};
    tuple T_2 { key int i; int a[Factors]; };

    {T_2} Processed_Data={<1,[2,3,4]>};

    execute
    {
    writeln(Processed_Data);
    }

    does not work yet and do not hesitate to log a wish in Aha if you want that to work.

    If you do not want to use any scripting I suggest you to rely on tuple sets:

    tuple T_1 { key int i; int a; int b; int c;};
    {T_1} Input_Data={<7,3,4,9>,<8,2,3,5>,<9,1,2,7>};

    {string} Factors = {"a","b","c"};
    tuple T_2 { key int i; key string factor; int a; };

    {int} I={e.i | e in Input_Data};

    {T_2} Processed_Data={<i,f,
    ((f=="a")
    ?item(Input_Data,<i>).a:((f=="b")
    ?item(Input_Data,<i>).b:
    item(Input_Data,<i>).c))> | i in I , f in Factors};

    execute
    {
    writeln(Processed_Data);
    for(var i in I)
    {
    write(i," ==> ");
    for(var f in Factors) //write(Opl.item(Processed_Data,Processed_Data.find(i,f)));
    write(Processed_Data.find(i,f).a," ");
    writeln();
    }
    }

    gives

    {<7 "a" 3> <7 "b" 4> <7 "c" 9> <8 "a" 2> <8 "b" 3> <8 "c" 5>
    <9 "a" 1> <9 "b" 2> <9 "c" 7>}
    7 ==> 3 4 9
    8 ==> 2 3 5
    9 ==> 1 2 7


    ------------------------------
    ALEX FLEISCHER
    ------------------------------



  • 7.  RE: Initiating sets of tuples which contain arrays

    Posted Wed November 04, 2020 03:02 PM
    I've raised an Aha:

    https://ibm-data-and-ai.ideas.aha.io/ideas/CPLEX-I-105

    ------------------------------
    Andrew Bullock
    ------------------------------



  • 8.  RE: Initiating sets of tuples which contain arrays

    Posted Thu November 05, 2020 05:09 AM
    Alex

    Don't want to overdo this one, but perhaps a neater approach, given that we have to use ILOG Script until an enhancement comes in is this:

    tuple T_1 {
      key int i;
      int a;
      int b;
      int c;
    };
    {T_1} Input_Data={<7,3,4,9>,<8,2,3,5>,<9,1,2,7>};

    {string} Factors = {"a","b","c"};
    tuple T_2 {
      key int i;
      int a[Factors];
    };
    {T_2} Processed_Data;
    int Temp[Factors];

    execute FILL_PROCESSED_DATA {
      for(var x in Input_Data) Processed_Data.add(x.i,Temp); // Any further simple elements of a more extensive tuple would go in here as well
        for(var p in Processed_Data) {
          p.a["a"] = Input_Data.get(p.i).a;
          p.a["b"] = Input_Data.get(p.i).b;
          p.a["c"] = Input_Data.get(p.i).c;
      }
    }

    I tried to use the with() statement in the ILOG Script for the repeated Input_Data.get(p.i) to make it a bit neater, but this does not seem to work in the way specified in the help manual:

    "When a reference to an identifier name in statement is evaluated, this identifier is first looked up as a property of the default value; if the default value does not have such a property, name is treated as a regular variable."

    Where I have "does not have such a property" for the p.a["a"] it errors rather than treating this variable as a "regular variable". I might raise a support request on this.

    Anyway, I think we've reached a conclusion on this thread.

    Andrew

    ------------------------------
    Andrew Bullock
    ------------------------------