Topic
  • 9 replies
  • Latest Post - ‏2013-06-24T13:09:50Z by Philippe_Refalo
Hosssein
Hosssein
26 Posts

Pinned topic deleting logical expressions

‏2013-06-19T21:26:22Z |

Hi,

Could you please tell me how I can rewrite the following part of my code more efficient?

 

// W and S are variables

// D is a data matrix

IloNumExpr OBJECTIVE(*envvv,0);

for(i = 0; i < n; i++){

       for (j = 0; j < m; j++){

OBJECTIVE += (S[i]+D[W[i]]>j)&&(S[i]<j))* W[i];

       }            

}

Mysolve(); //It calls cp.next() in a function and solve a cp model with the objective function of OBJECTIVE.

for(i = 0; i < n; i++){

       for (j = 0; j < m; j++){

              ((S[i]+D[W[i]]>j)&&(S[i]<j)).end();

       }            

}

OBJECTIVE.end();

 

Actually I found out that when I delete OBJECTIVE, the part of memory related to the logical expression (S[i]+D[W[i]]>j)&&(S[i]<j)) is not deleted and I have to call "((S[i]+D[W[i]]>j)&&(S[i]<j)).end();" separately. The problem is that deleting the logical expression in this way is very time consuming.

Anybody has any idea how to write this code more efficient?

