Catching exceptions
Exception handling for managing anomalies is a good programming practice when using CP Optimizer.
When programming an application, it is a good programming practice to enclose parts of your application in try-catch statements. In that way, when anomalies arise during execution, they can be managed as exceptions, so that your application can recover as cleanly as possible. You will find samples of try-catch statements in the examples distributed with CP Optimizer.
If you use try-catch statements, it is possible to distinguish
exceptions raised by CP Optimizer from exceptions raised by the rest
of the application. Specifically, when an error condition is encountered,
CP Optimizer raises an exception of type IloException. Your
application can catch these exceptions within try-catch statements,
and you can thus determine directly whether the anomaly arises within
the CP Optimizer part of your application or in another part of your
application. Here’s the conventional way to catch an error exception
from CP Optimizer in the C++ API:
catch (IloException& e) {
...
e.end();
}
The reference manual documents exceptions specific to IBM® ILOG® Concert Technology and CP Optimizer.
Catch exceptions by reference
Catch exceptions by reference, not by value, to avoid losing information and to prevent leaks from expressions or arrays.
In the C++ API, exception classes are not handle classes.
Thus, the correct type of an exception is lost if it is caught by
value rather than by reference (that is, using catch(IloException&
e) {...}). This is one reason that catching IloException objects
by reference is a good idea, as demonstrated in all the examples distributed
with CP Optimizer. Some derived exceptions may carry information that
would be lost if caught by value. So if you output an exception caught
by reference, you may get a more precise message than when outputting
the same exception caught by value.
There is a second reason for catching exceptions by reference.
Some exceptions contain arrays to communicate the reason for the failure
to the calling function. If this information were lost by calling
the exception by value, the method end could
not be called for such arrays, and their memory would be leaked (until env.end is called). After catching an exception
by reference, calling the end method of
the exception will free all the memory that may be used by arrays
(or expressions) of the actual exception that was thrown.
You can also control where warnings and error messages of the CP Optimizer part of your application are displayed. For example, during debugging, you might want all warning or error messages directed to your monitor, whereas when your application goes into production for use by customers, for example, you might want to direct warnings and error messages to a log file or some other discreet channel.
In the C++ API of Concert Technology, the class IloEnv initializes output streams for general information,
for error messages and for warnings. The class IloAlgorithm supports
these communication streams and the class IloCP inherits
its methods. For general output, there is the method IloAlgorithm::out.
For warnings and nonfatal conditions, there is the method IloAlgorithm::warning. For errors, there is the
method IloAlgorithm::error.
In the C++ API, an instance of IloEnv defines
the output stream referenced by the method out as the system cout in the C++ API, but you can use the method setOut to redefine it as you prefer. For example,
to suppress output to the screen in a C++ application, use this method
with this argument:
setOut(IloEnv::getNullStream())
Likewise, you can use the methods IloAlgorithm::setWarning and setError to redefine those channels as you prefer.
In the Microsoft .NET Framework languages and Java™ APIs, the native streams are used directly.