Initializing help system before first use

Basic Usage

Topics covered in this chapter:

The FICO Xpress Optimization Suite is a powerful and flexible framework catering for the development of a wide range of optimization applications. From the script-based Console Optimizer providing rapid development access to a subset of Optimizer functionality (Console Mode) to the more advanced, high performance access of the full Optimizer functionality through the library interface.

In the previous section we looked at the Console Optimizer interface and introduced some basic functions that all FICO Xpress Optimizer users should be familiar with. In this section we expand on the discussion and include some basic functions of the library interface.

Initialization

Before the FICO Xpress Optimization Suite can be used from any of the interfaces the Optimizer library must be initialized and the licensing status successfully verified. Details about licensing your installation can be found in FICO Xpress Installation Guide.

When the Console Optimizer is started from the command line the initialization and licensing security checks happen immediately and the results are displayed with the banner in the console window. For the library interface users, the initialization and licensing are triggered by a call to the library function XPRSinit, which must be made before any of the other Optimizer library routines can be successfully called. If the licensing security checks fail to check out a license then library users can obtain a string message explaining the issue using the function XPRSgetlicerrmsg.

Note that it is recommended that the users having licensing problems use the Console Optimizer as a means of checking the licensing status while resolving the issues. This is because it is the quickest and easiest way to check and display the licensing status.

Once the Optimizer functionality is no longer required the license and any system resources held by the Optimizer should be released. The Console Optimizer releases these automatically when the user exits the Console Optimizer with the QUIT or STOP command. For library users the Optimizer can be triggered to release its resources with a call to the routine XPRSfree, which will free the license checked out in the earlier call to XPRSinit.

{
  if(XPRSinit(NULL)) printf("Problem with XPRSinit\n");
  XPRSfree();
}

In general, library users will call XPRSinit once when their application starts and then call XPRSfree before it exits. This approach is recommended since calls to XPRSinit can have non-negligible (approx. 0.5 sec) overhead when using floating network licensing.

Although it is recommended that the user writes their code such that XPRSinit and XPRSfree are called only in sequence note that the routine XPRSinit may be called repeatedly before a call to XPRSfree. Each subsequent call to XPRSinit after the first will simply return without performing any tasks. In this case note that the routine XPRSfree must be called the same number of times as the calls to XPRSinit to fully release the resources held by the library. Only on the last of these calls to XPRSfree will the library be released and the license freed.

The Problem Pointer

The Optimizer provides a container or problem pointer to contain an optimization problem and its associated controls, attributes and any other resources the user may attach to help construct and solve the problem. Console Optimizer has one of these problem pointers that it uses to provide the user with loading and solving functionality. This problem pointer is automatically initialized when the Console Optimizer is started and release again when it is stopped.

In contrast to the Console Optimizer, library interface users can have multiple problem pointers coexisting simultaneously in a process. The library user creates and destroys a problem pointer using the routines XPRScreateprob and XPRSdestroyprob, respectively. In the C library interface, the user passes the problem pointer as the first argument in routines that are used to operate on the problem pointer's data. Note that it is recommended that the library user destroys all problem pointers before calling XPRSfree.

{
  XPRSprob prob;
  XPRScreateprob(&prob);
  XPRSdestroyprob(prob);
}

Logging

The Optimizer provides useful text logging messages for indicating progress during the optimization algorithms and for indicating the status of certain important commands such as XPRSreadprob. The messages from the optimization algorithms report information on iterations of the algorithm. The most important use of the logging, however, is to convey error messages reported by the Optimizer. Note that once a system is in production the error messages are typically the only messages of interest to the user.

Conveniently, the Console Optimizer automatically writes the logging messages for its problem pointer to the console screen. Although message management for the library users is more complicated than for Console Optimizer users, library users have more flexibility with the handling and routing of messages. The library user can route messages directly to file or they can intercept the messages via callback and marshal the message strings to appropriate destinations depending on the type of message and/or the problem pointer from which the message originates.

To write the messages sent from a problem pointer directly to file the user can call XPRSsetlogfile with specification of an output file name. To get messages sent from a problem pointer to the library user's application the user will define and then register a messaging callback function with a call to the XPRSaddcbmessage routine.

