Overview | Group | Tree | Graph | Index | Concepts |
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
IloEnv::setDeleter(IloLinearDeleterMode)
, orIloEnv::setDeleter()
, as it is the default mode.In linear mode, the following behavior is implemented:
0
in the ranges,
expressions, and objectives where it appears. The variable is removed from the
SOS1
, SOS2
, and IloConversion
where it appears.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:
IloEnv::setDeleter(IloSafeDeleterMode)
, and#include <ilconcert/ilodeleter.h>
to your
program.In this mode, the environment builds a dependency graph between all extractables. This graph contains all extractables created
IloEnv::setDeleter(IloSafeDeleterMode)
and IloEnv::unsetDeleter()
.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.
con
must appear
before the variable x
as it will be deleted before the variable
x
.