/********************************************************
  Xpress-BCL Java Example Problems
  ================================

  file foliomip1.java
  ```````````````````
  Modeling a small LP problem 
  to perform portfolio optimization.
   -- Limiting the total number of assets --

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, 2003, rev. Dec. 2011
********************************************************/

import com.dashoptimization.*;

public class foliomip1
{
 static final int MAXNUM = 4;      /* Max. number of different assets */
 static final int NSHARES = 10;    /* Number of shares */
 static final int NRISK = 5;       /* Number of high-risk shares */
 static final int NNA = 4;         /* Number of North-American shares */

 static final double[] RET = {5,17,26,12,8,9,7,6,31,21};
                                   /* Estimated return in investment  */
 static final int[] RISK = {1,2,3,8,9};  /* High-risk values among shares */
 static final int[] NA = {0,1,2,3};      /* Shares issued in N.-America */

 static final String[] MIPSTATUS = {"not loaded", "not optimized", 
                      "LP optimized", "unfinished (no solution)", 
                      "unfinished (solution found)", "infeasible", "optimal",
                      "unbounded"};
 
 public static void main(String[] args)
 { 
  int s;
  XPRB bcl;
  XPRBprob p;
  XPRBexpr Risk,Na,Return,Cap,Num;
  XPRBvar[] frac;                  /* Fraction of capital used per share */
  XPRBvar[] buy;                   /* 1 if asset is in portfolio, 0 otherwise */

  bcl = new XPRB();                /* Initialize BCL */
  p = bcl.newProb("FolioMIP1");    /* Create a new problem in BCL */

/* Create the decision variables */
  frac = new XPRBvar[NSHARES];
  buy = new XPRBvar[NSHARES];
  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 */
  Return = new XPRBexpr();
  for(s=0;s<NSHARES;s++) Return.add(frac[s].mul(RET[s])); 
  p.setObj(Return);                  /* Set the objective function */

/* Limit the percentage of high-risk values */
  Risk = new XPRBexpr();
  for(s=0;s<NRISK;s++) Risk.add(frac[RISK[s]]); 
  p.newCtr(Risk.lEql(1.0/3));

/* Minimum amount of North-American values */
  Na = new XPRBexpr();
  for(s=0;s<NNA;s++) Na.add(frac[NA[s]]); 
  p.newCtr(Na.gEql(0.5));

/* Spend all the capital */
  Cap = new XPRBexpr();
  for(s=0;s<NSHARES;s++) Cap.add(frac[s]); 
  p.newCtr(Cap.eql(1));
 
/* Limit the total number of assets */
  Num = new XPRBexpr();
  for(s=0;s<NSHARES;s++) Num.add(buy[s]);
  p.newCtr(Num.lEql(MAXNUM));

/* Linking the variables */
  for(s=0;s<NSHARES;s++) p.newCtr(frac[s].lEql(buy[s]));

/* Solve the problem */
  p.setSense(XPRB.MAXIM);
  p.mipOptimize("");

  System.out.println("Problem status: " + MIPSTATUS[p.getMIPStat()]);
 
/* Solution printing */
  System.out.println("Total return: " + p.getObjVal());
  for(s=0;s<NSHARES;s++) 
   System.out.println(s + ": " + frac[s].getSol()*100 + "% (" +
    buy[s].getSol() + ")");  

/* Delete the problem */
  p.finalize();              
  p=null;
 }
} 
