BCL in C++ and Java
An overview of BCL in C++
The C++ interface of BCL provides the full functionality of the C version except for the data input, output and error handling for which the corresponding C functions may be used. The C modeling objects, such as variables, constraints and problems, are converted into classes, and their associated functions into methods of the corresponding class in C++.
To use the C++ version of BCL, the C++ header file must be included at the beginning of the program (and not the main BCL header file xprb.h).
#include "xprb_cpp.h"Using C++, the termwise definition of constraints is even easier. This has been achieved by overloading the algebraic operators like '+`, '-`, '<=`, or '==`. With these operators constraints may be written in a form that is close to an algebraic formulation.
It should be noted that the names of classes and methods have been adapted to C++ naming standards: All C++ classes that have a direct correspondence with modeling objects in BCL (namely XPRBprob, XPRBvar, XPRBctr, XPRBcut, XPRBsos, XPRBindexSet, XPRBbasis) take the same names, with the exception of XPRBindexSet. In the names of the methods the prefix XPRB has been dropped, as have been references to the type of the object. For example, function XPRBgetvarname is turned into the method getName of class XPRBvar.
All C++ classes of BCL are part of the namespace dashoptimization. To use the (short) class names, it is recommended to add the line
using namespace ::dashoptimization;at the beginning of every program that uses the C++ classes of BCL.
C++ functions can be used together with C functions, for instance when printing program output or using Xpress-Optimizer functions. However, it is not possible to mix BCL C and C++ objects in a program.
Example
An example of use of BCL in C++ is the following, which constructs the scheduling example described in Chapter Modeling with BCL:
#include <iostream> #include "xprb_cpp.h" using namespace std; using namespace ::dashoptimization; #define NJ 4 // Number of jobs #define NT 10 // Time limit double DUR[] = {3,4,2,2}; // Durations of jobs XPRBvar start[NJ]; // Start times of jobs XPRBvar delta[NJ][NT]; // Binaries for start times XPRBvar z; // Max. completion time XPRBprob p("Jobs"); // Initialize BCL & a new problem void jobsModel() { XPRBlinExp le; int j,t; // Create start time variables for(j=0;j<NJ;j++) start[j] = p.newVar("start"); z = p.newVar("z",XPRB_PL,0,NT); // Makespan variable for(j=0;j<NJ;j++) // Binaries for each job for(t=0;t<(NT-DUR[j]+1);t++) delta[j][t] = p.newVar(XPRBnewname("delta%d%d",j+1,t+1),XPRB_BV); for(j=0;j<NJ;j++) // Calculate max. completion time p.newCtr("Makespan", start[j]+DUR[j] <= z); // Precedence relation betw. jobs p.newCtr("Prec", start[0]+DUR[0] <= start[2]); for(j=0;j<NJ;j++) // Linking start times & binaries { le=0; for(t=0;t<(NT-DUR[j]+1);t++) le += (t+1)*delta[j][t]; p.newCtr(XPRBnewname("Link_%d",j+1), le == start[j]); } for(j=0;j<NJ;j++) // Unique start time for each job { le=0; for(t=0;t<(NT-DUR[j]+1);t++) le += delta[j][t]; p.newCtr(XPRBnewname("One_%d",j+1), le == 1); } p.setObj(z); // Define and set objective for(j=0;j<NJ;j++) start[j].setUB(NT-DUR[j]+1); // Upper bounds on "start" var.s } void jobsSolve() { int j,t,statmip; for(j=0;j<NJ;j++) for(t=0;t<NT-DUR[j]+1;t++) delta[j][t].setDir(XPRB_PR,10*(t+1)); // Give highest priority to var.s for earlier start times p.setSense(XPRB_MINIM); p.solve("g"); // Solve the problem as MIP statmip = p.getMIPStat(); // Get the MIP problem status if((statmip == XPRB_MIP_SOLUTION) || (statmip == XPRB_MIP_OPTIMAL)) { // An integer solution has been found cout << "Objective: " << p.getObjVal() << endl; for(j=0;j<NJ;j++) { // Print the solution for all start times cout << start[j].getName() << ": " << start[j].getSol(); cout << endl; } } } int main(int argc, char **argv) { jobsModel(); // Problem definition jobsSolve(); // Solve and print solution return 0; }The definition of SOS is similar to the definition of constraints.
XPRBsos set[NJ]; void jobsModel() { ... for(j=0;j<NJ;j++) // Variables for each job for(t=0;t<(NT-DUR[j]+1);t++) delta[j][t] = p.newVar(XPRBnewname("delta%d%d",j+1,t+1),XPRB_PL,0,1); for(j=0;j<NJ;j++) // SOS definition { le=0; for(t=0;t<(NT-DUR[j]+1);t++) le += (t+1)*delta[j][t]; set[j] = p.newSos("sosj",XPRB_S1,le); } }Branching directives for the SOSs are added as follows.
for(j=0;j<NJ;j++) set[j].setDir(XPRB_DN); // First branch downwards on setsAdding the following two lines during or after the problem definition will print the problem to the standard output and export the matrix to a file respectively.
p.print(); // Print out the problem def. p.exportProb(XPRB_MPS,"expl1"); // Output matrix to MPS fileSimilarly to what has been shown for the problem formulation in C, we may read data from file and use index sets in the problem formulation. The following changes and additions to the basic model formulation are required for the creation of index sets based on data input from file. The function jobsSolve is left out in this listing since it remains unchanged from the previous one.
#include <iostream> #include <cstdio> #include <cstdlib> #include "xprb_cpp.h" using namespace std; using namespace ::dashoptimization; #define MAXNJ 4 // Max. number of jobs #define NT 10 // Time limit int NJ = 0; // Number of jobs read in double DUR[MAXNJ]; // Durations of jobs XPRBindexSet Jobs; // Names of Jobs XPRBvar *start; // Start times of jobs XPRBvar **delta; // Binaries for start times XPRBvar z; // Max. completion time XPRBprob p("Jobs"); // Initialize BCL & a new problem void readData() { char name[100]; FILE *datafile; // Create a new index set Jobs = p.newIndexSet("jobs", MAXNJ); // Open data file for read access datafile=fopen("durations.dat","r"); // Read in all (non-empty) lines up to the end of the file while(NJ<MAXNJ && XPRBreadlinecb(XPRB_FGETS, datafile, 99, "T,d", name, &DUR[NJ])) { Jobs += name; // Add job to the index set NJ++; } fclose(datafile); // Close the input file cout << "Number of jobs read: " << Jobs.getSize() << endl; } void jobsModel() { XPRBlinExp le; int j,t; // Create start time variables with bounds start = new XPRBvar[NJ]; if(start==NULL) { cout << "Not enough memory for 'start' variables." << endl; exit(0); } for(j=0;j<NJ;j++) start[j] = p.newVar("start",XPRB_PL,0,NT-DUR[j]+1)); z = p.newVar("z",XPRB_PL,0,NT); // Makespan variable delta = new XPRBvar*[NJ]; if(delta==NULL) { cout << "Not enough memory for 'delta' variables." << endl; exit(0); } for(j=0;j<NJ;j++) // Binaries for each job { delta[j] = new XPRBvar[NT]; if(delta[j]==NULL) { cout <<"Not enough memory for 'delta_j' variables." << endl; exit(0); } for(t=0;t<(NT-DUR[j]+1);t++) delta[j][t] = p.newVar(XPRBnewname("delta%s_%d",Jobs[j],t+1), XPRB_BV); for(j=0;j<NJ;j++) // Calculate max. completion time p.newCtr("Makespan", start[j]+DUR[j] <= z); // Precedence relation betw. jobs p.newCtr("Prec", start[0]+DUR[0] <= start[2]); for(j=0;j<NJ;j++) // Linking start times & binaries { le=0; for(t=0;t<(NT-DUR[j]+1);t++) le += (t+1)*delta[j][t]; p.newCtr(XPRBnewname("Link_%d",j+1), le == start[j]); } for(j=0;j<NJ;j++) // Unique start time for each job { le=0; for(t=0;t<(NT-DUR[j]+1);t++) le += delta[j][t]; p.newCtr(XPRBnewname("One_%d",j+1), le == 1); } p.setObj(z); // Define and set objective jobsSolve(); // Solve the problem delete [] start; for(j=0;j<NJ;j++) delete [] delta[j]; delete [] delta; } int main(int argc, char **argv) { readData(); // Read in the data jobsModel(); // Problem definition return 0; }An overview of BCL in Java
Much as for the C++ interface, the Java interface of BCL provides the full functionality of the C version except for the data input, output and error handling for which the standard Java system functions can be used. The C modeling objects, such as variables, constraints and problems, are again converted into classes, and their associated functions into methods of the corresponding class in Java.
Whereas in C++ it is possible to use C functions, such as printf or XPRBprintf for printing output, all code in Java programs must be written in Java itself. In addition, in Java it is not possible to overload the algebraic operators as has been done for the definition of constraints in C++. Instead, the Java interface provides a set of simple methods like add or eql that have been overloaded to accept various types and numbers of parameters.
The names for classes and methods in Java have been formed in the same way as those of their counterparts in C++: All Java classes that have a direct correspondence with modeling objects in BCL (namely XPRBprob, XPRBvar, XPRBctr, XPRBcut, XPRBsos, XPRBindexSet, XPRBbasis) take the same names, with the exception of XPRBindexSet. In the names of the methods the prefix XPRB has been dropped, as have references to the type of the object. For example, function XPRBgetvarname is turned into the method getName of class XPRBvar.
All Java BCL classes are contained in the package com.dashoptimization. To use the (short) class names, it is recommended to add the line
import com.dashoptimization.*;at the beginning of every program that uses the Java classes of BCL.
The overview on C++ and Java classes in section C++ and Java class reference gives preference to the C++ notation. A comprehensive documentation of the BCL Java interface is available as a separate `Java on-line documentation'.
Example
An example of use of BCL in Java is the following, which again constructs the example described in Chapter Modeling with BCL. Contrary to the C and C++ versions, BCL Java needs to be initialized explicitly by creating an instance of XPRB.
import com.dashoptimization.*; public class xbexpl1 { static final int NJ = 4; /* Number of jobs */ static final int NT = 10; /* Time limit */ static final double[] DUR = {3,4,2,2}; /* Durations of jobs */ static XPRBvar[] start; /* Start times of jobs */ static XPRBvar[][] delta; /* Binaries for start times */ static XPRBvar z; /* Max. completion time */ static XPRB bcl; static XPRBprob p; static void jobsModel() { XPRBlinExp le; int j,t; start = new XPRBvar[NJ]; /* Start time variables */ for(j=0;j<NJ;j++) start[j] = p.newVar("start"); z = p.newVar("z",XPRB.PL,0,NT); /* Makespan variable */ delta = new XPRBvar[NJ][NT]; for(j=0;j<NJ;j++) /* Binaries for each job */ for(t=0;t<(NT-DUR[j]+1);t++) delta[j][t] = p.newVar("delta"+(j+1)+(t+1), XPRB.BV); for(j=0;j<NJ;j++) /* Calculate max. completion time */ p.newCtr("Makespan", start[j].add(DUR[j]).lEql(z) ); p.newCtr("Prec", start[0].add(DUR[0]).lEql(start[2]) ); /* Precedence rel. between jobs */ for(j=0;j<NJ;j++) /* Linking start times & binaries */ { le = new XPRBlinExp(); for(t=0;t<(NT-DUR[j]+1);t++) le.add(delta[j][t].mul((t+1))); p.newCtr("Link_"+(j+1), le.eql(start[j]) ); } for(j=0;j<NJ;j++) /* Unique start time for each job */ { le = new XPRBlinExp(); for(t=0;t<(NT-DUR[j]+1);t++) le.add(delta[j][t]); p.newCtr("One_"+(j+1), le.eql(1)); } p.setObj(z); /* Define and set objective */ for(j=0;j<NJ;j++) start[j].setUB(NT-DUR[j]+1); /* Upper bounds on "start" var.s */ } static void jobsSolve() { int j,t,statmip; for(j=0;j<NJ;j++) for(t=0;t<NT-DUR[j]+1;t++) delta[j][t].setDir(XPRB.PR, 10*(t+1)); /* Give highest priority to var.s for earlier start times */ p.setSense(XPRB.MINIM); p.solve("g"); /* Solve the problem as MIP */ statmip = p.getMIPStat(); /* Get the MIP problem status */ if((statmip == XPRB.MIP_SOLUTION) || (statmip == XPRB.MIP_OPTIMAL)) { /* An integer solution has been found */ System.out.println("Objective: "+ p.getObjVal()); /* Print solution for all start times */ for(j=0;j<NJ;j++) System.out.println(start[j].getName() + ": "+ start[j].getSol()); } } public static void main(String[] args) { bcl = new XPRB(); /* Initialize BCL */ p = bcl.newProb("Jobs"); /* Create a new problem */ jobsModel(); /* Problem definition */ jobsSolve(); /* Solve and print solution */ } }The definition of SOS is similar to the definition of constraints.
static XPRBsos[] set; static XPRBprob p; static void jobsModel() { ... delta = new XPRBvar[NJ][NT]; for(j=0;j<NJ;j++) /* Variables for each job */ for(t=0;t<(NT-DUR[j]+1);t++) delta[j][t] = p.newVar("delta"+(j+1)+(t+1), XPRB.PL, 0, 1); set = new XPRBsos[NJ]; for(j=0;j<NJ;j++) /* SOS definition */ { le = new XPRBlinExp(); for(t=0;t<(NT-DUR[j]+1);t++) le.add(delta[j][t].mul((t+1))); set[j] = p.newSos("sosj", XPRB.S1, le); } }Branching directives for the SOSs are added as follows.
for(j=0;j<NJ;j++) set[j].setDir(XPRB.DN); /* First branch downwards on sets */Adding the following two lines during or after the problem definition will print the problem to the standard output and export the matrix to a file respectively.
p.print(); /* Print out the problem def. */ p.exportProb(XPRB.MPS,"expl1"); /* Output matrix to MPS file */Similarly to what has been shown for the problem formulation in C and C++, we may read data from file and use index sets in the problem formulation. Only a few changes and additions to the basic model formulation are required for the creation and use of index sets. However, if we want to read in a data file in the format accepted by the C functions XPRBreadline and XPRBreadarrline (that is, using '!' as commentary sign, and ',' as separators, and skip blanks and empty lines), we need to configure the data file access in Java.
In the following program listing we leave out the method jobsSolve because it remains unchanged from the previous.
import java.io.*; import com.dashoptimization.*; public class xbexpl1i { static final int MAXNJ = 4; /* Max. number of jobs */ static final int NT = 10; /* Time limit */ static int NJ = 0; /* Number of jobs read in */ static final double[] DUR; /* Durations of jobs */ static XPRBindexSet Jobs; /* Job names */ static XPRBvar[] start; /* Start times of jobs */ static XPRBvar[][] delta; /* Binaries for start times */ static XPRBvar z; /* Max. completion time */ static XPRB bcl; static XPRBprob p; /**** Initialize the stream tokenizer ****/ static StreamTokenizer initST(FileReader file) { StreamTokenizer st=null; st= new StreamTokenizer(file); st.commentChar('!'); /* Use character '!' for comments */ st.eolIsSignificant(true); /* Return end-of-line character */ st.ordinaryChar(','); /* Use ',' as separator */ st.parseNumbers(); /* Read numbers as numbers (not strings)*/ return st; } /**** Read data from files ****/ static void readData() throws IOException { FileReader datafile=null; StreamTokenizer st; int i; /* Create a new index set */ Jobs = p.newIndexSet("Jobs", MAXNJ); DUR = new double[MAXNJ]; datafile = new FileReader("durations.dat"); st = initST(datafile); do { do { st.nextToken(); } while(st.ttype==st.TT_EOL); /* Skip empty lines */ if(st.ttype != st.TT_WORD) break; i=Jobs.addElement(st.sval); if(st.nextToken() != ',') break; if(st.nextToken() != st.TT_NUMBER) break; DUR[i] = st.nval; NJ+=1; } while( st.nextToken() == st.TT_EOL && NJ<MAXNJ); datafile.close(); System.out.println("Number of jobs read: " + Jobs.getSize()); } static void jobsModel() { XPRBlinExp le; int j,t; start = new XPRBvar[NJ]; for(j=0;j<NJ;j++) /* Start time variables with bounds */ start[j] = p.newVar("start",XPRB.PL,0,NT-DUR[j]+1); z = p.newVar("z",XPRB.PL,0,NT); /* Makespan variable */ delta = new XPRBvar[NJ][NT]; for(j=0;j<NJ;j++) /* Binaries for each job */ for(t=0;t<(NT-DUR[j]+1);t++) delta[j][t] = p.newVar("delta"+Jobs.getIndexName(j)+"_"+(t+1), XPRB.BV); for(j=0;j<NJ;j++) /* Calculate max. completion time */ p.newCtr("Makespan", start[j].add(DUR[j]).lEql(z) ); p.newCtr("Prec", start[0].add(DUR[0]).lEql(start[2]) ); /* Precedence rel. between jobs */ for(j=0;j<NJ;j++) /* Linking start times & binaries */ { le = new XPRBlinExp(); for(t=0;t<(NT-DUR[j]+1);t++) le.add(delta[j][t].mul((t+1))); p.newCtr("Link_"+(j+1), le.eql(start[j]) ); } for(j=0;j<NJ;j++) /* Unique start time for each job */ { le = new XPRBlinExp(); for(t=0;t<(NT-DUR[j]+1);t++) le.add(delta[j][t]); p.newCtr("One_"+(j+1), le.eql(1)); } p.setObj(z); /* Define and set objective */ } public static void main(String[] args) { bcl = new XPRB(); /* Initialize BCL */ p = bcl.newProb("Jobs"); /* Create a new problem */ try { readData(); /* Data input from file */ } catch(IOException e) { System.err.println(e.getMessage()); System.exit(1); } jobsModel(); /* Problem definition */ jobsSolve(); /* Solve and print solution */ } }Error handling
If an error occurs, BCL Java raises exceptions. A large majority of these execeptions are of class XPRBerror, during initialization of class XPRBlicenseError, and if file access is involved (such as in method exportProb) of class IOException. For simplicity's sake most of the Java program examples in this manual omit the error handling. Below we show a Java implementation of the exmample of user error handling with BCL from Section User error handling. Other features demonstrated by this example include
- redirection of the BCL output stream for the whole program and for an individual problem;
- setting the BCL message printing level;
- forcing garbage collection for a problem.
import java.io.*; import com.dashoptimization.*; public class xbexpl3 { static XPRB bcl; /***********************************************************************/ public static void modexpl3(XPRBprob prob) throws XPRBerror { XPRBvar[] x; XPRBlinExp cobj; int i; x = new XPRBvar[3]; /* Create the variables */ for(i=0;i<2;i++) x[i] = prob.newVar("x_"+i, XPRB.UI, 0, 100); /* Create the constraints: C1: 2x0 + 3x1 >= 41 C2: x0 + 2x1 = 13 */ prob.newCtr("C1", x[0].mul(2).add(x[1].mul(3)) .gEql(41)); prob.newCtr("C2", x[0].add(x[1].mul(2)) .eql(13)); /* Uncomment the following line to cause an error in the model that triggers the error handling: */ // x[2] = prob.newVar("x_2", XPRB.UI, 10, 1); /* Objective: minimize x0+x1 */ cobj = new XPRBlinExp(); for(i=0;i<2;i++) cobj.add(x[i]); prob.setObj(cobj); /* Select objective function */ prob.setSense(XPRB.MINIM); /* Set objective sense to minimization */ prob.print(); /* Print current problem definition */ prob.solve(""); /* Solve the LP */ System.out.println("Problem status: " + prob.getProbStat() + " LP status: " + prob.getLPStat() + " MIP status: " + prob.getMIPStat()); /* This problem is infeasible, that means the following command will fail. It prints a warning if the message level is at least 2 */ System.out.println("Objective: " + prob.getObjVal()); for(i=0;i<2;i++) /* Print solution values */ System.out.print(x[i].getName() + ":" + x[i].getSol() + ", "); System.out.println(); } /***********************************************************************/ public static void main(String[] args) { FileWriter f; XPRBprob prob; try { bcl = new XPRB(); /* Initialize BCL */ } catch(XPRBlicenseError e) { System.err.println("BCL error "+ e.getErrorCode() + ": " + e.getMessage()); System.exit(1); } bcl.setMsgLevel(2); /* Set the printing flag. Try other values: 0 - no printed output, 2 - print warnings, 3 - all messages */ try { f=new FileWriter("expl3out.txt"); bcl.setOutputStream(f); /* Redirect all output from BCL to a file */ prob = bcl.newProb("Expl3"); /* Create a new problem */ prob.setOutputStream(); /* Output for this prob. on standard output */ modexpl3(prob); /* Formulate and solve the problem */ prob.setOutputStream(f); /* Redirect problem output to file */ prob.print(); /* Write to the output file */ f.close(); prob=null; /* Delete the problem */ System.gc(); /* Force garbage collection */ System.runFinalization(); System.err.flush(); } catch(IOException e) { System.err.println(e.getMessage()); System.exit(1); } catch(XPRBerror e) { System.err.println("BCL error "+ e.getErrorCode() + ": " + e.getMessage()); System.exit(1); } } }C++ and Java class reference
The complete set of classes of the BCL C++ and Java interfaces is summarized in the following list:
XPRB Initialization and general settings (C++ and Java), definition of all parameters (Java only).XPRBbasis Methods for accessing bases.XPRBctr Methods for modifying and accessing constraints and operators for constructing them.XPRBcut Methods for modifying and accessing cuts and operators for constructing them.XPRBerror Exception raised by BCL errors (Java only).XPRBindexSet Methods for accessing index sets and operators for adding and retrieving set elements.XPRBlinExp Methods and operators for constructing linear expressions.XPRBlinRel Methods and operators for constructing linear relations from linear expressions.XPRBprob Problem definition, including methods for creating and deleting the modeling objects, problem solving, changing settings, and retrieving solution information.XPRBquadExp Methods and operators for constructing quadratic expressions.XPRBsos Methods for modifying and accessing Special Ordered Sets and operators for constructing them.XPRBvar Methods for modifying and accessing variables.The method isValid may require some explanation: it should be used in combination with methods getVarByName, getCtrByName etc. These methods always return an object of the desired type, unlike the corresponding functions in standard BCL which return a NULL pointer if the object was not found. Only with method isValid it is possible to test whether the object is a valid object, that is, whether it is contained in a problem definition.
Classes corresponding to BCL modeling objects
All C++ and Java classes that have a direct correspondence with modeling objects in BCL (namely XPRBprob, XPRBvar, XPRBctr, XPRBcut, XPRBsos, XPRBindexSet, XPRBbasis) take the same names, with the exception of XPRBindexSet. In C++, the corresponding BCL modeling object in C can be obtained from each of these classes, with the method getCRef. It is also possible to obtain the Xpress-Optimizer problem corresponding to a BCL C++ or Java problem by using method getXPRSprob of class XPRBprob.
Most of the methods of the classes listed in this section call standard BCL C functions, as indicated, and return their result. These methods are common to C++ and Java and are listed only once, giving preference to the C++ notation (the type char or char * in C++ is replaced by String in Java, and the type bool in C++ becomes boolean in Java, furthermore, in Java there are no pointers). Where the C and C++ functions return 0 or 1 to indicate success or failure of the execution of a function the Java methods have return type void, raising an exception if an error occurs.
The major difference between the C++ and Java implementations is in the way linear and quadratic expressions and constraints are created. In C++, the algebraic operators like + or == are overloaded so that constraints may be written in a form that is close to an algebraic formulation. In Java, it is not possible to overload operators; instead, a set of simple methods is provided, for example, add or eql that have been overloaded to accept various types and numbers of parameters. The corresponding operators and methods are presented in separate paragraphs.
Additional classes
The classes listed in this section do not correspond to standard BCL modeling objects. Class XPRB contains some methods relating to the initialization and the general status of the software and in Java also the definition of all parameters (not listed here). This means, any parameter with the prefix XPRB_ in standard BCL has to be referred to as a constant of the Java class XPRB. For example, XPRB_BV in standard BCL becomes XPRB.BV in Java; in C++ it stays the same as in C.
Most of the remaining classes have been introduced to aid the termwise definition of constraints, by overloading certain arithmetic operators in the case of C++ and by overloading a set of simple methods in the case of Java. Linear expressions (class XPRBlinExp) are required in the definition of constraints and Special Ordered Sets. Quadratic expressions (class XPRBquadExp) are used to define quadratic objective functions. Linear relations (class XPRBlinRel), may be used as an intermediary in the definition of constraints.
In BCL Java, there are a few additional classes related to error handling and licensing, namely XPRBerror, XPRBlicense, and XPRBlicenseError. License errors are raised by the initialization of BCL, all other BCL errors are handled by exceptions of the type XPRBerror. Output functions involving file access (in particular matrix output with exportProb) may also generate exceptions of type IOException. The documentation of class XPRBerror is listed below. XPRBlicenseError overloads this class without any methods of its own and is therefore not listed separately. The class XPRBlicense only serves for OEM licensing; for further detail please see the Xpress-MP OEM licensing documentation.
As in the previous section, wherever the C++ and Java functions are similar (remember that the type char or char * in C++ is replaced by String in Java, and the type bool in C++ becomes boolean in Java, there are no pointers in Java, and the return types more often are void, errors being dealt with by raising exceptions) they are listed only once, giving preference to the C++ notation.
If you have any comments or suggestions about these pages, please send mail to docs@dashoptimization.com.