How to add dialogs SCIP comes with a command line shell which allows the user to read in problem instances, modify the solver's parameters, initiate the optimization and display certain statistics and solution information. This shell consists of dialogs, which are organized as a tree in SCIP. A node of this tree which is not a leaf represents a menu in the shell and the children of this node correspond to the entries of this menu (which can again be menus). All different dialogs are managed by a dialog handler, which, in particular, is responsible for executing the dialog corresponding to the user's command in the shell. The concept of a dialog handler is different to that of a constraint handler, which is used to manage objects of the same structure, see How to add constraint handlers. In particular, SCIP features only one dialog handler (dialog_default.h), whereas there may exist different constraint handlers. We now explain how users can extend the interactive shell by adding their own dialog. We give the explanation for creating your own source file for each additional dialog. Of course, you can collect different dialogs in one source file. Take src/scip/dialog_default.c, where all default dialog plugins are collected, as an example. As all other default plugins, the default dialog plugin and the template dialog are written in C. C++ users can easily adapt the code by using the scip::ObjDialog wrapper base class and implement the scip_...() virtual methods instead of the SCIP_DECL_DIALOG... callback methods. Additional documentation for the callback methods of a dialog can be found in the file type_dialog.h. Here is what you have to do to add a dialog (assuming your dialog is named "mydialog"):
Properties of a DialogAt the top of the new file "dialog_mydialog.c" you can find the dialog properties. These are given as compiler defines. In the C++ wrapper class, you have to provide the dialog properties by calling the constructor of the abstract base class scip::ObjDialog from within your constructor. The properties you have to set have the following meaning:
Dialog DataBelow the header "Data structures" you can find a struct which is called "struct SCIP_DialogData". In this data structure, you can store the data of your dialog. If you are using C++, you can add dialog data as usual as object variables to your class. Interface MethodsAt the bottom of "dialog_mydialog.c" you can find the interface method SCIPincludeDialogMydialog(), which also appears in "dialog_mydialog.h". if( !SCIPdialogHasEntry(parentdialog, DIALOG_NAME) ) { SCIP_CALL( SCIPcreateDialog(scip, &dialog, dialogExecMydialog, dialogDescMydialog, dialogFreeMydialog, DIALOG_NAME, DIALOG_DESC, DIALOG_ISSUBMENU, dialogdata) ); SCIP_CALL( SCIPaddDialogEntry(scip, parentdialog, dialog) ); SCIP_CALL( SCIPreleaseDialog(scip, &dialog) ); } Here "parentdialog" has to be an existing dialog which is defined to be a menu (see DIALOG_ISSUBMENU), e.g., the default root dialog. The method SCIPgetRootDialog() returns the root dialog. The interface method is called by the user, if (s)he wants to include the dialog, i.e., if (s)he wants to use the dialog in his/her application. Note that in order to be able to link the new dialog to an existing default dialog (except the root dialog) it has to be included after the default dialogs plugin, i.e., the SCIPincludeDialogMydialog() call has to occur after the SCIPincludeDialogDefault() call. The SCIPincludeDialogDefault() method is called from within the SCIPincludeDefaultPlugins() method. Therefore, it suffices to include your dialog plugins after you have called SCIPincludeDefaultPlugins(). In case you want to add a dialog to the root dialog, you just use the following lines of code to get/create the root dialog. SCIP_DIALOG* root; root = SCIPgetRootDialog(scip); if( root == NULL ) { SCIP_CALL( SCIPcreateRootDialog(scip, &root) ); } assert( root != NULL ); Therefore, in this case you do not have to worry about the calls of SCIPincludeDialogDefault() and SCIPincludeDefaultPlugins() . If you are using dialog data, you have to allocate the memory for the data at this point. You can do this by calling: SCIP_CALL( SCIPallocMemory(scip, &dialogdata) ); You also have to initialize the fields in struct SCIP_DialogData afterwards. Consider the following example. The user wants to add a "drawgraph" command to the root menu of SCIP. (S)he copies the "dialog_xyz.c" and "dialog_xyz.h" files into files "dialog_drawgraph.c" and "dialog_drawgraph.h", respectively. Then, (s)he puts the following code into the SCIPincludeDialogDrawgraph() method, compare SCIPincludeDialogDefault() in src/scip/dialog_default.c: SCIP_RETCODE SCIPincludeDialogDrawgraph( SCIP* scip ) { SCIP_DIALOG* root; SCIP_DIALOG* dialog; root = SCIPgetRootDialog(scip); if( root == NULL ) { SCIP_CALL( SCIPcreateRootDialog(scip, &root) ); } assert( root != NULL ); { SCIP_CALL( SCIPaddDialogEntry(scip, root, dialog) ); SCIP_CALL( SCIPreleaseDialog(scip, &dialog) ); } return SCIP_OKAY; } Using this code, it is even possible to call SCIPincludeDialogDrawgraph() before including the default dialog plugins, and you can also call it multiple times without causing inconsistencies in the dialog structure. Fundamental Callback Methods of a DialogDialogs have only one fundamental callback method, namely the DIALOGEXEC method. This method has to be implemented for every dialog; the other callback methods are optional. In the C++ wrapper class scip::ObjDialog, the scip_exec() method (which corresponds to the DIALOGEXEC callback) is a virtual abstract member function. You have to implement it in order to be able to construct an object of your dialog class. Additional documentation for the callback methods can be found in type_dialog.h. DIALOGEXECThe DIALOGEXEC method is invoked, if the user selected the dialog's command name in the parent's menu. It should execute what is stated in DIALOG_DESC, e.g., the display constraint handlers dialog should display information about the constraint handlers included in SCIP, see src/scip/dialog_default.c. For typical methods called by the execution method, have a look at src/scip/dialog_default.c. The callback has to return which dialog should be processed next. This can be, for example, the root dialog (SCIPdialoghdlrGetRoot()), the parent dialog (SCIPdialogGetParent()) or NULL, which stands for closing the interactive shell. Additional Callback Methods of a DialogThe additional callback methods do not need to be implemented in every case. They can be used, for example, to free private data. DIALOGPFREEIf you are using dialog data, you have to implement this method in order to free the dialog data. This can be done by the following procedure: static SCIP_DECL_DIALOGFREE(dialogFreeMydialog) { SCIP_DIALOGDATA* dialogdata; dialogdata = SCIPdialogGetData(dialog); assert(dialogdata != NULL); SCIPfreeMemory(scip, &dialogdata); SCIPdialogSetData(dialog, NULL); return SCIP_OKAY; } If you have allocated memory for fields in your dialog data, remember to free this memory before freeing the dialog data itself. If you are using the C++ wrapper class, this method is not available. Instead, just use the destructor of your class to free the member variables of your class. DIALOGDESCThis method is called when the help menu of the parent is displayed. It should output (usually a single line of) information describing the meaning of the dialog. DIALOGCOPYThe DIALOGCOPY callback is executed when a SCIP instance is copied, e.g. to solve a sub-SCIP. By defining this callback as |