Updated on 2013-06-19T21:27:22Z at 2013-06-19T21:27:22Z by Hosssein
  • Philippe_Refalo
    Philippe_Refalo
    48 Posts
    ACCEPTED ANSWER

    Re: deleting logical expressions

    ‏2013-06-20T08:56:53Z  

    The problem is that you recreate an expression that you end in the loop after Mysolve(). You need to store them in an array and release them after. Moreover, in Concert, constraints as expressions like (S[i]+D[W[i]]>j) need to be release by directly calling end() on them because they are not considered as expressions. Consequently, your code does not release much of the original expression

    So here is a possible solution : 

    1. create (S[i]+D[W[i]]>j) and (S[i]<j) for each i, j and store them in two arrays.

    2. create OBJECTIVE from these arrays

    3. release OBJECTIVE

    4. release constraints in the 2 arrays one by one.

    Regards

    Philippe

     

     

     

    Philippe

  • rdumeur
    rdumeur
    102 Posts
    ACCEPTED ANSWER

    Re: deleting logical expressions

    ‏2013-06-20T09:30:58Z  

    Dear Hossein,

    First, doing ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]).end() doesn't actually delete the initial expression. It immediately deletes the newly ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]) created expression.

    If you actually need to delete the expression it would be safer to record each created ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]) expression element into an array and then delete each array element in reverse order after solve. For that, you can't use += on the objective expression.

      IloExtractableArray   record(env);
    // create expr recording array
      record.add(obj);
      for(i = 0; i < n; i++){
        for (j = 0; j < m; j++){
          IloNumExpr        eltdw(D[W[i]]);
          IloNumExpr        sum1(S[i]+eltdw);
          IloNumExpr        cmp1(sum1 > j);
          IloNumExpr        cmp2(S[i] < j);
          IloNumExpr        conj(cmp1 && cmp2);
          IloNumExpr        weight(conj * W[i]);
          IloNumExpr        newobj(OBJECTIVE + weight);
          record.add(eltw);
          record.add(sum1);
          record.add(cmp1);
          record.add(cmp2);
          record.add(conj);
          record.add(weight);
          record.add(newobj);
          OBJECTIVE = newobj;
       }         

    then after solve you can do :

    for(int i(record.getSize()-1); i >= 0; --i)
          record[i].end();  
    record.end(); // array no longer needed.

    Note that if you are doing very complex expressions that need to be later deleted, then it would be better to create your own  expression factory object (MyExprFactory) that would record each created expression:

    MyExprFactory       f(env); // create my factory object that owns a recording array
       OBJECTIVE = f.constant(0);
        for(i = 0; i < n; i++)
         for (j = 0; j < m; j++)
           OBJECTIVE = f.plus
              (OBJECTIVE, f.times
               (f.conjunction
                (f.gt
                 (f.plus
                  (S[i],f.element(D,W[j])), j),
                 f.lt(S[i], j)), W[i]));
        MySolve(OBJECTIVE);
        f.endCreatedExprs(); // destroy all the recorded exprs.

    I hope this helps.

    Cheers,

     

     

    Updated on 2013-06-20T09:37:28Z at 2013-06-20T09:37:28Z by rdumeur
  • Philippe_Refalo
    Philippe_Refalo
    48 Posts
    ACCEPTED ANSWER

    Re: deleting logical expressions

    ‏2013-06-24T13:09:50Z  
    • Hosssein
    • ‏2013-06-20T18:35:08Z

    Yes, it works now. Thank you.

    I can see that the following line is very time consuming in my code.

    for(int i=(record.getSize()-1); i >= 0; --i)
              record[i].end();  
     

    Is it possible to improve the time efficiency of this line?
     

    Unfortunately, I don't see any other way to free expressions memory. An option is to avoid deleting parts of the objective that you reuse. 

    Philippe

  • Philippe_Refalo
    Philippe_Refalo
    48 Posts

    Re: deleting logical expressions

    ‏2013-06-20T08:56:53Z  

    The problem is that you recreate an expression that you end in the loop after Mysolve(). You need to store them in an array and release them after. Moreover, in Concert, constraints as expressions like (S[i]+D[W[i]]>j) need to be release by directly calling end() on them because they are not considered as expressions. Consequently, your code does not release much of the original expression

    So here is a possible solution : 

    1. create (S[i]+D[W[i]]>j) and (S[i]<j) for each i, j and store them in two arrays.

    2. create OBJECTIVE from these arrays

    3. release OBJECTIVE

    4. release constraints in the 2 arrays one by one.

    Regards

    Philippe

     

     

     

    Philippe

  • rdumeur
    rdumeur
    102 Posts

    Re: deleting logical expressions

    ‏2013-06-20T09:30:58Z  

    Dear Hossein,

    First, doing ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]).end() doesn't actually delete the initial expression. It immediately deletes the newly ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]) created expression.

    If you actually need to delete the expression it would be safer to record each created ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]) expression element into an array and then delete each array element in reverse order after solve. For that, you can't use += on the objective expression.

      IloExtractableArray   record(env);
    // create expr recording array
      record.add(obj);
      for(i = 0; i < n; i++){
        for (j = 0; j < m; j++){
          IloNumExpr        eltdw(D[W[i]]);
          IloNumExpr        sum1(S[i]+eltdw);
          IloNumExpr        cmp1(sum1 > j);
          IloNumExpr        cmp2(S[i] < j);
          IloNumExpr        conj(cmp1 && cmp2);
          IloNumExpr        weight(conj * W[i]);
          IloNumExpr        newobj(OBJECTIVE + weight);
          record.add(eltw);
          record.add(sum1);
          record.add(cmp1);
          record.add(cmp2);
          record.add(conj);
          record.add(weight);
          record.add(newobj);
          OBJECTIVE = newobj;
       }         

    then after solve you can do :

    for(int i(record.getSize()-1); i >= 0; --i)
          record[i].end();  
    record.end(); // array no longer needed.

    Note that if you are doing very complex expressions that need to be later deleted, then it would be better to create your own  expression factory object (MyExprFactory) that would record each created expression:

    MyExprFactory       f(env); // create my factory object that owns a recording array
       OBJECTIVE = f.constant(0);
        for(i = 0; i < n; i++)
         for (j = 0; j < m; j++)
           OBJECTIVE = f.plus
              (OBJECTIVE, f.times
               (f.conjunction
                (f.gt
                 (f.plus
                  (S[i],f.element(D,W[j])), j),
                 f.lt(S[i], j)), W[i]));
        MySolve(OBJECTIVE);
        f.endCreatedExprs(); // destroy all the recorded exprs.

    I hope this helps.

    Cheers,

     

     

    Updated on 2013-06-20T09:37:28Z at 2013-06-20T09:37:28Z by rdumeur
  • Hosssein
    Hosssein
    26 Posts

    Re: deleting logical expressions

    ‏2013-06-20T17:26:53Z  
    • rdumeur
    • ‏2013-06-20T09:30:58Z

    Dear Hossein,

    First, doing ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]).end() doesn't actually delete the initial expression. It immediately deletes the newly ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]) created expression.

    If you actually need to delete the expression it would be safer to record each created ((S[i]+D[W[i]]>j)&&(S[i]<j))* W[i]) expression element into an array and then delete each array element in reverse order after solve. For that, you can't use += on the objective expression.

      IloExtractableArray   record(env);
    // create expr recording array
      record.add(obj);
      for(i = 0; i < n; i++){
        for (j = 0; j < m; j++){
          IloNumExpr        eltdw(D[W[i]]);
          IloNumExpr        sum1(S[i]+eltdw);
          IloNumExpr        cmp1(sum1 > j);
          IloNumExpr        cmp2(S[i] < j);
          IloNumExpr        conj(cmp1 && cmp2);
          IloNumExpr        weight(conj * W[i]);
          IloNumExpr        newobj(OBJECTIVE + weight);
          record.add(eltw);
          record.add(sum1);
          record.add(cmp1);
          record.add(cmp2);
          record.add(conj);
          record.add(weight);
          record.add(newobj);
          OBJECTIVE = newobj;
       }         

    then after solve you can do :

    for(int i(record.getSize()-1); i >= 0; --i)
          record[i].end();  
    record.end(); // array no longer needed.

    Note that if you are doing very complex expressions that need to be later deleted, then it would be better to create your own  expression factory object (MyExprFactory) that would record each created expression:

    MyExprFactory       f(env); // create my factory object that owns a recording array
       OBJECTIVE = f.constant(0);
        for(i = 0; i < n; i++)
         for (j = 0; j < m; j++)
           OBJECTIVE = f.plus
              (OBJECTIVE, f.times
               (f.conjunction
                (f.gt
                 (f.plus
                  (S[i],f.element(D,W[j])), j),
                 f.lt(S[i], j)), W[i]));
        MySolve(OBJECTIVE);
        f.endCreatedExprs(); // destroy all the recorded exprs.

    I hope this helps.

    Cheers,

     

     

    Thank you so much for your replies.
    I face with an error on operator "&&" in line " IloNumExpr        conj(cmp1 && cmp2);".

    Error: No operator && matches these operands. Could you please tell me what I can do to handle it?

    Moreover, I can see you are adding some elements to record array and finally delete it without using the array. Maybe I am missing something.

  • Hosssein
    Hosssein
    26 Posts

    Re: deleting logical expressions

    ‏2013-06-20T17:48:29Z  

    The problem is that you recreate an expression that you end in the loop after Mysolve(). You need to store them in an array and release them after. Moreover, in Concert, constraints as expressions like (S[i]+D[W[i]]>j) need to be release by directly calling end() on them because they are not considered as expressions. Consequently, your code does not release much of the original expression

    So here is a possible solution : 

    1. create (S[i]+D[W[i]]>j) and (S[i]<j) for each i, j and store them in two arrays.

    2. create OBJECTIVE from these arrays

    3. release OBJECTIVE

    4. release constraints in the 2 arrays one by one.

    Regards

    Philippe

     

     

     

    Philippe

    Hi,

    Thank you for your reply. Actually, I cannot use operator && to link (S[i]+D[W[i]]>j) and (S[i]<j) from the array.

    IloNumExprArray   record(env);

    IloNumExpr OBJECTIVE(env,0);
    for(i = 0; i < n; i++){
         for (j = 0; j < m; j++){
             record.add(-(S[i]+DDurations[W[i]]>j));
             record.add((S[i]<j));
             OBJECTIVE += record[record.getSize()-1] && record[record.getSize()-2]; // I get an error on operator && in this line
          }  
    }

     

    Mysolve();

     

    for(int i=(record.getSize()-1); i >= 0; --i)
              record[i].end();  
    record.end();
    OBJECTIVE.end();

     

    Is there any way to handle it?

    Updated on 2013-06-20T18:14:05Z at 2013-06-20T18:14:05Z by Hosssein
  • Philippe_Refalo
    Philippe_Refalo
    48 Posts

    Re: deleting logical expressions

    ‏2013-06-20T18:16:07Z  
    • Hosssein
    • ‏2013-06-20T17:48:29Z

    Hi,

    Thank you for your reply. Actually, I cannot use operator && to link (S[i]+D[W[i]]>j) and (S[i]<j) from the array.

    IloNumExprArray   record(env);

    IloNumExpr OBJECTIVE(env,0);
    for(i = 0; i < n; i++){
         for (j = 0; j < m; j++){
             record.add(-(S[i]+DDurations[W[i]]>j));
             record.add((S[i]<j));
             OBJECTIVE += record[record.getSize()-1] && record[record.getSize()-2]; // I get an error on operator && in this line
          }  
    }

     

    Mysolve();

     

    for(int i=(record.getSize()-1); i >= 0; --i)
              record[i].end();  
    record.end();
    OBJECTIVE.end();

     

    Is there any way to handle it?

    You need to use IloConstraintArray to store the constraints. Then the operator && will be accepted.

    Philippe

  • Hosssein
    Hosssein
    26 Posts

    Re: deleting logical expressions

    ‏2013-06-20T18:35:08Z  

    You need to use IloConstraintArray to store the constraints. Then the operator && will be accepted.

    Philippe

    Yes, it works now. Thank you.

    I can see that the following line is very time consuming in my code.

    for(int i=(record.getSize()-1); i >= 0; --i)
              record[i].end();  
     

    Is it possible to improve the time efficiency of this line?
     

  • rdumeur
    rdumeur
    102 Posts

    Re: deleting logical expressions

    ‏2013-06-21T09:51:19Z  
    • Hosssein
    • ‏2013-06-20T17:26:53Z

    Thank you so much for your replies.
    I face with an error on operator "&&" in line " IloNumExpr        conj(cmp1 && cmp2);".

    Error: No operator && matches these operands. Could you please tell me what I can do to handle it?

    Moreover, I can see you are adding some elements to record array and finally delete it without using the array. Maybe I am missing something.

    Dear Hossein

    Indeed I think the type is not correct. All relational and logical expressions should be IloBoolExpr handles.

    Concerning array deletion. As said in my message, *after solve*, the array is used to destroy all the created expressions by calling record[i].end().

    Why do you think it is not used?

    Cheers,

     

  • Hosssein
    Hosssein
    26 Posts

    Re: deleting logical expressions

    ‏2013-06-21T15:11:51Z  
    • rdumeur
    • ‏2013-06-21T09:51:19Z

    Dear Hossein

    Indeed I think the type is not correct. All relational and logical expressions should be IloBoolExpr handles.

    Concerning array deletion. As said in my message, *after solve*, the array is used to destroy all the created expressions by calling record[i].end().

    Why do you think it is not used?

    Cheers,

     

    OK. I got it. Thank you so much.
    I tested it. Actually, since the objective is very huge, it is very time consuming to delete it at each iteration. So I have asked another related question in the forum. Could you please help me?

    I am solving a CP model iteratively with same variables and constraints but different objective functions. The structure of the objective function does not change. The only things that change, from an iteration to the next, are the data arrays based on which the objective function is created in each iteration.

    In my current implementation, in each iteration I delete the previous objective function and add a new objective function with new data arrays which is very time consuming.  Actually the objective is very huge and its deletion is the source of long run time.

    Is it possible just to change the data arrays in each iteration inside of the objective expression to correct the objective function rather than deleting the previous objective function and adding the new objective function?

    An example of such objective function is as follows:

    // W and S are variables
    // D, P and L are data arrays
    for (i = 0; i < n; i++){
           for (j = 0; j < m; j++){
                   // D, P and L are updated at this line
                   OBJECTIVE = -((S[i]+D[W[i]]>j)&&(S[i]<j))*P[L[W[i]]*j];
                   //CP model is solved at this line
                   OBJECTIVE.end();
           }
    }
  • Philippe_Refalo
    Philippe_Refalo
    48 Posts

    Re: deleting logical expressions

    ‏2013-06-24T13:09:50Z  
    • Hosssein
    • ‏2013-06-20T18:35:08Z

    Yes, it works now. Thank you.

    I can see that the following line is very time consuming in my code.

    for(int i=(record.getSize()-1); i >= 0; --i)
              record[i].end();  
     

    Is it possible to improve the time efficiency of this line?
     

    Unfortunately, I don't see any other way to free expressions memory. An option is to avoid deleting parts of the objective that you reuse. 

    Philippe