{
  XPRSprob prob;
  XPRScreateprob(&prob);
  XPRSsetlogfile(prob, "logfile.log");
  XPRSdestroyprob(prob);
}

Note that a high level messaging framework is also available — which handles messages from all problem pointers created by the Optimizer library and messages related to initialization of the library itself — by calling the XPRS_ge_addcbmsghandler function. A convenient use of this callback, particularly when developing and debugging an application, is to trap all messages to file. The following line of code shows how to use the library function XPRSlogfilehandler together with XPRS_ge_addcbmsghandler to write all library message output to the file log.txt.

XPRS_ge_addcbmsghandler(XPRSlogfilehandler, "log.txt", 0);

Details about the use of callback functions can be found in section Using the Callbacks.

Problem Loading

Once a problem pointer has been created, an optimization problem can be loaded into it. The problem can be loaded either from file or from memory via the suite of problem loading and problem manipulation routines available in the Optimizer library interface. The simplest of these approaches, and the only approach available to Console Optimizer users, is to read a matrix from an MPS or LP file using XPRSreadprob (READPROB).

{
  XPRSprob prob;
  XPRScreateprob(&prob);
  XPRSsetlogfile(prob, "logfile.log");
  XPRSreadprob(prob, "hpw15", "");
  XPRSdestroyprob(prob);
}

Library users can construct the problem in their own arrays and then load this problem specification using one of the functions XPRSloadlp, XPRSloadqp, XPRSloadqcqp, XPRSloadmip, XPRSloadmiqp or XPRSloadmiqcqp. During the problem load routine the Optimizer will use the user's data to construct the internal problem representation in new memory that is associated with the problem pointer. Note, therefore, that the user's arrays can be freed immediately after the call. Once the problem has been loaded, any subsequent call to one of these load routines will overwrite the problem currently represented in the problem pointer.

The names of the problem loading routines indicate the type of problem that can be represented using the routine. The following table outlines the components of an optimization problem as denoted by the codes used in the function names.

Code Problem Content
lp Linear Program (LP) (linear constraints and linear objective)
qp Quadratic Program (LP with quadratic objective)
mi(p) MIP entities (optimization problem with discrete variables and/or special ordered sets)
qc Quadratic Constraints (LP with quadratic constraints)

Many of the array arguments of the load routines can optionally take NULL pointers if the associated component of the problem is not required to be defined. Note, therefore, that the user need only use the XPRSloadmiqcqp routine to load any problem that can be loaded by the other routines.

Finally, note that the names of the rows and columns of the problem are not loaded together with the problem specification. These may be loaded afterwards using a call to the function XPRSaddnames.

Problem Solving

With a problem loaded into a problem pointer the user can run the optimization algorithms on the problem to solve it.

The two main commands to run the optimization algorithms on a problem are XPRSmipoptimize(MIPOPTIMIZE) and XPRSlpoptimize(LPOPTIMIZE) depending on whether the problem needs to be solved with or without MIP entities. The XPRSlpoptimize function will solve LPs, QPs and QCQPs or the initial continuous relaxation of a MIP problem, depending on the type of problem loaded in the problem pointer. The XPRSmipoptimize function will solve MIPs, MIQPs and MIQCQPs.

For problems with MIP entities the Optimizer can be told to stop after having solved the initial relaxation by passing the 'l' flag to the XPRSmipoptimize function. The remaining MIP search can be run by calling the XPRSmipoptimize function without the 'l' flag.

{
  XPRSprob prob;
  XPRScreateprob(&prob);
  XPRSsetlogfile(prob, "logfile.log");
  XPRSreadprob(prob, "hpw15", "");
  XPRSmipoptimize(prob, "");
  XPRSdestroyprob(prob);
}

Non-convex quadratic problems must be solved with XPRSoptimize or XPRSnlpoptimize. See the Global Solver User Guide for more information.

Interrupting the Solve

It is common that users need to interrupt iterations before a solving algorithm is complete. This is particularly common when solving MIP problems since the time to solve these to completion can be large and users are often satisfied with near-optimal solutions. The Optimizer provides for this with structured interrupt criteria using controls and with user-triggered interrupts.

