FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious 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 (folioinit)
  • 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)
  • heuristic solution of a MIP problem (folioheur)
Advanced modeling and solving tasks:
  • enlarged version of the basic MIP model (foliomip3, 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, foliomiis)
  • 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


Source Files

Data Files





folioiis.cs

/********************************************************
Xpress-BCL Java Example Problems
================================

file folioiis.cs
```````````````````
Modeling a MIP problem
to perform portfolio optimization.
Same model as in foliomip3.cs.
-- Infeasible model parameter values --
-- Retrieving IIS --

(c) 2014-2024 Fair Isaac Corporation
  author: L.Bertacco, September 2014
********************************************************/

using System;
using System.Collections;
using System.Text;
using System.IO;
using BCL;

namespace Examples
{
  public class TestUGFolioIIS
  {
    const String DATAFILE = "folio10.cdat";

    const int MAXNUM = 5;          /* Max. number of different assets */
    const double MAXRISK = 1.0/3;  /* Max. investment into high-risk values */
    const double MINREG = 0.1;     /* Min. investment per geogr. region */
    const double MAXREG = 0.2;     /* Max. investment per geogr. region */
    const double MAXSEC = 0.1;     /* Max. investment per ind. sector */
    const double MAXVAL = 0.2;     /* Max. investment per share */
    const double MINVAL = 0.1;     /* Min. investment per share */

    static double[] RET;           /* Estimated return in investment  */
    static int[] RISK;             /* High-risk values among shares */
    static bool[][] LOC;           /* Geogr. region of shares */
    static bool[][] SEC;           /* Industry sector of shares */

    static String[] SHARES_n;
    static String[] REGIONS_n;
    static String[] TYPES_n;

    static readonly String[] MIPSTATUS = {"not loaded", "not optimized",
                    "LP optimized", "unfinished (no solution)",
                    "unfinished (solution found)", "infeasible", "optimal",
                    "unbounded"};

    public static void Main()
    {
      try
      {
        readData();                     /* Read data from file */
      }
      catch (Exception exc)
      {
        Console.Error.WriteLine(exc);
        Console.Error.WriteLine(Environment.StackTrace);
        return;
      }

      XPRB.init();                /* Initialize BCL */
      XPRBprob p = new XPRBprob("FolioMIP3inf");  /* Create a new problem in BCL */

      /* Create the decision variables */
      XPRBvar[] frac = new XPRBvar[SHARES_n.Length]; /* Fraction of capital used per share */
      XPRBvar[] buy = new XPRBvar[SHARES_n.Length]; /* 1 if asset is in portfolio, 0 otherwise */
      for (int s = 0; s < SHARES_n.Length; s++)
      {
        frac[s] = p.newVar("frac", BCLconstant.XPRB_PL, 0, MAXVAL);
        buy[s] = p.newVar("buy", BCLconstant.XPRB_BV);
      }

      /* Objective: total return */
      XPRBexpr Return = new XPRBexpr();
      for (int s = 0; s < SHARES_n.Length; s++) Return.add(frac[s] * RET[s]);
      p.setObj(Return);                  /* Set the objective function */

      /* Limit the percentage of high-risk values */
      XPRBexpr Risk = new XPRBexpr();
      for (int s = 0; s < RISK.Length; s++) Risk.add(frac[RISK[s]]);
      p.newCtr(Risk <= MAXRISK);

      /* Limits on geographical distribution */
      XPRBexpr[] MinReg = new XPRBexpr[REGIONS_n.Length];
      XPRBexpr[] MaxReg = new XPRBexpr[REGIONS_n.Length];
      for (int r = 0; r < REGIONS_n.Length; r++)
      {
        MinReg[r] = new XPRBexpr();
        MaxReg[r] = new XPRBexpr();
        for (int s = 0; s < SHARES_n.Length; s++)
          if (LOC[r][s])
          {
            MinReg[r].add(frac[s]);
            MaxReg[r].add(frac[s]);
          }
        p.newCtr(MinReg[r] >= MINREG);
        p.newCtr(MaxReg[r] <= MAXREG);
      }

      /* Diversification across industry sectors */
      XPRBexpr[] LimSec = new XPRBexpr[TYPES_n.Length];
      for (int t = 0; t < TYPES_n.Length; t++)
      {
        LimSec[t] = new XPRBexpr();
        for (int s = 0; s < SHARES_n.Length; s++)
          if (SEC[t][s]) LimSec[t].add(frac[s]);
        p.newCtr(LimSec[t] <= MAXSEC);
      }

      /* Spend all the capital */
      XPRBexpr Cap = new XPRBexpr();
      for (int s = 0; s < SHARES_n.Length; s++) Cap.add(frac[s]);
      p.newCtr(Cap == 1.0);

      /* Limit the total number of assets */
      XPRBexpr Num = new XPRBexpr();
      for (int s = 0; s < SHARES_n.Length; s++) Num.add(buy[s]);
      p.newCtr(Num <= MAXNUM);

      /* Linking the variables */
      for (int s = 0; s < SHARES_n.Length; s++) p.newCtr(frac[s] <= buy[s] * MAXVAL);
      for (int s = 0; s < SHARES_n.Length; s++) p.newCtr(frac[s] >= buy[s] * MINVAL);

      p.exportProb(BCLconstant.XPRB_LP, "dnetmat.lp");

      /* Solve the problem */
      p.setSense(BCLconstant.XPRB_MAXIM);
      p.lpOptimize();

      Console.WriteLine("Problem status: " + p.getLPStat());
      if (p.getLPStat() == BCLconstant.XPRB_LP_INFEAS)
      {
        Console.WriteLine("LP infeasible. Retrieving IIS.");

        int numiis = p.getNumIIS();       /* Get the number of independent IIS */
        Console.WriteLine("Number of IIS: " + numiis);

        for(int s=1; s<=numiis; s++)
        {
          ArrayList iisctr = new ArrayList();
          ArrayList iisvar = new ArrayList();
          p.getIIS(iisvar, iisctr, s);
          Console.WriteLine("IIS {0}: {1} variables, {2} constraints", s, iisvar.Count, iisctr.Count);
          if (iisvar.Count > 0)
          {                              /* Print all variables in the IIS */
            Console.Write("        Variables: ");
            foreach(XPRBvar v in iisvar) Console.Write("{0} ", v.getName());
            Console.WriteLine();
          }
          if (iisctr.Count>0)
          {                              /* Print all constraints in the IIS */
            Console.Write("        Constraints: ");
            foreach (XPRBctr c in iisctr) Console.Write("{0} ", c.getName());
            Console.WriteLine();
          }
        }
      }
      else
      {
        /* Solution printing */
        Console.WriteLine("Total return: " + p.getObjVal());
        for (int s = 0; s < SHARES_n.Length; s++)
          if (buy[s].getSol() > 0.5)
            Console.WriteLine("  " + s + ": " + frac[s].getSol() * 100 + "% (" +
              buy[s].getSol() + ")");
      }
    }

