FRAMES NO FRAMES

Deletion of Extractables
PREVIOUS NEXT

As a modeling layer, Concert allows the creation and destruction of extractables. This is accessible through the method IloExtractable::end() and IloExtractableArray::endElements() method. The goal 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; this is referred to as a dangling pointer in C++.

There exist two paradigms to ensure the safeness of the delete operation. The first, linear mode, comes from math programming and is possible only on extractables and objects used in linear programming. The second, safe generic mode, is more strict and is valid on all Concert extractables.

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 extractables. This graph contains all extractables 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.

We recommended that you create this graph just after the creation of the environment and that you refrain from using IloEnv::unsetDeleter. We make these recommendations because building an incomplete dependency graph is very error prone and should only be attempted by advanced users. A good 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 uses extractable xi. If this is not the case, a call to IloExtractable::end() will throw an exception IloDeleter::RequiresAnotherDeletionException indicating which extractable uses the extractable that you want to delete.

Example

This example shows an attempt to delete one extractable 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, you should use the IloExtractableArray::endElements() method. With this method, all extractables appearing in the array are deleted one after another. Thus, if an extractable is used by another extractable and this other extractable 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();
  }
  

The example will not throw an exception.

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