As described previously in section Interrupting Console Optimizer, the Console Optimizer can receive a user-triggered interrupt from the keyboard Ctrl-C event. It was also described in this previous section how interrupted commands could be resumed by simply reissuing the command. Similarly, optimization runs started from the library interface and interrupted by either structured or user-triggered interrupts, will return from the call in such a state that the run may be resumed with a follow-on call.

To setup structured interrupts the user will need to set the value of certain controls. Controls are scalar values that are accessed by their name in the Console Optimizer and by their id number via the library interface using functions such as XPRSgetintcontrol and XPRSsetintcontrol. These particular library functions are used for getting and setting the values of integer controls. Similar library functions are used for accessing double precision and string type controls.

Some types of structured interrupts include limits on iterations of the solving algorithms and a limit on the overall time of the optimization run. Limits on the simplex algorithms' iterations are set using the control LPITERLIMIT. Iterations of the Newton barrier algorithm are limited using the control BARITERLIMIT. A limit on the number of nodes processed in the branch and bound search when solving MIP problems is provided with the MAXNODE control. The integer control MAXTIME is used to limit the overall run time of the optimization run.

Note that it is important to be careful when using interrupts, to ensure that the optimization run is not being unduly restricted. This is particularly important when using interrupts on MIP optimization runs. Specific controls to use as stopping criteria for the MIP search are discussed in section Stopping Criteria.

{
  XPRSprob prob;
  XPRScreateprob(&prob);
  XPRSsetlogfile(prob, "logfile.log");
  XPRSreadprob(prob, "hpw15", "");
  XPRSsetintcontrol(prob, XPRS_MAXNODE, 20000);
  XPRSmipoptimize(prob, "");
  XPRSdestroyprob(prob);
}

Finally note that library users can trigger an interrupt on an optimization run (in a similar way to the Ctrl-C interrupt in the Console Optimizer) using a call to the function XPRSinterrupt. It is recommended that the user call this function from a callback during the optimization run. See section Using the Callbacks for details about using callbacks.

Results Processing

Once the optimization algorithms have completed, either a solution will be available, or else the problem will have been identified as infeasible or unbounded. In the latter case, the user might want to know what caused this particular outcome and take steps to correct it. How to identify the causes of infeasibility and unboundedness are discussed in Chapter Infeasibility, Unboundedness and Instability. In the former case, however, the user typically wants to retrieve the solution information into the required format.

The FICO Xpress Optimizer provides a number of functions for accessing solution information. An ASCII solution file can be obtained by XPRSwriteslxsol (WRITESLXSOL). The .slx format is similar format to the .mps format for MIP models and to the .sol format. Files in .slx format can be read back into the optimizer using the XPRSreadslxsol function. An extended solution file with additional information per column may be obtained as an ASCII file using either of XPRSwritesol (WRITESOL) or XPRSwriteprtsol(WRITEPRTSOL).

Library interface users may additionally access the current solution information via memory using XPRSgetsolution. The values of the slack values, dual values and reduced costs can be obtained by calling XPRSgetslacks, XPRSgetduals and XPRSgetredcosts.

In addition to the arrays of solution information provided by the Optimizer, summary solution information is also available through problem attributes. These are named scalar values that can be accessed by their id number using the library functions XPRSgetintattrib, XPRSgetdblattrib and XPRSgetstrattrib. Examples of attributes include LPOBJVAL and MIPOBJVAL, which return the objective function values for the current LP, QP or QCQP solution and the last MIP solution, respectively. A full list of attributes may be found in Chapter Problem Attributes.

When the optimization routine returns it is recommended that the user check the status of the run to ensure the results are interpreted correctly. For continuous optimization runs (started with XPRSlpoptimize) the status is available using the LPSTATUS integer problem attribute. For MIP optimization runs (started with XPRSmipoptimize) the status is available using the MIPSTATUS integer problem attribute. See the attribute's reference section for the definition of their values.

