Decision Optimization

Decision Optimization

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

 View Only

A little more about generic indexed array in OPL

  • 1.  A little more about generic indexed array in OPL

    Posted Thu January 24, 2019 06:10 AM

    Hi,

    answering https://www.ibm.com/developerworks/community/forums/html/topic?id=6738f835-063c-4496-ad87-8946bac15ed7&ps=25

    reminded me that each time I taught OPL for 13 years, when I described generic indexed arrays I lost eye contact with the audience and was never sure anybody got the idea.

    This is of course described quite well in OPL documentation : https://www.ibm.com/support/knowledgecenter/SSSA5P_12.8.0/ilog.odms.ide.help/OPL_Studio/opllangref/topics/opl_langref_data_init_arrays.html

    The examples there are:

    
    int a[1..10] = [ i-1 : i | i in 2..11 ]; 
    int m[0..10][0..10] = [ i : [ j : 10*i+j ] | i,j in 0..10 ];
    

    But let me add some more and explain why generic indexed array are useful.

    A tiny example where I need to compute the latest y for a given x

    tuple t
    {
    key int x;
    int y;
    }

    {t} s={<1,2>,<2,1>,<3,2>};

    int lastxfory[1..2]=[i.y : i.x | i in s];

    int lastxfory_through_slicing[y in 1..2]=last({i.x | i in s : i.y==y});

    int lastxfory_through_scripting[1..2];

    execute
    {
    for(var i in s) lastxfory_through_scripting[i.y]=i.x;
    }


    execute
    {
    writeln("lastxfory = ",lastxfory);
    writeln("lastxfory_through_slicing = ",lastxfory_through_slicing);
    writeln("lastxfory_through_scripting = ",lastxfory_through_scripting);
    }

    gives

    lastxfory =  [2 3]
    lastxfory_through_slicing =  [2 3]
    lastxfory_through_scripting =  [2 3]

    and shows how generic indexed arrays, slicing and scripting provide the same results.

     

    The slicing way could be seen as easier to read but its time complexity is the square of the size of the set. Scripting has a linear complexity but is not as fast as OPL

     

    Let's see that with a bigger example:

    int scale=10000000;

    tuple t
    {
    key int x;
    int y;
    }

    {t} s={<i,1+rand(scale)> | i in 1..scale};

    execute
    {
    s;
    }

    int lastxfory[1..scale]=[i.y : i.x | i in s];

    {int} xFory[y in 1..scale]={i.x | i in s : i.y==y};
    int lastxfory_through_slicing[y in 1..scale]=(card(xFory[y])==0)?0:last(xFory[y]);

    int lastxfory_through_scripting[1..scale];

    execute generic
    {
    var d1=new Date();
    lastxfory;
    var d2=new Date();
    writeln("time generic = ",d2-d1);
    }

    execute slicing
    {
    var d1=new Date();
    lastxfory_through_slicing;
    var d2=new Date();
    writeln("time slicing = ",d2-d1);
    }

    execute scripting
    {
    var d1=new Date();
    for(var i in s) lastxfory_through_scripting[i.y]=i.x;
    var d2=new Date();
    writeln("time scripting = ",d2-d1);
    }

     

    assert forall(i in 1..scale)
    lastxfory_through_slicing[i]==lastxfory[i];

    assert forall(i in 1..scale)
    lastxfory_through_scripting[i]==lastxfory[i];

    which gives

    time generic = 2611
    time slicing = 95879
    time scripting = 15093

    where we can see that generic indexed array is the best way.

    I hope this helps.

     

    regards

     

    https://www.linkedin.com/pulse/making-decision-optimization-simple-alex-fleischer/

     

     

     

     


    #DecisionOptimization
    #OPLusingCPLEXOptimizer