Implementation with BCL
All BCL examples in this book are written with C++. Due to the possibility of overloading arithmetic operators in the C++ programming language, this interface provides the most convenient way of stating models in a close to algebraic form. The same models can also be implemented using the C, Java, or C# interfaces of BCL.
The following BCL program implements the LP example introduced in Chapter 2:
#include <iostream> #include "xprb_cpp.h" using namespace std; using namespace ::dashoptimization; #define NSHARES 10 // Number of shares #define NRISK 5 // Number of high-risk shares #define NNA 4 // Number of North-American shares double RET[] = {5,17,26,12,8,9,7,6,31,21}; // Estimated return in investment int RISK[] = {1,2,3,8,9}; // High-risk values among shares int NA[] = {0,1,2,3}; // Shares issued in N.-America int main(int argc, char **argv) { int s; XPRBprob p("FolioLP"); // Initialize a new problem in BCL XPRBexpr Risk,Na,Return,Cap; XPRBvar frac[NSHARES]; // Fraction of capital used per share // Create the decision variables for(s=0;s<NSHARES;s++) frac[s] = p.newVar("frac"); // Objective: total return for(s=0;s<NSHARES;s++) Return += RET[s]*frac[s]; p.setObj(Return); // Set the objective function // Limit the percentage of high-risk values for(s=0;s<NRISK;s++) Risk += frac[RISK[s]]; p.newCtr("Risk", Risk <= 1.0/3); // Minimum amount of North-American values for(s=0;s<NNA;s++) Na += frac[NA[s]]; p.newCtr("NA", Na >= 0.5); // Spend all the capital for(s=0;s<NSHARES;s++) Cap += frac[s]; p.newCtr("Cap", Cap == 1); // Upper bounds on the investment per share for(s=0;s<NSHARES;s++) frac[s].setUB(0.3); // Solve the problem p.setSense(XPRB_MAXIM); p.lpOptimize(""); // Solution printing cout << "Total return: " << p.getObjVal() << endl; for(s=0;s<NSHARES;s++) cout << s << ": " << frac[s].getSol()*100 << "%" << endl; return 0; }
Let us now have a closer look at what we have just written.
Initialization
To use the BCL C++ interface you need to include the header file xprb_cpp.h. We also define the namespace to which the BCL classes belong.
If the software has not been initialized previously, BCL is initialized automatically when the first problem is created, that is by the line
XPRBprob p("FolioLP");
which creates a new problem with the name `FolioLP'.
General structure
The definition of the model itself starts with the creation of the decision variables (method newVar), followed by the definition of the objective function and the constraints. In C++ (and Java, C#) constraints may be created starting with linear expressions as shown in the example. Equivalently, they may be constructed termwise, for instance the constraint limiting the percentage of high-risk shares:
XPRBctr CRisk; CRisk = p.newCtr("Risk"); for(s=0;s<NRISK;s++) CRisk.addTerm(frac[RISK[s]], 1); CRisk.setType(XPRB_L); CRisk.addTerm(1.0/3);
This second type of constraint definition is common to all BCL interfaces and is the only method of defining constraints in C where overloading is not available.
Notice that in the definition of equality constraints (here the constraint stating that we wish to spend all the capital) we need to employ a double equality sign ==.
The method setUB is used to set the upper bounds on the decision variables frac. Alternatively to this separate function call, we may also specify the bounds directly at the creation of the variables, but in this case we need to provide the full information including the name, variable type (XPRB_PL for continuous), lower and upper bound values:
for(s=0;s<NSHARES;s++) frac[s] = p.newVar("frac", XPRB_PL, 0, 0.3);
Giving string names to modeling objects (decision variables, constraints, etc.) as shown in our example program is optional. If the user does not specify any name, BCL will generate a default name. However, user-defined names may be helpful for debugging and for the interpretation of output produced by the Optimizer.
Solving
Prior to launching the solver, the optimization direction is set to maximization with a call to setSense. With the method lpOptimize we then call Xpress Optimizer to maximize the objective function (Return) set with the method setObj, subject to all constraints that have been defined. The empty string argument of lpOptimize indicates that the default LP algorithm is to be used. Other possible values are "p" for primal, "d" for dual Simplex, and "b" for Newton-Barrier.
Output printing
The last few lines print out the value of the optimal solution and the solution values for all variables.
© 2001-2019 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.