Decision Optimization

 View Only
  • 1.  CPLEX C++ Add columns to a deep copy of an IloModel

    Posted Mon October 09, 2023 12:59 PM

    i used the code of user Marko Reclic to create a deep copy of an IloModel.

    IloEnv testenv;
    IloModel testmodel(testenv);
    IloCplex testcplex(testmodel);
    
    IloNumVarArray x = CreateNumVarArray(testenv, 2, "x", 0, 1);
    IloObjective testobj = IloMaximize(testenv, IloSum(x));
    testmodel.add(testobj);
    IloRangeArray cnstr = CreateRangeArray(testenv, 3, "c");
    for (int i = 0; i < cnstr.getSize(); i++) {
        cnstr[i].setLinearCoef(x[0], (3 - i) + 2);
        cnstr[i].setLinearCoef(x[1], i * 3 + 1);
        cnstr[i].setUB(10 * (5 - i) - 2);
    }
    testmodel.add(cnstr);
    IloModel testmodel1(testenv);
    for (IloModel::Iterator it(testmodel); it.ok(); ++it)
        testmodel1.add(*it);
    

    My question is how to add new columns to testmodel1. For testmodel i would use the following code. I don't know what to apply for testmodel1.

    IloNumColumn col(testenv);
    col += testobj(22);
    for (int i = 0; i < cnstr.getSize(); ++i) {
        col += cnstr[i](i * 3 + 5);
    }
    x.add(IloNumVar(col, 0, 1, ILOFLOAT));


    ------------------------------
    ozan aksu
    ------------------------------


  • 2.  RE: CPLEX C++ Add columns to a deep copy of an IloModel

    Posted Tue October 10, 2023 06:08 AM

    Dear Ozan,

    My understanding of your code is that by iterating over the `testmodel` entities, you are creating a shallow copy of the model (not a deep copy). This means that both models are then updated when a new column is added.

    Anyway, trying to clone and edit a model can be confusing and lead to unnecessary complications. I would rather advice to wrap the creation of your model in a function, and then invoking this function a second time to create a new instance of the model.

    Best regards,



    ------------------------------
    Hugues Juille
    ------------------------------



  • 3.  RE: CPLEX C++ Add columns to a deep copy of an IloModel

    Posted Fri October 13, 2023 03:54 PM

    Dear Hugues

    Thank you for your reply. I think i am creating a deep model because adding new constraints to the copy does not affect the original model:

    IloRangeArray cnstr1 = CreateRangeArray; 
    testmodel1.add(cnstr1);

    However adding columns only to testmodel1 is not possible:

    IloNumColumn col(testenv);
    col += testobj(int);
    for (int i = 0; i < cnstr.getSize(); ++i) {
        col += cnstr[i](int);
    }
    IloNumVar newVar(col, 0, 1, ILOFLOAT);
    testmodel1.add(newVar);
    

    This is probably because I don't have copies of IloObjective and IloRangeArray. How can i create those copies? Or in general how can i add new columns to testmodel1 without modifying testmodel?



    ------------------------------
    ozan aksu
    ------------------------------



  • 4.  RE: CPLEX C++ Add columns to a deep copy of an IloModel

    Posted Mon October 16, 2023 06:26 AM

    Dear Ozan,

    I'm still confused about the "deep copy" snippet...
    I did a simple experiment where I edited "cnstr" in "testmodel" (duplicating the same loop, but using different values for the coefs) AFTER "testmodel1" has been created using the iterator over IloModel entities.
    Then, I displayed both models as follows:

            IloModel testmodel1(testenv);
            for (IloModel::Iterator it(testmodel); it.ok(); ++it) {
                testmodel1.add(*it);
            }
            testenv.out() << "=========================================" << std::endl;
    
            for (int i = 0; i < cnstr.getSize(); i++) {
                cnstr[i].setLinearCoef(x[0], (6 - i) + 2);  // Arbitrary updates to original constraints...
                cnstr[i].setLinearCoef(x[1], i * 11 + 1);
                cnstr[i].setUB(10 * (49 - i) - 2);
            }
            testenv.out() << "=========================================" << std::endl;
    
            for (IloModel::Iterator it(testmodel); it.ok(); ++it) {
                IloExtractable e = *it;
                testenv.out() << "TestModel : " << e << std::endl;
            }
    
            for (IloModel::Iterator it(testmodel1); it.ok(); ++it) {
                IloExtractable e = *it;
                testenv.out() << "TestModel1 : " << e << std::endl;
            }

    The same information is displayed for both models, meaning that a shallow copy was performed, not a deep copy.

    Could you replicate the experiment on your side ?

    Is performing a deep copy of the model the only possibility in your application ? Wouldn't it be better to just recreate a new model from scratch for testmodel1 ?

    Best regards,



    ------------------------------
    Hugues Juille
    ------------------------------



  • 5.  RE: CPLEX C++ Add columns to a deep copy of an IloModel

    Posted Mon October 16, 2023 08:21 AM

    Dear Hugues,

    With the code i posted, i was able to add additional constraints to testmodel1 without modifying testmodel. This made me believe that it might be a deep copy. But obviously it was not 100% (if that's even possible).

    For now following your advise seems to be the clever one. I use getExpr to recreate the equations.

    Maybe different using environments would somehow isolate the models, dont know yet.

    Best regards



    ------------------------------
    ozan aksu
    ------------------------------