foliolp.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliolp.cpp
````````````````
Modeling a small LP problem
to perform portfolio optimization.
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#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"); //, XPRB_PL, 0, 0.3);
// 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);
/* Equivalent:
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);
*/
// 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);
// Export matrix to a file
/* p.exportProb(XPRB_MPS, "Folio");
p.setSense(XPRB_MAXIM);
p.exportProb(XPRB_LP, "Folio");
*/
// Disable all BCL and Optimizer message printing, except error messages
// p.setMsgLevel(1);
// Solve the problem
p.setSense(XPRB_MAXIM);
p.lpOptimize("");
char *LPSTATUS[] = {"not loaded", "optimal", "infeasible",
"worse than cutoff", "unfinished", "unbounded", "cutoff in dual",
"unsolved", "nonconvex"};
cout << "Problem status: " << LPSTATUS[p.getLPStat()] << endl;
// Solution printing
cout << "Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
return 0;
}
|
|
folioinit.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioinit.cpp
``````````````````
Modeling a small LP problem
to perform portfolio optimization.
Explicit initialization.
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#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
void solveProb()
{
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("");
char *LPSTATUS[] = {"not loaded", "optimal", "infeasible",
"worse than cutoff", "unfinished", "unbounded", "cutoff in dual",
"unsolved", "nonconvex"};
cout << "Problem status: " << LPSTATUS[p.getLPStat()] << endl;
// Solution printing
cout << "Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
}
int main(int argc, char **argv)
{
if(XPRB::init() != 0)
{
cout << "Initialization failed." << endl;
return 1;
}
solveProb();
return 0;
}
|
|
foliodata.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliodata.cpp
``````````````````
Modeling a small LP problem
to perform portfolio optimization.
-- Data input from file --
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include "xprb_cpp.h"
using namespace std;
using namespace ::dashoptimization;
#define DATAFILE XPRBDATAPATH "/GS/foliocpplp.dat"
#define NSHARES 10 // Number of shares
#define NRISK 5 // Number of high-risk shares
#define NNA 4 // Number of North-American shares
double RET[NSHARES]; // Estimated return in investment
char RISK[][100] = {"hardware", "theater", "telecom", "software",
"electronics"}; // High-risk values among shares
char NA[][100] = {"treasury", "hardware", "theater", "telecom"};
// Shares issued in N.-America
XPRBindexSet SHARES; // Set of shares
XPRBprob p("FolioLP"); // Initialize a new problem in BCL
void readData(void)
{
double value;
int s;
FILE *datafile;
char name[100];
SHARES=p.newIndexSet("Shares",NSHARES); // Create the `SHARES' index set
// Read `RET' data from file
datafile=fopen(DATAFILE,"r");
for(s=0;s<NSHARES;s++)
{
XPRBreadlinecb(XPRB_FGETS, datafile, 200, "T g", name, &value);
RET[SHARES+=name]=value;
}
fclose(datafile);
SHARES.print(); // Print out the set contents
}
int main(int argc, char **argv)
{
int s;
XPRBexpr Risk,Na,Return,Cap;
XPRBvar frac[NSHARES]; // Fraction of capital used per share
// Read data from file
readData();
// 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[SHARES[RISK[s]]];
p.newCtr("Risk", Risk <= 1.0/3);
// Minimum amount of North-American values
for(s=0;s<NNA;s++) Na += frac[SHARES[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 << SHARES[s] << ": " << frac[s].getSol()*100 << "%" << endl;
return 0;
}
|
|
foliomip1.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliomip1.cpp
``````````````````
Modeling a small MIP problem
to perform portfolio optimization.
-- Limiting the total number of assets --
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#include <iostream>
#include "xprb_cpp.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 4 // Max. number of different assets
#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("FolioMIP1"); // Initialize a new problem in BCL
XPRBexpr Risk,Na,Return,Cap,Num;
XPRBvar frac[NSHARES]; // Fraction of capital used per share
XPRBvar buy[NSHARES]; // 1 if asset is in portfolio, 0 otherwise
// Create the decision variables (including upper bounds for `frac')
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, 0.3);
buy[s] = p.newVar("buy", XPRB_BV);
}
// 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 <= 1.0/3);
// Minimum amount of North-American values
for(s=0;s<NNA;s++) Na += frac[NA[s]];
p.newCtr(Na >= 0.5);
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++) p.newCtr(frac[s] <= buy[s]);
// Solve the problem
p.setSense(XPRB_MAXIM);
p.mipOptimize("");
char *MIPSTATUS[] = {"not loaded", "not optimized", "LP optimized",
"unfinished (no solution)",
"unfinished (solution found)", "infeasible", "optimal",
"unbounded"};
cout << "Problem status: " << MIPSTATUS[p.getMIPStat()] << endl;
// Solution printing
cout << "Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "% (" << buy[s].getSol()
<< ")" << endl;
return 0;
}
|
|
foliomip2.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliomip2.cpp
``````````````````
Modeling a small MIP problem
to perform portfolio optimization.
-- Imposing a minimum investment per share --
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#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("FolioSC"); // 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", XPRB_SC, 0, 0.3);
frac[s].setLim(0.1);
}
// 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 <= 1.0/3);
// Minimum amount of North-American values
for(s=0;s<NNA;s++) Na += frac[NA[s]];
p.newCtr(Na >= 0.5);
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Solve the problem
p.setSense(XPRB_MAXIM);
p.mipOptimize("");
// Solution printing
cout << "Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
return 0;
}
|
|
folioqp.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioqp.cpp
````````````````
Modeling a small QP problem
to perform portfolio optimization.
-- 1. QP: minimize variance
2. MIQP: limited number of assets ---
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include "xprb_cpp.h"
using namespace std;
using namespace ::dashoptimization;
#define DATAFILE XPRBDATAPATH "/GS/foliocppqp.dat"
#define TARGET 9 // Target yield
#define MAXNUM 4 // Max. number of different assets
#define NSHARES 10 // Number of 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 NA[] = {0,1,2,3}; // Shares issued in N.-America
double VAR[NSHARES][NSHARES]; // Variance/covariance matrix of
// estimated returns
int main(int argc, char **argv)
{
int s,t;
XPRBprob p("FolioQP"); // Initialize a new problem in BCL
XPRBexpr Na,Return,Cap,Num,Variance;
XPRBvar frac[NSHARES]; // Fraction of capital used per share
XPRBvar buy[NSHARES]; // 1 if asset is in portfolio, 0 otherwise
FILE *datafile;
// Read `VAR' data from file
datafile=fopen(DATAFILE,"r");
for(s=0;s<NSHARES;s++)
XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g ", VAR[s], NSHARES);
fclose(datafile);
// **** First problem: unlimited number of assets ****
// Create the decision variables
for(s=0;s<NSHARES;s++)
frac[s] = p.newVar(XPRBnewname("frac(%d)",s+1), XPRB_PL, 0, 0.3);
// Objective: mean variance
for(s=0;s<NSHARES;s++)
for(t=0;t<NSHARES;t++) Variance += VAR[s][t]*frac[s]*frac[t];
p.setObj(Variance); // Set the objective function
// Minimum amount of North-American values
for(s=0;s<NNA;s++) Na += frac[NA[s]];
p.newCtr(Na >= 0.5);
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Target yield
for(s=0;s<NSHARES;s++) Return += RET[s]*frac[s];
p.newCtr(Return >= TARGET);
// Solve the problem
p.setSense(XPRB_MINIM);
p.lpOptimize("");
// Solution printing
cout << "With a target of " << TARGET << " minimum variance is " <<
p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
// **** Second problem: limit total number of assets ****
// Create the decision variables
for(s=0;s<NSHARES;s++)
buy[s] = p.newVar(XPRBnewname("buy(%d)",s+1), XPRB_BV);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++) p.newCtr(frac[s] <= buy[s]);
// Solve the problem
p.mipOptimize("");
// Solution printing
cout << "With a target of " << TARGET << " and at most " << MAXNUM <<
" assets, minimum variance is " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "% (" << buy[s].getSol()
<< ")" << endl;
return 0;
}
|
|
folioqc.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioqp.cpp
````````````````
Modeling a small QCQP problem
to perform portfolio optimization.
-- Maximize return with limit on variance ---
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, July 2008, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include "xprb_cpp.h"
using namespace std;
using namespace ::dashoptimization;
#define DATAFILE XPRBDATAPATH "/GS/foliocppqp.dat"
#define MAXVAR 0.55 // Max. allowed variance
#define NSHARES 10 // Number of 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 NA[] = {0,1,2,3}; // Shares issued in N.-America
double VAR[NSHARES][NSHARES]; // Variance/covariance matrix of
// estimated returns
int main(int argc, char **argv)
{
int s,t;
XPRBprob p("FolioQC"); // Initialize a new problem in BCL
XPRBexpr Na,Return,Cap,Variance;
XPRBvar frac[NSHARES]; // Fraction of capital used per share
FILE *datafile;
// Read `VAR' data from file
datafile=fopen(DATAFILE,"r");
for(s=0;s<NSHARES;s++)
XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g ", VAR[s], NSHARES);
fclose(datafile);
// Create the decision variables
for(s=0;s<NSHARES;s++)
frac[s] = p.newVar(XPRBnewname("frac(%d)",s+1), XPRB_PL, 0, 0.3);
// Objective: total return
for(s=0;s<NSHARES;s++) Return += RET[s]*frac[s];
p.setObj(Return); // Set the objective function
// Minimum amount of North-American values
for(s=0;s<NNA;s++) Na += frac[NA[s]];
p.newCtr(Na >= 0.5);
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit variance
for(s=0;s<NSHARES;s++)
for(t=0;t<NSHARES;t++) Variance += VAR[s][t]*frac[s]*frac[t];
p.newCtr(Variance <= MAXVAR);
// Solve the problem
p.setSense(XPRB_MAXIM);
p.lpOptimize("");
// Solution printing
cout << "With a max. variance of " << MAXVAR << " total return is " <<
p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
return 0;
}
|
|
folioheur.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioheur.cpp
``````````````````
Modeling a small MIP problem
to perform portfolio optimization.
-- Heuristic solution --
(c) 2008 Fair Isaac Corporation
author: S.Heipcke, Aug. 2003, rev. Mar. 2011
********************************************************/
#include <iostream>
#include "xprb_cpp.h"
#include "xprs.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 4 // Max. number of shares to be selected
#define NSHARES 10 // Number of shares
#define NRISK 5 // Number of high-risk shares
#define NNA 4 // Number of North-American shares
void solveHeur();
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
XPRBprob p("FolioMIPHeur"); // Initialize a new problem in BCL
XPRBvar frac[NSHARES]; // Fraction of capital used per share
XPRBvar buy[NSHARES]; // 1 if asset is in portfolio, 0 otherwise
int main(int argc, char **argv)
{
int s;
XPRBexpr Risk,Na,Return,Cap,Num;
// Create the decision variables (including upper bounds for `frac')
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, 0.3);
buy[s] = p.newVar("buy", XPRB_BV);
}
// 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 <= 1.0/3);
// Minimum amount of North-American values
for(s=0;s<NNA;s++) Na += frac[NA[s]];
p.newCtr(Na >= 0.5);
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++) p.newCtr(frac[s] <= buy[s]);
// Solve problem heuristically
p.setSense(XPRB_MAXIM);
solveHeur();
// Solve the problem
p.mipOptimize("");
// Solution printing
if(p.getMIPStat()==XPRB_MIP_SOLUTION || p.getMIPStat()==XPRB_MIP_OPTIMAL)
{
cout << "Exact solution: Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
}
else
cout << "Heuristic solution is optimal." << endl;
return 0;
}
void solveHeur()
{
XPRBbasis basis;
int s, ifgsol;
double solval, fsol[NSHARES],TOL;
XPRSsetintcontrol(p.getXPRSprob(), XPRS_CUTSTRATEGY, 0);
// Disable automatic cuts
XPRSsetintcontrol(p.getXPRSprob(), XPRS_PRESOLVE, 0);
// Switch presolve off
XPRSgetdblcontrol(p.getXPRSprob(), XPRS_FEASTOL, &TOL);
// Get feasibility tolerance
p.mipOptimize("l"); // Solve the LP-relaxation
basis=p.saveBasis(); // Save the current basis
// Fix all variables `buy' for which `frac' is at 0 or at a relatively
// large value
for(s=0;s<NSHARES;s++)
{
fsol[s]=frac[s].getSol(); // Get the solution values of `frac'
if(fsol[s] < TOL) buy[s].setUB(0);
else if(fsol[s] > 0.2-TOL) buy[s].setLB(1);
}
p.mipOptimize("c"); // Solve the MIP-problem
ifgsol=0;
if(p.getMIPStat()==XPRB_MIP_SOLUTION || p.getMIPStat()==XPRB_MIP_OPTIMAL)
{ // If an integer feas. solution was found
ifgsol=1;
solval=p.getObjVal(); // Get the value of the best solution
cout << "Heuristic solution: Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
cout << s << ": " << frac[s].getSol()*100 << "%" << endl;
}
// XPRSpostsolve(p.getXPRSprob()); // Re-initialize the global search
// Reset variables to their original bounds
for(s=0;s<NSHARES;s++)
if((fsol[s] < TOL) || (fsol[s] > 0.2-TOL))
{
buy[s].setLB(0);
buy[s].setUB(1);
}
p.loadBasis(basis); /* Load the saved basis: bound changes are
immediately passed on from BCL to the
Optimizer if the problem has not been modified
in any other way, so that there is no need to
reload the matrix */
basis.reset(); // No need to store the saved basis any longer
if(ifgsol==1)
XPRSsetdblcontrol(p.getXPRSprob(), XPRS_MIPABSCUTOFF, solval+TOL);
// Set the cutoff to the best known solution
}
|
|
foliomip3.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliomip3.cpp
``````````````````
Modeling a MIP problem
to perform portfolio optimization.
-- Extending the problem with constraints on
the geographical and sectorial distributions --
-- Working with a larger data set --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, May 2009, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include "xprb_cpp.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 7 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.2 // Min. investment per geogr. region
#define MAXREG 0.5 // Max. investment per geogr. region
#define MAXSEC 0.25 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
#include "readfoliodata.c_"
int main(int argc, char **argv)
{
int s,r,t;
XPRBprob p("FolioMIP3"); // Initialize a new problem in BCL
XPRBexpr Risk,Return,Cap,Num;
XPRBexpr *MinReg, *MaxReg, *LimSec, LinkL, LinkU;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// 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 <= MAXRISK);
// Limits on geographical distribution
MinReg = new XPRBexpr[NREGIONS];
MaxReg = new XPRBexpr[NREGIONS];
for(r=0;r<NREGIONS;r++)
{
for(s=0;s<NSHARES;s++)
if(LOC[r][s]>0)
{
MinReg[r] += frac[s];
MaxReg[r] += frac[s];
}
p.newCtr(MinReg[r] >= MINREG);
p.newCtr(MaxReg[r] <= MAXREG);
}
// Diversification across industry sectors
LimSec = new XPRBexpr[NTYPES];
for(t=0;t<NTYPES;t++)
{
for(s=0;s<NSHARES;s++)
if(SECT[t][s]>0) LimSec[t] += frac[s];
p.newCtr(LimSec[t] <= MAXSEC);
}
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++)
{
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Solve the problem
p.setSense(XPRB_MAXIM);
p.mipOptimize("");
char *MIPSTATUS[] = {"not loaded", "not optimized", "LP optimized",
"unfinished (no solution)",
"unfinished (solution found)", "infeasible", "optimal",
"unbounded"};
cout << "Problem status: " << MIPSTATUS[p.getMIPStat()] << endl;
// Solution printing
cout << "Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
if(buy[s].getSol()>0.5)
cout << SHARES_n[s] << ": " << frac[s].getSol()*100 << "% (" << buy[s].getSol()
<< ")" << endl;
return 0;
}
|
|
readfoliodata.c_ |
/********************************************************
Xpress-BCL C Example Problems
=============================
file readfoliodata.c_
`````````````````````
Include file reading data for model foliomip3
from a text file.
(c) 2009 Fair Isaac Corporation
author: Y.Colombani, May 2009
********************************************************/
/****************************************************/
/* Skip empty lines & comments and find next record */
/****************************************************/
int nextrec(FILE *f,char *rec)
{
int c;
do
{
c=fgetc(f);
if(c==EOF) return 0;
else
if(c=='!')
{
do
{
c=fgetc(f);
if(c==EOF) return 0;
}
while(c!='\n');
}
} while (isspace(c));
rec[0]=c;
return fscanf(f,"%128s",rec+1);
}
/***************************/
/* Input a list of strings */
/***************************/
int read_str_list(FILE *f,char ***list,int *size)
{
int n;
char word[128];
char *buf[MAXENTRIES];
n=0;
while(fscanf(f,"%128s",word)>0)
if(strcmp(word,";")==0) break;
else
if(word[strlen(word)-1]==';')
{
word[strlen(word)-1]='\0';
buf[n++]=strdup(word);
break;
}
else
buf[n++]=strdup(word);
*size=n;
*list=(char **)malloc(sizeof(char *)*n);
memcpy(*list,buf,sizeof(char *)*n);
return 0;
}
/************************/
/* Input a list of ints */
/************************/
int read_int_list(FILE *f,int **list,int *size)
{
int n,c;
int word;
int buf[MAXENTRIES];
n=0;
while(fscanf(f,"%d",&word)>0)
buf[n++]=word;
do
{
c=fgetc(f);
} while(isspace(c));
*size=n;
*list=(int *)malloc(sizeof(int)*n);
memcpy(*list,buf,sizeof(int)*n);
return 0;
}
/****************************/
/* Input a table of doubles */
/****************************/
int read_dbl_table(FILE *f,double **table,int size)
{
int n,c;
*table=(double *)malloc(sizeof(double)*size);
for(n=0;n<size;n++)
if(fscanf(f,"%lf",(*table)+n)<1) exit(1);
do
{
c=fgetc(f);
} while(isspace(c));
return 0;
}
/************************************/
/* Input a sparse table of booleans */
/************************************/
int read_bool_table(FILE *f,char ***table,int nrow,int ncol)
{
int r,c,i;
char **tbl;
*table=tbl=(char **)malloc(sizeof(char*)*nrow);
tbl[0]=(char*)malloc(sizeof(char)*ncol*nrow);
memset(tbl[0],0,sizeof(char)*ncol*nrow);
for(r=0;r<nrow;r++)
{
if(r>0) tbl[r]=tbl[r-1]+ncol;
while(fscanf(f,"%d",&i)>0)
tbl[r][i]=1;
do
{
c=fgetc(f);
} while(isspace(c));
}
return 0;
}
int readdata(const char *filename)
{
FILE *f;
char rec[128];
f=fopen(filename,"r");
if(f==NULL) return 1;
while(nextrec(f,rec)>0)
{
if(strcmp(rec,"SHARES:")==0 && NSHARES==0)
read_str_list(f,&SHARES_n,&NSHARES);
else
if(strcmp(rec,"REGIONS:")==0 && NREGIONS==0)
read_str_list(f,®IONS_n,&NREGIONS);
else
if(strcmp(rec,"TYPES:")==0 && NTYPES==0)
read_str_list(f,&TYPES_n,&NTYPES);
else
if(strcmp(rec,"RISK:")==0 && NRISK==0)
read_int_list(f,&RISK,&NRISK);
else
if(strcmp(rec,"RET:")==0 && NSHARES>0)
read_dbl_table(f,&RET,NSHARES);
else
if(strcmp(rec,"LOC:")==0 && NSHARES>0 && NREGIONS>0)
read_bool_table(f,&LOC,NREGIONS,NSHARES);
else
if(strcmp(rec,"SEC:")==0 && NSHARES>0 && NTYPES>0)
read_bool_table(f,&SECT,NTYPES,NSHARES);
else
break;
}
fclose(f);
return NSHARES<1 || NRISK<1 || NREGIONS<1 || NTYPES<1 ||
RET==NULL || RISK==NULL || LOC==NULL || SECT==NULL;
}
void testprintout(void)
{
int i,j;
printf("Shares(%d):",NSHARES);
for(i=0;i<NSHARES;i++) printf("%s ",SHARES_n[i]); printf("\n");
printf("Regions(%d):",NREGIONS);
for(i=0;i<NREGIONS;i++) printf("%s ",REGIONS_n[i]); printf("\n");
printf("Types(%d):",NTYPES);
for(i=0;i<NTYPES;i++) printf("%s ",TYPES_n[i]); printf("\n");
printf("Risks(%d):",NRISK);
for(i=0;i<NRISK;i++) printf("%d ",RISK[i]); printf("\n");
printf("RET:");
for(i=0;i<NSHARES;i++) printf("%g ",RET[i]); printf("\n");
printf("LOC:");
for(i=0;i<NREGIONS;i++)
{
for(j=0;j<NSHARES;j++)
printf(" %d",LOC[i][j]);
printf("\n");
}
printf("SECT:");
for(i=0;i<NTYPES;i++)
{
for(j=0;j<NSHARES;j++)
printf(" %d",SECT[i][j]);
printf("\n");
}
}
|
|
foliocb.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliocb.cpp
````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cpp.
-- Defining an integer solution callback --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, May 2009, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include "xprb_cpp.h"
#include "xprs.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 15 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.2 // Min. investment per geogr. region
#define MAXREG 0.5 // Max. investment per geogr. region
#define MAXSEC 0.25 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
#include "readfoliodata.c_"
void XPRS_CC print_sol(XPRSprob oprob, void *vp);
int main(int argc, char **argv)
{
int s,r,t;
XPRBprob p("FolioMIP3"); // Initialize a new problem in BCL
XPRBexpr Risk,Return,Cap,Num;
XPRBexpr *MinReg, *MaxReg, *LimSec, LinkL, LinkU;
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// 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 <= MAXRISK);
// Limits on geographical distribution
MinReg = new XPRBexpr[NREGIONS];
MaxReg = new XPRBexpr[NREGIONS];
for(r=0;r<NREGIONS;r++)
{
for(s=0;s<NSHARES;s++)
if(LOC[r][s]>0)
{
MinReg[r] += frac[s];
MaxReg[r] += frac[s];
}
p.newCtr(MinReg[r] >= MINREG);
p.newCtr(MaxReg[r] <= MAXREG);
}
// Diversification across industry sectors
LimSec = new XPRBexpr[NTYPES];
for(t=0;t<NTYPES;t++)
{
for(s=0;s<NSHARES;s++)
if(SECT[t][s]>0) LimSec[t] += frac[s];
p.newCtr(LimSec[t] <= MAXSEC);
}
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++)
{
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Define an integer solution callback
XPRSsetcbintsol(p.getXPRSprob(), print_sol, &p);
// Solve the problem
p.setSense(XPRB_MAXIM);
p.mipOptimize("");
char *MIPSTATUS[] = {"not loaded", "not optimized", "LP optimized",
"unfinished (no solution)",
"unfinished (solution found)", "infeasible", "optimal",
"unbounded"};
cout << "Problem status: " << MIPSTATUS[p.getMIPStat()] << endl;
return 0;
}
/**************************Solution printing****************************/
void XPRS_CC print_sol(XPRSprob oprob, void *vp)
{
int num,s;
XPRBprob *bprob;
bprob = (XPRBprob *)vp;
bprob->beginCB(oprob);
XPRSgetintattrib(oprob, XPRS_MIPSOLS, &num); // Get number of the solution
bprob->sync(XPRB_XPRS_SOL); // Update BCL solution values
cout << "Solution " << num << ": Total return: " << bprob->getObjVal() << endl;
for(s=0;s<NSHARES;s++)
if(buy[s].getSol()>0.5)
cout << " " << SHARES_n[s] << ": " << frac[s].getSol()*100 << "% (" <<
buy[s].getSol() << ")" << endl;
bprob->endCB();
}
|
|
foliosolpool.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliosolpool.cpp
```````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cpp.
-- Using the MIP solution pool --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, May 2009, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include "xprb_cpp.h"
#include "xprs.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 7 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.2 // Min. investment per geogr. region
#define MAXREG 0.5 // Max. investment per geogr. region
#define MAXSEC 0.25 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
XPRBctr Return;
#include "readfoliodata.c_"
void print_sol(int num);
int main(int argc, char **argv)
{
int s,r,t;
XPRBprob p("FolioMIP3"); // Initialize a new problem in BCL
XPRBexpr Risk,Cap,Num,le;
XPRBexpr *MinReg, *MaxReg, *LimSec, LinkL, LinkU;
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// Objective: total return
for(s=0;s<NSHARES;s++) le += RET[s]*frac[s];
Return = p.newCtr(le);
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 <= MAXRISK);
// Limits on geographical distribution
MinReg = new XPRBexpr[NREGIONS];
MaxReg = new XPRBexpr[NREGIONS];
for(r=0;r<NREGIONS;r++)
{
for(s=0;s<NSHARES;s++)
if(LOC[r][s]>0)
{
MinReg[r] += frac[s];
MaxReg[r] += frac[s];
}
p.newCtr(MinReg[r] >= MINREG);
p.newCtr(MaxReg[r] <= MAXREG);
}
// Diversification across industry sectors
LimSec = new XPRBexpr[NTYPES];
for(t=0;t<NTYPES;t++)
{
for(s=0;s<NSHARES;s++)
if(SECT[t][s]>0) LimSec[t] += frac[s];
p.newCtr(LimSec[t] <= MAXSEC);
}
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++)
{
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Create a MIP solution pool and attach it to the problem
// (so it collects the solutions)
XPRSmipsolpool msp;
XPRS_msp_create(&msp);
XPRS_msp_probattach(msp, p.getXPRSprob());
// Avoid storing of duplicate solutions (3: compare discrete variables only)
XPRS_msp_setintcontrol(msp, XPRS_MSP_DUPLICATESOLUTIONSPOLICY, 3);
// Solve the problem
p.setSense(XPRB_MAXIM);
p.mipOptimize("");
// Setup some resources to iterate through the solutions stored
// in the MIP solution pool
int nSols, nCols, i;
double *xsol;
int *solIDs;
XPRSgetintattrib(p.getXPRSprob(), XPRS_ORIGINALCOLS, &nCols);
XPRS_msp_getintattrib(msp, XPRS_MSP_SOLUTIONS, &nSols);
xsol = (double *) malloc(nCols * sizeof(double));
solIDs = (int *) malloc(nSols * sizeof(int));
// Get the solution IDs
XPRS_msp_getsollist(msp, p.getXPRSprob(), XPRS_MSP_SOLPRB_OBJ, 1, 1,
nSols, solIDs, &nSols, NULL);
// Display all solutions from the pool
for(i=0; i<nSols; i++)
{ // Get the solution
XPRS_msp_getsol(msp, solIDs[i], NULL, xsol, 0, nCols - 1, NULL);
p.loadMIPSol(xsol, nCols, 0); // Load the solution into BCL
print_sol(i+1); // Display the solution
}
free(xsol);
XPRS_msp_destroy(msp);
return 0;
}
// Solution printing
void print_sol(int num)
{
int s;
cout << "Solution " << num << ": Total return: " << Return.getAct() << endl;
for(s=0;s<NSHARES;s++)
if(buy[s].getSol()>0.5)
cout << " " << SHARES_n[s] << ": " << frac[s].getSol()*100 << "% ("
<< buy[s].getSol() << ")" << endl;
}
|
|
folioenumsol.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioenumsol.cpp
`````````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cpp.
-- Using the solution enumerator --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, June 2009, rev. Jul. 2014
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include "xprb_cpp.h"
#include "xprs.h"
#include "xprs_mse_defaulthandler.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 7 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.2 // Min. investment per geogr. region
#define MAXREG 0.5 // Max. investment per geogr. region
#define MAXSEC 0.25 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
XPRBctr Return;
#include "readfoliodata.c_"
void print_sol(int num);
int main(int argc, char **argv)
{
int s,r,t;
XPRBprob p("FolioMIP3"); // Initialize a new problem in BCL
XPRBexpr Risk,Cap,Num,le;
XPRBexpr *MinReg, *MaxReg, *LimSec, LinkL, LinkU;
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// Objective: total return
for(s=0;s<NSHARES;s++) le += RET[s]*frac[s];
Return = p.newCtr(le);
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 <= MAXRISK);
// Limits on geographical distribution
MinReg = new XPRBexpr[NREGIONS];
MaxReg = new XPRBexpr[NREGIONS];
for(r=0;r<NREGIONS;r++)
{
for(s=0;s<NSHARES;s++)
if(LOC[r][s]>0)
{
MinReg[r] += frac[s];
MaxReg[r] += frac[s];
}
p.newCtr(MinReg[r] >= MINREG);
p.newCtr(MaxReg[r] <= MAXREG);
}
// Diversification across industry sectors
LimSec = new XPRBexpr[NTYPES];
for(t=0;t<NTYPES;t++)
{
for(s=0;s<NSHARES;s++)
if(SECT[t][s]>0) LimSec[t] += frac[s];
p.newCtr(LimSec[t] <= MAXSEC);
}
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
for(s=0;s<NSHARES;s++) Num += buy[s];
p.newCtr(Num <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++)
{
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Create a MIP solution pool & enumerator
XPRSmipsolpool msp;
XPRSmipsolenum mse;
XPRS_mse_create(&mse);
XPRS_msp_create(&msp);
// Load matrix into the Optimizer, then hand over to sol. enumerator
p.loadMat();
// Disable heuristics to avoid duplicate solutions being stored
XPRSsetintcontrol(p.getXPRSprob(), XPRS_HEURSTRATEGY, 0);
int nMaxSols = 15; // Max. number of solutions to return
// Solve the problem
XPRS_mse_maxim(mse, p.getXPRSprob(), msp, XPRS_mse_defaulthandler,
NULL, &nMaxSols);
// Setup some resources to iterate through the solutions stored
// in the MIP solution pool
int nSols, nCols, i;
double *xsol;
int *solIDs;
XPRSgetintattrib(p.getXPRSprob(), XPRS_ORIGINALCOLS, &nCols);
XPRS_mse_getintattrib(mse, XPRS_MSE_SOLUTIONS, &nSols);
xsol = (double *) malloc(nCols * sizeof(double));
solIDs = (int *) malloc(nSols * sizeof(int));
// Get the solution IDs
XPRS_mse_getsollist(mse, XPRS_MSE_METRIC_MIPOBJECT, 1, nSols,
solIDs, &nSols, NULL);
// Display all solutions from the pool
for(i=0; i<nSols; i++)
{ // Get the solution
XPRS_msp_getsol(msp, solIDs[i], NULL, xsol, 0, nCols - 1, NULL);
p.loadMIPSol(xsol, nCols, 0); // Load the solution into BCL
print_sol(i+1); // Display the solution
}
free(xsol);
XPRS_mse_destroy(mse);
XPRS_msp_destroy(msp);
return 0;
}
// Solution printing
void print_sol(int num)
{
int s;
cout << "Solution " << num << ": Total return: " << Return.getAct() << endl;
for(s=0;s<NSHARES;s++)
if(buy[s].getSol()>0.5)
cout << " " << SHARES_n[s] << ": " << frac[s].getSol()*100 << "% (" << buy[s].getSol()
<< ")" << endl;
}
|
|
folioinfeas.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioinfeas.cpp
````````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cpp.
-- Infeasible model parameter values --
-- Handling infeasibility through auxiliary variables --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, June 2009, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include "xprb_cpp.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 4 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.3 // Min. investment per geogr. region
#define MAXREG 0.5 // Max. investment per geogr. region
#define MAXSEC 0.15 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
#include "readfoliodata.c_"
int main(int argc, char **argv)
{
int s,r,t;
XPRBprob p("FolioMIP3"); // Initialize a new problem in BCL
XPRBctr Risk,Return,Num,*MinReg, *MaxReg, *LimSec;
XPRBexpr le, le2, Cap, LinkL, LinkU;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// Objective: total return
for(s=0;s<NSHARES;s++) le += RET[s]*frac[s];
Return = p.newCtr(le);
p.setObj(Return); // Set the objective function
// Limit the percentage of high-risk values
le=0;
for(s=0;s<NRISK;s++) le += frac[RISK[s]];
Risk = p.newCtr(le <= MAXRISK);
// Limits on geographical distribution
MinReg = new XPRBctr[NREGIONS];
MaxReg = new XPRBctr[NREGIONS];
for(r=0;r<NREGIONS;r++)
{
le=0; le2=0;
for(s=0;s<NSHARES;s++)
if(LOC[r][s]>0)
{
le += frac[s];
le2 += frac[s];
}
MinReg[r] = p.newCtr(le >= MINREG);
MaxReg[r] = p.newCtr(le2 <= MAXREG);
}
// Diversification across industry sectors
LimSec = new XPRBctr[NTYPES];
for(t=0;t<NTYPES;t++)
{
le=0;
for(s=0;s<NSHARES;s++)
if(SECT[t][s]>0) le += frac[s];
LimSec[t] = p.newCtr(le <= MAXSEC);
}
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr(Cap == 1);
// Limit the total number of assets
le=0;
for(s=0;s<NSHARES;s++) le += buy[s];
Num = p.newCtr(le <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++)
{
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Solve the problem
p.setSense(XPRB_MAXIM);
p.mipOptimize("");
char *MIPSTATUS[] = {"not loaded", "not optimized", "LP optimized",
"unfinished (no solution)",
"unfinished (solution found)", "infeasible", "optimal",
"unbounded"};
cout << "Problem status: " << MIPSTATUS[p.getMIPStat()] << endl;
if (p.getMIPStat()==XPRB_MIP_INFEAS)
{
cout << "Original problem infeasible. Adding deviation variables" << endl;
// Define deviation variables and add them to the constraints
// to make problem solvable */
XPRBvar devRisk, devNum, *devMinReg, *devMaxReg, *devSec;
devRisk = p.newVar("devRisk");
Risk -= devRisk;
devMinReg = new XPRBvar[NREGIONS];
devMaxReg = new XPRBvar[NREGIONS];
for(r=0;r<NREGIONS;r++)
{ /* Only allow small deviations */
devMinReg[r] = p.newVar("devMinReg", XPRB_PL, 0, MAXREG/2);
MinReg[r] += devMinReg[r];
devMaxReg[r] = p.newVar("devMaxReg", XPRB_PL, 0, MAXREG/2);
MaxReg[r] -= devMaxReg[r];
}
devSec = new XPRBvar[NTYPES];
for(t=0;t<NTYPES;t++)
{
devSec[t] = p.newVar("devSec", XPRB_PL, 0, MAXSEC/2);
LimSec[t] -= devSec[t];
}
devNum = p.newVar("devNum", XPRB_PL, 0, XPRB_INFINITY);
Num -= devNum;
/* Resolve the problem with penalty terms added to the objective */
double penalty = -10;
Return += devRisk * penalty;
for(r=0;r<NREGIONS;r++) Return += (devMinReg[r]+devMaxReg[r]) * penalty;
for(t=0;t<NTYPES;t++) Return += devSec[t] * penalty;
Return += devNum * penalty;
p.setObj(Return); /* Set the new objective function */
p.mipOptimize("");
if (p.getMIPStat()== XPRB_MIP_INFEAS)
{
cout << "No solution after relaxation" << endl;
return 0;
}
else
{
cout << "Constraint violations:" << endl;
cout << " Constraint Activity Deviation Bound(s)" << endl;
printf(" Risk %1.2f\t %1.2f\t (%1.2f)\n",
Risk.getAct()+devRisk.getSol(), devRisk.getSol(), MAXRISK);
for(r=0;r<NREGIONS;r++)
{
double sumf=0;
for(s=0;s<NSHARES;s++) if(LOC[r][s]>0) sumf+=frac[s].getSol();
printf(" Region %-11s %1.2f\t %1.2f\t (%g-%g)\n", REGIONS_n[r], sumf,
devMaxReg[r].getSol()-devMinReg[r].getSol(),
MINREG, MAXREG);
}
for(t=0;t<NTYPES;t++)
{
printf(" Sector %-14s %1.2f\t %1.2f\t (%g)\n", TYPES_n[t],
LimSec[t].getAct()+devSec[t].getSol(), devSec[t].getSol(),
MAXSEC);
}
printf(" Number of assets %1.2f\t %1.2f\t (%d)\n",
Num.getAct()+devNum.getSol(), devNum.getSol(), MAXNUM);
}
}
// Solution printing
cout << "Total return: " << p.getObjVal() << endl;
for(s=0;s<NSHARES;s++)
if(buy[s].getSol()>0.5)
cout << SHARES_n[s] << ": " << frac[s].getSol()*100 << "% (" << buy[s].getSol()
<< ")" << endl;
return 0;
}
|
|
folioiis.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file folioiis.cpp
`````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cpp.
-- Infeasible model parameter values --
-- Retrieving IIS --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, June 2009, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include "xprb_cpp.h"
#include "xprs.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 5 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.1 // Min. investment per geogr. region
#define MAXREG 0.2 // Max. investment per geogr. region
#define MAXSEC 0.1 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
#include "readfoliodata.c_"
int main(int argc, char **argv)
{
int s,r,t;
XPRBprob p("FolioMIP3inf"); // Initialize a new problem in BCL
XPRBctr Risk,Return,Num,*MinReg, *MaxReg, *LimSec;
XPRBexpr le, le2, Cap, LinkL, LinkU;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for(s=0;s<NSHARES;s++)
{
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// Objective: total return
for(s=0;s<NSHARES;s++) le += RET[s]*frac[s];
Return = p.newCtr(le);
p.setObj(Return); // Set the objective function
// Limit the percentage of high-risk values
le=0;
for(s=0;s<NRISK;s++) le += frac[RISK[s]];
Risk = p.newCtr("Risk", le <= MAXRISK);
// Limits on geographical distribution
MinReg = new XPRBctr[NREGIONS];
MaxReg = new XPRBctr[NREGIONS];
for(r=0;r<NREGIONS;r++)
{
le=0; le2=0;
for(s=0;s<NSHARES;s++)
if(LOC[r][s]>0)
{
le += frac[s];
le2 += frac[s];
}
MinReg[r] = p.newCtr(XPRBnewname("MinReg(%s)",REGIONS_n[r]), le >= MINREG);
MaxReg[r] = p.newCtr(XPRBnewname("MaxReg(%s)",REGIONS_n[r]), le2 <= MAXREG);
}
// Diversification across industry sectors
LimSec = new XPRBctr[NTYPES];
for(t=0;t<NTYPES;t++)
{
le=0;
for(s=0;s<NSHARES;s++)
if(SECT[t][s]>0) le += frac[s];
LimSec[t] = p.newCtr(XPRBnewname("LimSec(%s)",TYPES_n[t]), le <= MAXSEC);
}
// Spend all the capital
for(s=0;s<NSHARES;s++) Cap += frac[s];
p.newCtr("Cap", Cap == 1);
// Limit the total number of assets
le=0;
for(s=0;s<NSHARES;s++) le += buy[s];
Num = p.newCtr("Num", le <= MAXNUM);
// Linking the variables
for(s=0;s<NSHARES;s++)
{
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Solve the problem (LP)
p.setSense(XPRB_MAXIM);
p.lpOptimize("");
if (p.getLPStat()==XPRB_LP_INFEAS)
{
cout << "LP infeasible. Retrieving IIS." << endl;
int numiis = p.getNumIIS(); // Get the number of independent IIS
cout << "Number of IIS: " << numiis << endl;
XPRSprob op = p.getXPRSprob(); // Retrieve the Optimizer problem
/**** Obtain variable and constraint names for use in printout ****/
int ncol, nrow, len, numc, numv, i;
char *vnames, *cnames;
int *viis,*ciis;
char **vindex,**cindex;
// Retrieve variable names
XPRSgetintattrib(op, XPRS_ORIGINALCOLS, &ncol);
XPRSgetnamelist(op, 2, NULL, 0, &len, 0, ncol-1);
// Get number of bytes required for retrieving names
vnames = new char[len];
vindex = new char*[ncol];
XPRSgetnamelist(op, 2, vnames, len, NULL, 0, ncol-1);
vindex[0]=vnames;
for(i=1; i<ncol; i++) vindex[i] =vindex[i-1]+strlen(vindex[i-1])+1;
// Retrieve constraint names
XPRSgetintattrib(op, XPRS_ORIGINALROWS, &nrow);
XPRSgetnamelist(op, 1, NULL, 0, &len, 0, nrow-1);
cnames = new char[len];
cindex = new char*[nrow];
XPRSgetnamelist(op, 1, cnames, len, NULL, 0, nrow-1);
cindex[0]=cnames;
for(i=1; i<nrow; i++) cindex[i] =cindex[i-1]+strlen(cindex[i-1])+1;
/**** Retrieve variables and constraints contained in IIS ****/
for(s=1;s<=numiis;s++)
{
XPRSgetiisdata(op, s, &numc, &numv, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL);
ciis = new int[numc];
viis = new int[numv];
XPRSgetiisdata(op, s, &numc, &numv, ciis, viis, NULL, NULL,
NULL, NULL, NULL, NULL);
cout << "IIS " << s << ": " << numv << " variables, ";
cout << numc << " constraints" << endl;
if (numv>0)
{
cout << " Variables: "; // Print all variables in the IIS
for(i=0;i<numv;i++) cout << vindex[viis[i]] << " ";
cout << endl;
delete [] viis; // Free the array of variables
}
if (numc>0)
{
cout << " Constraints: "; // Print all constraints in the IIS
for(i=0;i<numc;i++) cout << cindex[ciis[i]] << " ";
cout << endl;
delete [] ciis; // Free the array of constraints
}
}
delete [] vnames;
delete [] cnames;
delete [] vindex;
delete [] cindex;
}
return 0;
}
|
|
foliorep.cpp |
/********************************************************
Xpress-BCL C++ Example Problems
===============================
file foliorep.cpp
`````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cpp.
-- Infeasible model parameter values --
-- Repairing infeasibilities --
(c) 2009 Fair Isaac Corporation
author: S.Heipcke, June 2009, rev. Mar. 2011
********************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include "xprb_cpp.h"
#include "xprs.h"
using namespace std;
using namespace ::dashoptimization;
#define MAXNUM 4 // Max. number of different assets
#define MAXRISK 1.0/3 // Max. investment into high-risk values
#define MINREG 0.3 // Min. investment per geogr. region
#define MAXREG 0.5 // Max. investment per geogr. region
#define MAXSEC 0.15 // Max. investment per ind. sector
#define MAXVAL 0.2 // Max. investment per share
#define MINVAL 0.1 // Min. investment per share
#define DATAFILE "folio10.cdat" // File with problem data
#define MAXENTRIES 10000
int NSHARES; // Number of shares
int NRISK; // Number of high-risk shares
int NREGIONS; // Number of geographical regions
int NTYPES; // Number of share types
double *RET; // Estimated return in investment
int *RISK; // High-risk values among shares
char **LOC; // Geogr. region of shares
char **SECT; // Industry sector of shares
char **SHARES_n;
char **REGIONS_n;
char **TYPES_n;
XPRBvar *frac; // Fraction of capital used per share
XPRBvar *buy; // 1 if asset is in portfolio, 0 otherwise
#include "readfoliodata.c_"
void print_sol_opt(XPRBprob &p);
void print_violated(vector<XPRBctr> &ctrs);
int main(int argc, char **argv)
{
int s, r, t;
XPRBprob p("FolioMIP3inf"); // Initialize a new problem in BCL
XPRBctr Return, *Risk, *Num, *MinReg, *MaxReg, *LimSec;
XPRBexpr le, le2, Cap, LinkL, LinkU;
readdata(DATAFILE); // Data input from file
// Create the decision variables (including upper bounds for `frac')
frac = new XPRBvar[NSHARES];
buy = new XPRBvar[NSHARES];
for (s = 0; s<NSHARES; s++) {
frac[s] = p.newVar("frac", XPRB_PL, 0, MAXVAL);
buy[s] = p.newVar("buy", XPRB_BV);
}
// Objective: total return
for (s = 0; s<NSHARES; s++) le += RET[s] * frac[s];
Return = p.newCtr(le);
p.setObj(Return); // Set the objective function
// allocate memory for all constraints: Risk(1), Num(1), MinReg(NREGIONS), MaxReg(NREGIONS), LimSec(NTYPES)
vector<XPRBctr> allCtr(2 + 2 * NREGIONS + NTYPES);
int allCtrCount = 0;
/* init constraint pointers */
Risk = &allCtr[allCtrCount++];
Num = &allCtr[allCtrCount++];
MinReg = &allCtr[allCtrCount]; allCtrCount += NREGIONS;
MaxReg = &allCtr[allCtrCount]; allCtrCount += NREGIONS;
LimSec = &allCtr[allCtrCount]; allCtrCount += NTYPES;
// Limit the percentage of high-risk values
le = 0;
for (s = 0; s<NRISK; s++) le += frac[RISK[s]];
*Risk = p.newCtr("Risk", le <= MAXRISK);
// Limits on geographical distribution
for (r = 0; r<NREGIONS; r++) {
le = 0; le2 = 0;
for (s = 0; s<NSHARES; s++)
if (LOC[r][s]>0) {
le += frac[s];
le2 += frac[s];
}
MinReg[r] = p.newCtr(XPRBnewname("MinReg(%s)", REGIONS_n[r]), le >= MINREG);
MaxReg[r] = p.newCtr(XPRBnewname("MaxReg(%s)", REGIONS_n[r]), le2 <= MAXREG);
}
// Diversification across industry sectors
for (t = 0; t<NTYPES; t++) {
le = 0;
for (s = 0; s<NSHARES; s++)
if (SECT[t][s]>0) le += frac[s];
LimSec[t] = p.newCtr(XPRBnewname("LimSec(%s)", TYPES_n[t]), le <= MAXSEC);
}
// Spend all the capital
for (s = 0; s<NSHARES; s++) Cap += frac[s];
p.newCtr("Cap", Cap == 1);
// Limit the total number of assets
le = 0;
for (s = 0; s<NSHARES; s++) le += buy[s];
*Num = p.newCtr("Num", le <= MAXNUM);
// Linking the variables
for (s = 0; s<NSHARES; s++) {
p.newCtr(frac[s] <= MAXVAL*buy[s]);
p.newCtr(frac[s] >= MINVAL*buy[s]);
}
// Solve the problem (LP)
p.setMsgLevel(1);
p.setSense(XPRB_MAXIM);
p.lpOptimize("");
if (p.getLPStat() == XPRB_LP_INFEAS) {
cout << "LP infeasible. Start infeasibility repair." << endl;
XPRSprob op = p.getXPRSprob(); // Retrieve the Optimizer problem
// Must use the weighted infeasibility repair method since
// only some constraints of each type may be relaxed
/*
lrp: (affects = and <= rows)
ax - aux_var = b
ax - aux_var <= b
grp: (affects = and >= rows)
ax + aux_var = b
ax + aux_var >= b
lbp:
x_i + aux_var >= l
ubp:
x_i - aux_var <= u
*/
int ncol, nrow, repstatus;
double *lrp, *grp, *lbp, *ubp;
XPRSgetintattrib(op, XPRS_ORIGINALCOLS, &ncol);
XPRSgetintattrib(op, XPRS_ORIGINALROWS, &nrow);
lrp = new double[nrow];
grp = new double[nrow];
lbp = new double[ncol];
ubp = new double[ncol];
memset(lrp, 0, nrow*sizeof(double));
memset(grp, 0, nrow*sizeof(double));
memset(lbp, 0, ncol*sizeof(double));
memset(ubp, 0, ncol*sizeof(double));
lrp[Risk->getRowNum()] = 1;
for (r = 0; r<NREGIONS; r++) lrp[MaxReg[r].getRowNum()] = 1;
for (t = 0; t<NTYPES; t++) lrp[LimSec[t].getRowNum()] = 1;
lrp[Num->getRowNum()] = 1;
for (r = 0; r<NREGIONS; r++) grp[MinReg[r].getRowNum()] = 1;
char *rstat[] = { "relaxed optimum found", "relaxed problem infeasible",
"relaxed problem unbounded", "solution nonoptimal for original objective",
"error", "numerical instability" };
for (double delta = 0.001; delta < 10; delta *= 10) {
XPRSrepairweightedinfeas(op, &repstatus, lrp, grp, lbp, ubp, 'd', delta, "");
cout << "delta = " << delta << ": Status: " << rstat[repstatus] << endl;
if (repstatus == 0) {
p.sync(XPRB_XPRS_SOLMIP);
print_sol_opt(p);
print_violated(allCtr);
}
}
delete[] lrp;
delete[] grp;
delete[] lbp;
delete[] ubp;
}
return 0;
}
void print_sol_opt(XPRBprob &p)
{
cout << " Total return: " << p.getObjVal() << endl;
for (int s = 0; s<NSHARES; s++)
if (buy[s].getSol() > 0.5)
cout << " " << SHARES_n[s] << " : " << frac[s].getSol() * 100 << "% (" << buy[s].getSol() << ")" << endl;
}
void print_violated(vector<XPRBctr> &ctrs)
{
char *type = NULL;
cout << " Violated (relaxed) constraints:" << endl;
for (vector<XPRBctr>::iterator c = ctrs.begin(); c != ctrs.end(); c++) {
double viol, slack = c->getSlack();
switch (c->getType()) {
case XPRB_E: viol = abs(slack); type = " ="; break;
case XPRB_G: viol = slack; type = ">="; break;
case XPRB_L: viol = -slack; type = "<="; break;
default: cout << " unexpected constraint type" << endl; continue;
}
if (viol > 1e-6) cout << " " << type << " constraint " << c->getName() << " by " << -slack << endl;
}
}
|
|