Skip to main content
FRAMES NO FRAMES

Deletion of Extractable Objects in CPLEX
PREVIOUS NEXT

As a modeling layer, Concert allows the creation and destruction of extractables through the methods IloExtractable::end and IloExtractableArray::endElements. The purpose of these methods is to reclaim memory associated with the deleted objects while maintaining the safest possible Concert environment. In this context, a safe Concert environment is defined by the property that no object points to a deleted object; a pointer to a deleted object is referred to as a dangling pointer in C++.

There exist two paradigms to make sure of the safety of the delete operation. The first, linear mode, comes from math programming; in a Concert application, linear mode is possible only on extractable and other objects used in linear programming. The second, safe generic mode, is stricter and is valid on all Concert extractable objects.

You can access both paradigms by calling IloEnv::setDeleter(IloDeleterMode mode), where mode may be IloLinearDeleterMode or IloSafeDeleterMode.

Linear Mode

To use linear mode, you must either

In linear mode, the following behavior is implemented:

Example

This example tests the linear mode deletion of a variable x.

  void TestLinearDeleter() {
    IloEnv env;
    env.out() << "TestLinearDeleter" << endl;
    try {
      IloModel model(env);
      IloNumVar x(env, 0, 10, "x");
      IloNumVar y(env, 0, 10, "y");
      IloConstraint con = (x + y <= 0);
      IloConstraint con2 = y >= 6;
      IloNumVarArray ar(env, 2, x, y);
      IloSOS1 sos(env, ar, "sos");
      model.add(con);
      model.add(con2);
      model.add(sos);
      env.out() << "Before Delete" << endl;
      env.out() << model << endl;
      x.end();
      con2.end();
      env.out() << "After Delete" << endl;
      env.out() << model << endl;    
    } catch (IloException& e) {
      cout << "Error : " << e << endl;
    }
    env.end();
  }
  

The example produces the following output:

  TestLinearDeleter
  Before Delete
  IloModel model0 = {
  IloRange rng3(    1 * x + 1 * y ) <= 0
  
  IloRange rng46 <=(    1 * y )
  
  IloSOS1I (sos)
    _varArray [x(F)[0..10], y(F)[0..10]]
    _valArray []
      
  }
  
  After Delete  
  IloModel model0 = {
  IloRange rng3(    1 * y ) <= 0
  
  IloSOS1I (sos)
    _varArray [y(F)[0..10]]
    _valArray []
  }

Safe Generic Mode

To use safe generic mode, you must:

In this mode, the environment builds a dependency graph between all extractable objects. This graph contains all extractable objects created

Objects not managed by this dependency graph are referred to here as "nondeletable". An attempt to delete a nondeletable object will throw an exception.

It is recommended that you create this graph just after the creation of the environment and that you refrain from using IloEnv::unsetDeleter because building an incomplete dependency graph is very error prone and should only be attempted by advanced users. A clear example of this incomplete graph is the separation of a model between a nondeletable base model and deletable extensions of this base model.

Calling IloExtractable::end on extractable xi will succeed only if no other extractable object uses extractable xi. If this is not the case, a call to IloExtractable::end will throw an exception IloDeleter::RequiresAnotherDeletionException indicating which extractable object uses the extractable object that you want to delete.

Example

This example shows an attempt to delete one extractable object that is used by another.

  
  void TestSafeDeleter() {
    IloEnv env;
    env.out() << "TestSafeDeleter" << endl;
    env.setDeleter(IloSafeDeleterMode);
    try {
      IloModel model(env);
      IloNumVar x(env, 0, 10);
      IloNumVar y(env, 0, 10);
      IloConstraint con = (x + y <= 0);
      try {
        x.end();
      } catch (IloDeleter::RequiresAnotherDeletionException &e) {
        cout << "Caught " << e << endl;
        e.getUsers()[0].end();
        e.end();
      }
      x.end();
    } catch (IloException& e) {
      cout << "Error : " << e << endl;
    }
    env.unsetDeleter();
    env.end();
  }
  

The example produces the following output:

  TestSafeDeleter
  Caught You cannot end x1(F)[0..10] before IloRange rng3(  1 * x1 + 1 * x2  ) <= 0
  

To address this situation, you should use the method IloExtractableArray::endElements. With this method, all extractable objects in the array are deleted one after another. Thus, if an extractable object is used by another extractable object and this other extractable object is deleted before the first one, the system will not complain and will not throw an exception.

Example

This example illustrates the use of the endElements method

  
  void TestSafeDeleterWithArray() {
    IloEnv env;
    env.out() << "TestSafeDeleterWithArray" << endl;
    env.setDeleter(IloSafeDeleterMode);
    try {
      IloModel model(env);
      IloNumVar x(env, 0, 10);
      IloNumVar y(env, 0, 10);
      IloConstraint con = (x + y <= 0);
      IloExtractableArray ar(env, 2, con, x);
      ar.endElements();
    } catch (IloException& e) {
      cout << "Error : " << e << endl;
    }
    env.unsetDeleter();
    env.end();
  }
  

That example will not throw an exception.

Note
In this last example, the constraint con must appear before the variable x as it will be deleted before the variable x.
PREVIOUS NEXT