FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Folio - Examples from 'Getting Started'

Description
Different versions of a portfolio optimization problem.

Basic modelling and solving tasks:
  • modeling and solving a small LP problem (foliolp)
  • performing explicit initialization (folioini*)
  • data input from file, index sets (foliodata, requires foliocpplp.dat)
  • modeling and solving a small MIP problem with binary variables (foliomip1)
  • modeling and solving a small MIP problem with semi-continuous variables (foliomip2)
  • modeling and solving QP and MIQP problems (folioqp, requires foliocppqp.dat)
  • modeling and solving QCQP problems (folioqc, requires foliocppqp.dat)
  • heuristic solution of a MIP problem (folioheur)
Advanced modeling and solving tasks:
  • enlarged version of the basic MIP model (foliomip3 with include file readfoliodata.c_, to be used with data set folio10.cdat)
  • defining an integer solution callback (foliocb)
  • using the MIP solution pool (foliosolpool)
  • using the solution enumerator (folioenumsol)
  • handling infeasibility through deviation variables (folioinfeas)
  • retrieving IIS (folioiis)
  • using the built-in infeasibility repair functionality (foliorep)
Further explanation of this example: 'Getting Started with BCL' for the basic modelling and solving tasks; 'Advanced Evaluators Guide' for solution enumeration and infeasibilit handling

xbfoliocpp.zip[download all files]

Source Files

Data Files





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-2024 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;
}

Back to examples browserPrevious exampleNext example