{
  XPRSprob prob;
  int nCols;
  double *x;
  XPRScreateprob(&prob);
  XPRSsetlogfile(prob, "logfile.log");
  XPRSreadprob(prob, "hpw15", "");
  XPRSgetintattrib(prob, XPRS_COLS, &nCols);
  XPRSsetintcontrol(prob, XPRS_MAXNODE, 20000);
  XPRSmipoptimize(prob, "");
  XPRSgetintattrib(prob, XPRS_MIPSTATUS, &iStatus);
  if(iStatus == XPRS_MIP_SOLUTION || iStatus == XPRS_MIP_OPTIMAL) {
    x = (double *) malloc(sizeof(double) * nCols);
    XPRSgetsolution(prob, NULL, x, 0, nCols - 1);
  }
  XPRSdestroyprob(prob);
}

Note that, unlike for LP, QP or QCQP solutions, dual solution information is not available by calling XPRSgetduals or XPRSgetredcosts and is not automatically generated with the MIP solutions. The reason for this is that MIP problems do not satisfy the theoretical conditions by which dual information is derived (i.e., Karush-Kuhn-Tucker conditions). In particular, this is because the MIP constraint functions are, in general, not continuously differentiable (indeed, the domains of integer variables are not continuous).

Despite this, some useful dual information can be generated if a MIP has continuous variables and we solve the resulting LP problem generated by fixing the non-continuous component of the problem to their solution values. Because this process can be expensive it is left to the user to perform this in a post solving phase where the user will simply call the function XPRSfixmipentities followed with a call to the optimization routine XPRSlpoptimize.

Function Quick Reference

Administration

XPRSinit Initialize the Optimizer.
XPRScreateprob Create a problem pointer.
XPRSsetlogfile Direct all Optimizer output to a log file.
XPRSaddcbmessage Define a message handler callback function.
XPRSgetintcontrol Get the value of an integer control,
XPRSsetintcontrol Set the value of an integer control.
XPRSinterrupt Set the interrupt status of an optimization run.
XPRSdestroyprob Destroy a problem pointer.
XPRSfree Release resources used by the Optimizer.

Problem Loading

XPRSreadprob Read an MPS or LP format file.
XPRSloadlp Load an LP problem.
XPRSloadqp Load a quadratic objective problem.
XPRSloadqcqp Load a quadratically constrained, quadratic objective problem.
XPRSloadmip Load a MIP problem.
XPRSloadmiqp Load a quadratic objective MIP problem.
XPRSloadmiqcqp Load a quadratically constrained, quadratic objective MIP problem.
XPRSaddnames Load names for a range of rows or columns in a problem.

Problem Solving

XPRSreadbasis Read a basis from file.
XPRSloadbasis Load a basis from user arrays.
XPRSreaddirs Read a directives file.
XPRSlpoptimize Solve the problem without MIP entities.
XPRSmipoptimize Run the problem with MIP entities.
XPRSfixmipentities Fix the discrete variables in the problem to the values of the current
MIP solution stored with the problem pointer.
XPRSgetbasis Copy the current basis into user arrays.
XPRSwritebasis Write the current basis to file.

Results Processing

XPRSwritesol Write the current solution to ASCII files.
XPRSwriteprtsol Write the current solution in printable format to file.
XPRSgetsolution Copy the current solution values into a user array.
XPRSgetslacks Copy the current slack values into a user array.
XPRSgetduals Copy the current dual values into a user array.
XPRSgetredcosts Copy the current reduced costs into a user array.
XPRSgetintattrib Get the value of an integer problem attribute e.g., by passing the id
MIPSOLS the user can get the number of MIP solutions found.
XPRSgetdblattrib Get the value of a double problem attribute e.g., by passing the id
MIPOBJVAL the user can get the objective value of the last MIP
solution.
XPRSgetstrattrib Get the value of a string problem attribute.

Summary

In the previous sections a brief introduction is provided to the most common features of the FICO Xpress Optimizer and its most general usage. The reader should now be familiar with the main routines in the Optimizer library. These routines allow a user to create problem pointers and load problems into these problem pointers. The reader should be familiar with the requirements for setting up message handling with the Optimizer library. Also the reader should know how to run the optimization algorithms on the loaded problems and be familiar with the various ways that results can be accessed.

Examples of using the Optimizer are available from a number of sources, most notably from FICO Xpress Getting Started manual. This provides a straight forward, "hands-on" approach to the FICO Xpress Optimization Suite and it is highly recommended that users read the relevant chapters before considering the reference manuals. Additionally, more advanced, examples may be downloaded from the website.


© 2001-2025 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.