    /***********************Data input routines***************************/

    /***************************/
    /* Input a list of strings */
    /***************************/
    private static String[] read_str_list(String data)
    {
      return data.Split();
    }

    private static Array read_list(String data, Type ty)
    {
      ArrayList li = new ArrayList();
      foreach (String s in data.Split())
      {
        if (s == null || s == "") { continue; }
        Object value = Convert.ChangeType(s, ty);
        li.Add(value);
      }
      return li.ToArray(ty);
    }

    /************************/
    /* Input a list of ints */
    /************************/
    private static int[] read_int_list(String data)
    {
      return (int[])read_list(data, typeof(int));
    }

    /****************************/
    /* Input a table of doubles */
    /****************************/
    private static double[] read_dbl_list(String data)
    {
      return (double[])read_list(data, typeof(double));
    }

    private static bool[] read_bool_list(String data, int len)
    {
      bool[] bools = new bool[len];
      int[] trues = read_int_list(data);
      foreach (int t in trues) bools[t] = true;
      return bools;
    }

    /************************************/
    /* Input a sparse table of bools */
    /************************************/
    private static bool[][] read_bool_table(StreamReader r, int nrows, int ncols)
    {
      bool[][] lists = new bool[nrows][];
      for (int i = 0; i < nrows; i++) { lists[i] = new bool[ncols]; }

      for (int i = 0; i < nrows; i++)
      {
        String line = r.ReadLine();
        if (line == null) { break; }
        LineData ld = new LineData(line);
        if (ld.data == "") { break; }

        bool[] row = read_bool_list(ld.data, ncols);
        lists[i] = row;
      }
      return lists;
    }

    private class LineData
    {
      internal String name;
      internal String data;

      internal LineData(String line)
      {
        name = "";
        data = "";
        line = line.Trim();
        String[] split = line.Split(new char[] { '!' }, 2); // the comment char
        if (split.Length == 0) { return; }
        line = split[0].Trim();
        // chop into name:data pair
        split = line.Split(new char[] { ':' }, 2);
        if (split.Length == 0) { return; }
        if (split.Length > 1) name = split[0].Trim();
        // lose trailing ';'
        data = split[split.Length - 1].Trim().TrimEnd(';').Trim();
      }
    }

    private static void readData()
    {
      using (StreamReader r = new StreamReader(DATAFILE))
      {
        for (; ; )
        {
          String line = r.ReadLine();
          if (line == null) { break; }
          LineData ld = new LineData(line);
          if (ld.name == "SHARES" && SHARES_n == null)
            SHARES_n = read_str_list(ld.data);
          else if (ld.name == "REGIONS" && REGIONS_n == null)
            REGIONS_n = read_str_list(ld.data);
          else if (ld.name == "TYPES" && TYPES_n == null)
            TYPES_n = read_str_list(ld.data);
          else if (ld.name == "RISK" && RISK == null)
            RISK = read_int_list(ld.data);
          else if (ld.name == "RET" && RET == null)
            RET = read_dbl_list(ld.data);
          else if (ld.name == "LOC" && SHARES_n != null && REGIONS_n != null)
            LOC = read_bool_table(r, REGIONS_n.Length, SHARES_n.Length);
          else if (ld.name == "SEC" && SHARES_n != null && REGIONS_n != null)
            SEC = read_bool_table(r, TYPES_n.Length, SHARES_n.Length);
        }
      }
    }
  }
}
Back to examples browserPrevious example