Decision Optimization

Decision Optimization

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


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
  • 1.  How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/18/11 10:30 PM

    Originally posted by: duyuquan2006


    Hi all,

    I try to use the STL function "max_element" towards an IloNumArray object in C++ (MS VS 2008),with the following codes,

    #include <algorithm>
       ...
       ...
       IloNumArray X;
       X.add(3);
       X.add(5);
       X.add(1);
       X.add(6);
       X.add(4);
       IloNum d = *max_element(X,X+X.getSize());
       IloNum d_pos = max_element(X,X+X.getSize())-X;
       cout<<"d="<<d<<" pos="<<d_pos<<endl;
    


    It didn't work. So could you pls show me how to use "max_element" towards an IloNumArray object?

    Many thanks!

    Bst rgrds!

    Yuquan
    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/18/11 11:38 PM

    Originally posted by: duyuquan2006


    1. I got a awkward work-around. I defined a function to convert IloNumArray to vector<IloNum>, and used "max_element" towards a vector<IloNum> object instead of a IloNumArray object. See the following codes:
    typedef vector<IloNum> ILNVECTOR;
       ILNVECTOR INA2INV(IloNumArray& in_array)
       {
            ILNVECTOR out_vector;
            for (int i = 0;i < in_array.getSize();i++)
            {
                    out_vector.push_back(in_array[i]);
            }
            return out_vector;
       }
       ...
       ...
       IloNumArray X(env);
       X.add(3);
       X.add(5);
       X.add(1);
       X.add(6);
       X.add(4);
       ILNVECTOR Y = INA2INV(X);
       for (int i = 0;i<Y.size();i++)
       {
               cout<<Y[i]<<endl;
       }
       IloNum d=*max_element(Y.begin(),Y.end());
       IloNum d_pos=max_element(Y.begin(),Y.end())-Y.begin();
       cout<<"d="<<d<<"d_pos="<<d_pos<<endl;
    


    However, do u have a more elegant method to use "max_element" towards an IloNumArray object?

    2. I began to think why "IloNumArray" exists,since "vector<IloNum>" is more powerful.
    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/19/11 03:28 AM

    Originally posted by: SystemAdmin


    Containers like IloNumArray were introduced to the Concert API a long time ago. At this time not all compilers/platforms had support for STL.
    They are also different from STL containers as they are only handle-classes. This means that they do not actually hold the data but only a handle to that data. I.e., the IloXXXArray classes are only reference to the real data. Consequently, some code like this
    
    IloNumArray X(env); X.add(1); X.add(2); X.add(3); X.add(4); IloNumArray Y = X; std::cout << 
    "X: " << X << std::endl << 
    "Y: " << Y << std::endl; X.remove(0); std::cout << 
    "X: " << X << std::endl << 
    "Y: " << Y << std::endl;
    

    will always have the same output for X and Y. The operator= does not create a deep copy of the array. Instead it just creates a copy of the reference to the real data.

    As you have noticed by now, the IloXXXArray classes are not compatible with the STL algorithms, mainly because they do not provide iterators and almost all STL algorithms are based on iterators. Instead of writing a function that converts an IloNumArray to a vector you should either write your own version of max_element() for IloNumArray or implement an iterator for that class. For example, the following minimalistic implementation does work:
    
    #include <vector> #include <iostream> #include <algorithm> #include <ilcplex/ilocplex.h>   
    /** An iterator for IloNumArray instances. * The implementation assumes that you never mix iterators for different * arrays. */ 
    
    class IloNumArrayIterator 
    { IloNumArray array; IloInt pos; 
    
    public: IloNumArrayIterator(IloNumArray const& a) : array(a), pos(0) 
    {
    } IloNumArrayIterator(IloNumArray const& a, IloInt p) : array(a), pos(p) 
    {
    } bool operator!=(IloNumArrayIterator it) 
    
    const 
    { 
    
    return pos != it.pos; 
    } bool operator==(IloNumArrayIterator it) 
    
    const 
    { 
    
    return pos == it.pos; 
    } IloNum operator*() 
    
    const 
    { 
    
    return array[pos]; 
    } IloNumArrayIterator& operator++() 
    { ++pos; 
    
    return *
    
    this; 
    } 
    };   
    
    int main(
    
    void) 
    { IloEnv env;   IloNumArray X(env); X.add(3); X.add(5); X.add(1); X.add(6); X.add(4);   std::cout << 
    "Max element: " << *std::max_element(IloNumArrayIterator(X), IloNumArrayIterator(X, X.getSize())) << std::endl; 
    
    return 0; 
    }
    

    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/19/11 03:36 AM

    Originally posted by: SystemAdmin


    Addendum: A way to invoke max_element() without having to create any additional would be
    std::cout << "Max element: "
              << *std::max_element(&X[0], &X[0] + X.getSize())
              << std::endl;
    

    But this relies on the implementation detail that IloNumArray keeps the data in one flat array. This is not likely to change but there is of course no guarantee.
    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/19/11 04:18 AM

    Originally posted by: duyuquan2006


    I like the latter approach you provided. You showed me the technical key is: &X[0] can retrieve the address 0 of X (For a common C++ array,"X" or "X[0]" is OK).I also tested it with the STL function "count_if",and it really worked. So we can always use all the algorithmic functions in <algorithm>.

    Thank u so much,Daniel!

    I will post this approach in my blog(http://blog.sina.com.cn/duyuquan).

    Bst rgrds!

    Yuquan
    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/19/11 01:52 PM

    Originally posted by: SystemAdmin


    I just checked. IloXXXArray does not necessarily store its data in a flat array. This means that what I suggested in my second post is risky. In order to be safe you should implement your own iterator.
    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/20/11 02:44 AM

    Originally posted by: duyuquan2006


    Hi Daniel,

    When I used the "&X[0]" method, I found a weird instance. By the following code, the position of the element "4" should be 4. However, the output is 5.
    IloNumArray X(env);
       X.add(3);
       X.add(5);
       X.add(1);
       X.add(6);
       X.add(4);
       cout<<"X="<<X<<endl;
       int pos1= find(&X[0],&X[0]+X.getSize(),3)-&X[0];
       cout<<"3 is at "<<pos1<<endl;
       int pos2= find(&X[0],&X[0]+X.getSize(),5)-&X[0];
       cout<<"5 is at "<<pos2<<endl;
       int pos3= find(&X[0],&X[0]+X.getSize(),1)-&X[0];
       cout<<"1 is at "<<pos3<<endl;
       int pos4= find(&X[0],&X[0]+X.getSize(),6)-&X[0];
       cout<<"6 is at "<<pos4<<endl;
       int pos5= find(&X[0],&X[0]+X.getSize(),4)-&X[0];
       cout<<"4 is at "<<pos5<<endl;
    

    The output is:
    X=[3, 5, 1, 6, 4]
    3 is at 0
    5 is at 1
    1 is at 2
    6 is at 3
    4 is at 5
    

    Could u pls explain this? or I made some mistake?

    Thanks.

    Yuquan
    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/20/11 02:52 AM

    Originally posted by: SystemAdmin


    This is most probably due to the fact that IloArray<X> does not store its data in a flat array. Instead it stores the data in an array of arrays (for performance reasons). You can see that by inspecting the implementation of IloArrayI in the header file.
    This means that the approach using '&X[0]' and then doing pointer arithmetic will not work in the majority of cases (as I warned in this post). I think in order to get the STL functions working in a safe and reliable way you have to implement the iterator as described here.
    #CPLEXOptimizers
    #DecisionOptimization


  • 9.  Re: How to use the STL function "max_element" towards an IloNumArray object?

    Posted 12/20/11 03:14 AM

    Originally posted by: duyuquan2006


    Hi Daniel,

    Thanks for your prompt reply. Indeed, I use the STL algorithmic functions when I modeling my problem, for processing the read data. I do NOT care much about the modeling performance (I instead care the solving performance). So I prefer to temporarily convert an IloNumArray object to a vector<IloNum> object before I use the STL functions.

    Thank u so much!

    Yuquan
    #CPLEXOptimizers
    #DecisionOptimization