/*
 * -------------------------------------------------------------------------
 *      $Id: Computer.java,v 1.2 2004/05/26 18:08:33 estewart Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved.
 *
 *      This software is confidential information which is proprietary to
 *      and a trade secret of Visual Numerics, Inc.  Use, duplication or
 *      disclosure is subject to the terms of an appropriate license
 *      agreement.
 *
 *      VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 *      SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 *      BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 *      FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
 *      NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 *      AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 *      ITS DERIVATIVES.
 *--------------------------------------------------------------------------
 */

package com.imsl.demo.Efficient;
import com.imsl.math.*;
import com.imsl.stat.*;

/**
 *
 * @author  Kim Ju-Yeol
 * @created October 9, 2002
 */
public class Computer {
    
    public static final int MODEL_EWMA = 0;
    public static final int MODEL_SMA = 1;
    public static final int MODEL_AHP = 2;
    public static double[] results;
    public static double[] expected_ret;
    
    private static double[][] w_fCorelations1, w_fCorelations2, w_fCorelations3;
    private static double[][] w_fCorelations4, w_fCorelations5, w_fCorelations6;
    private static double[][] w_fCorelations7, w_fCorelations8, w_fCorelations9;
    private static double[][] w_fCorelations10;
    
    private static int N_VARIABLES = 2;
    private static int N_OBSERVATIONS = 36;
    
    private static double w_fRisk1, w_fRisk2, w_fRisk3, w_fRisk4, w_fRisk5;
    private static int iMin;
    private static int iMax;
    
    private static double i_fDepositReturn;
    private static double i_fDepositRisk;
    private static double i_fLoanReturn;
    private static double i_fLoanRisk;
    private static double i_fInvestBondReturn;
    private static double i_fInvestBondRisk;
    private static double i_fCommBondReturn;
    private static double i_fCommBondRisk;
    private static double i_fEquityReturn;
    private static double i_fEquityRisk;
    private static int icount = 0;
    
    private int model;
    
    public Computer() {
        model = MODEL_EWMA;
        if ( 0 == icount ) {
            calcCorrStrategy();
        }
        icount++;
    }
    
    public static double[] getResults() {
        return results;
    }
    
    public static double[] getExpected_ret() {
        return expected_ret;
    }
    
    public int getModel() {
        return model;
    }
    
    public void setModel(int model) {
        this.model = model;
        switch (model) {
            case MODEL_EWMA: {
                setEWMA();
                break;
            }
            case MODEL_SMA: {
                setSMA();
                break;
            }
            case MODEL_AHP: {
                setAHP();
                break;
            }
        }
    }
    
    public static double[] getReturn() {
        double[] allReturnVal = {
            i_fDepositReturn,
            i_fLoanReturn,
            i_fInvestBondReturn,
            i_fCommBondReturn,
            i_fEquityReturn};
            return allReturnVal;
    }
    
    public static double[] getRisk() {
        double[] allRiskVal = {
            i_fDepositRisk,
            i_fLoanRisk,
            i_fInvestBondRisk,
            i_fCommBondRisk,
            i_fEquityRisk};
            return allRiskVal;
    }
    
    public static String[] getCommodity() {
        String[] allCommodity = {
            "Deposit",
            "Loan",
            "InvestBond",
            "CommBond",
            "Equity"};
            return allCommodity;
    }
    
    void initialize() {
        setEWMA();
        compute();
    }
    
    public void setEWMA() {
        i_fDepositReturn = 5.92;
        i_fDepositRisk = 3.60;
        i_fLoanReturn = 9.95;
        i_fLoanRisk = 3.21;
        i_fInvestBondReturn = 7.73;
        i_fInvestBondRisk = 4.38;
        i_fCommBondReturn = 6.94;
        i_fCommBondRisk = 4.52;
        i_fEquityReturn = 48.54;
        i_fEquityRisk = 31.33;
    }
    
    public void setSMA() {
        i_fDepositReturn = 6.14;
        i_fDepositRisk = 3.36;
        i_fLoanReturn = 10.02;
        i_fLoanRisk = 2.58;
        i_fInvestBondReturn = 8.22;
        i_fInvestBondRisk = 4.62;
        i_fCommBondReturn = 7.58;
        i_fCommBondRisk = 4.17;
        i_fEquityReturn = 1.35;
        i_fEquityRisk = 30.20;
    }
    
    public void setAHP() {
        i_fDepositReturn = 4.97;
        i_fDepositRisk = 3.60;
        i_fLoanReturn = 11.0;
        i_fLoanRisk = 3.21;
        i_fInvestBondReturn = 7.70;
        i_fInvestBondRisk = 4.38;
        i_fCommBondReturn = 7.70;
        i_fCommBondRisk = 4.52;
        i_fEquityReturn = 45.00;
        i_fEquityRisk = 31.33;
    }
    
    public void compute() {
        int neq = 2;
        int ncon = 2;
        int nvar = 5;
        double a[], b[], xlb[], xub[], obj;
        int i;
        
        a = new double[10];
        b = new double[2];
        xlb = new double[5];
        xub = new double[5];
        
        // Initial value of Constraints
        double i_fDepositUpper = 0.;
        double i_fDepositLower = 0.;
        
        double i_fLoanUpper = 71.;
        double i_fLoanLower = 0.;
        
        double i_fInvestBondUpper = 74.;
        double i_fInvestBondLower = 0.;
        
        double i_fCommBondUpper = 86.;
        double i_fCommBondLower = 0.;
        
        double i_fEquityUpper = 60.;
        double i_fEquityLower = 1.;
        // End of Initialization
        
        double dMin, dMax, fExpected_ret;
        
        // Find a Min & Max using LinearProgramming
        dMin = minFunction(i_fDepositReturn, i_fLoanReturn, i_fCommBondReturn, i_fInvestBondReturn, i_fEquityReturn,
        i_fDepositLower, i_fLoanLower, i_fCommBondLower, i_fInvestBondLower, i_fEquityLower,
        i_fDepositUpper, i_fLoanUpper, i_fCommBondUpper, i_fInvestBondUpper, i_fEquityUpper);
        
        dMax = maxFunction(i_fDepositReturn, i_fLoanReturn, i_fCommBondReturn, i_fInvestBondReturn, i_fEquityReturn,
        i_fDepositLower, i_fLoanLower, i_fCommBondLower, i_fInvestBondLower, i_fEquityLower,
        i_fDepositUpper, i_fLoanUpper, i_fCommBondUpper, i_fInvestBondUpper, i_fEquityUpper);
        
        iMin = (int) Math.ceil(dMin)*10;
        iMax = (int) Math.floor(Math.abs(dMax))*10;
        
        w_fRisk1 = i_fDepositRisk;
        w_fRisk2 = i_fLoanRisk;
        w_fRisk3 = i_fCommBondRisk;
        w_fRisk4 = i_fInvestBondRisk;
        w_fRisk5 = i_fEquityRisk;
        
        i_fDepositLower *= (double)0.01;
        i_fLoanLower *= (double)0.01;
        i_fCommBondLower *= (double)0.01;
        i_fInvestBondLower *= (double)0.01;
        i_fEquityLower *= (double)0.01;
        i_fDepositUpper *= (double)0.01;
        i_fLoanUpper *= (double)0.01;
        i_fCommBondUpper *= (double)0.01;
        i_fInvestBondUpper *= (double)0.01;
        i_fEquityUpper *= (double)0.01;
        
        a[0] = i_fDepositReturn;
        a[1] = i_fLoanReturn;
        a[2] = i_fInvestBondReturn;
        a[3] = i_fCommBondReturn;
        a[4] = i_fEquityReturn;
        a[5] = 1.0;
        a[6] = 1.0;
        a[7] = 1.0;
        a[8] = 1.0;
        a[9] = 1.0;
        b[1] = 1.0;
        
        xlb[0] = i_fDepositLower;
        xlb[1] = i_fLoanLower;
        xlb[2] = i_fInvestBondLower;
        xlb[3] = i_fCommBondLower;
        xlb[4] = i_fEquityLower;
        
        xub[0] = i_fDepositUpper;
        xub[1] = i_fLoanUpper;
        xub[2] = i_fInvestBondUpper;
        xub[3] = i_fCommBondUpper;
        xub[4] = i_fEquityUpper;
        
        results = new double[iMax-(iMin+1)];
        expected_ret = new double[iMax-(iMin+1)];
        
        // Simulate Using MinConGenLin
        for (i = iMin + 1; i < iMax; i++) {
            fExpected_ret = (double)i/10;
            b[0] = fExpected_ret;
            
            MinConGenLin.Function fcn = new MinConGenLin.Function() {
                public double f(double[] x) {
                    return Math.sqrt(
                     Math.pow(w_fRisk1,2)*Math.pow(x[0],2)
                      + Math.pow(w_fRisk2,2)*Math.pow(x[1],2)
                      + Math.pow(w_fRisk3,2)*Math.pow(x[2],2)
                      + Math.pow(w_fRisk4,2)*Math.pow(x[3],2)
                      + Math.pow(w_fRisk5,2)*Math.pow(x[4],2)
                      + 2 * (
                        w_fRisk1*w_fRisk2*w_fCorelations1[0][1]*x[0]*x[1]
                        + w_fRisk1*w_fRisk3*w_fCorelations2[0][1]*x[0]*x[2]
                        + w_fRisk1*w_fRisk4*w_fCorelations3[0][1]*x[0]*x[3]
                        + w_fRisk1*w_fRisk5*w_fCorelations4[0][1]*x[0]*x[4]
                        + w_fRisk2*w_fRisk3*w_fCorelations5[0][1]*x[1]*x[2]
                        + w_fRisk2*w_fRisk4*w_fCorelations6[0][1]*x[1]*x[3]
                        + w_fRisk2*w_fRisk5*w_fCorelations7[0][1]*x[1]*x[4]
                        + w_fRisk3*w_fRisk4*w_fCorelations8[0][1]*x[2]*x[3]
                        + w_fRisk3*w_fRisk5*w_fCorelations9[0][1]*x[2]*x[4]
                        + w_fRisk4*w_fRisk5*w_fCorelations10[0][1]*x[3]*x[4])
                    );
                }
            };
            
            MinConGenLin zf = new MinConGenLin(fcn, nvar, ncon, neq, a, b, xlb, xub);
            
            try {
                zf.solve();
            } catch (MinConGenLin.ConstraintsInconsistentException e) {
                System.out.println(e.getMessage());
            } catch (MinConGenLin.VarBoundsInconsistentException e) {
                System.out.println(e.getMessage());
            } catch (MinConGenLin.ConstraintsNotSatisfiedException e) {
                System.out.println(e.getMessage());
            } catch (MinConGenLin.EqualityConstraintsException e) {
                System.out.println(e.getMessage());
            }
            
            results[i-(iMin+1)] = zf.getObjectiveValue();
            expected_ret[i-(iMin+1)] = fExpected_ret;
        }
    }
    
    // Save the Results to File.
    public void saveData(java.awt.Component parent, String fileName) {
        try {
            java.nio.DoubleBuffer db = java.nio.DoubleBuffer.allocate(results.length);
            db.put(results[0]);
            java.io.DataOutputStream dos = new java.io.DataOutputStream(new java.io.FileOutputStream(fileName));
            
            for (int i=0; i< results.length; i++) {
                dos.writeBytes(Double.toString(results[i]) + "\n");
            }

            dos.close();
            javax.swing.JOptionPane.showMessageDialog(parent, "Finished Save As Data\nFilename is " + fileName, 
                "Save As Results", javax.swing.JOptionPane.INFORMATION_MESSAGE);
        } catch (Exception e) {
            String name = e.toString().substring(0,e.toString().indexOf(':'));
            javax.swing.JOptionPane.showMessageDialog(parent, e.getMessage(), name, javax.swing.JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }
    
    // Caculate the Correlations for Strategy
    public static void calcCorrStrategy() {
        int i,j;
        // Rates of Return for 3 years
        double[] data = {
            6.67,6.67,6.67,6.67,10.93,10.93,10.93,8.84,8.84,9.23,
            10.93,8.84,9.23,15.45,8.84,9.23,15.45,9.23,15.45,15.45,
            6.72,6.72,6.72,6.72,10.86,10.86,10.86,9.39,9.39,10.26,
            10.86,9.39,10.26,-3.94,9.39,10.26,-3.94,10.26,-3.94,-3.94,
            6.76,6.76,6.76,6.76,10.83,10.83,10.83,9.19,9.19,9.95,
            10.83,9.19,9.95,-0.66,9.19,9.95,-0.66,9.95,-0.66,-0.66,
            6.87,6.87,6.87,6.87,10.71,10.71,10.71,8.3,8.3,9.02,
            10.71,8.3,9.02,-10.61,8.3,9.02,-10.61,9.02,-10.61,-10.61,
            6.89,6.89,6.89,6.89,10.58,10.58,10.58,8.87,8.87,9.72,
            10.58,8.87,9.72,14.66,8.87,9.72,14.66,9.72,14.66,14.66,
            7.03,7.03,7.03,7.03,10.58,10.58,10.58,9.19,9.19,9.95,
            10.58,9.19,9.95,3.62,9.19,9.95,3.62,9.95,3.62,3.62,
            7.23,7.23,7.23,7.23,10.59,10.59,10.59,9.21,9.21,10.12,
            10.59,9.21,10.12,-3.25,9.21,10.12,-3.25,10.12,-3.25,-3.25,
            7.34,7.34,7.34,7.34,10.64,10.64,10.64,9.13,9.13,9.9,
            10.64,9.13,9.9,-5.23,9.13,9.9,-5.23,9.9,-5.23,-5.23,
            7.3,7.3,7.3,7.3,10.79,10.79,10.79,9.2,9.2,9.98,
            10.79,9.2,9.98,-2.69,9.2,9.98,-2.69,9.98,-2.69,-2.69,
            7.27,7.27,7.27,7.27,10.61,10.61,10.61,8.93,8.93,9.94,
            10.61,8.93,9.94,-11.22,8.93,9.94,-11.22,9.94,-11.22,-11.22,
            7.15,7.15,7.15,7.15,10.62,10.62,10.62,8.88,8.88,9.89,
            10.62,8.88,9.89,-7.57,8.88,9.89,-7.57,9.89,-7.57,-7.57,
            7.05,7.05,7.05,7.05,10.49,10.49,10.49,8.55,8.55,9.37,
            10.49,8.55,9.37,10.31,8.55,9.37,10.31,9.37,10.31,10.31,
            7.07,7.07,7.07,7.07,10.51,10.51,10.51,8.31,8.31,9.17,
            10.51,8.31,9.17,-0.13,8.31,9.17,-0.13,9.17,-0.13,-0.13,
            7.02,7.02,7.02,7.02,10.41,10.41,10.41,8.36,8.36,8.98,
            10.41,8.36,8.98,-9.28,8.36,8.98,-9.28,8.98,-9.28,-9.28,
            6.86,6.86,6.86,6.86,10.43,10.43,10.43,8.44,8.44,9.04,
            10.43,8.44,9.04,-13.53,8.44,9.04,-13.53,9.04,-13.53,-13.53,
            6.95,6.95,6.95,6.95,10.51,10.51,10.51,7.96,7.96,8.59,
            10.51,7.96,8.59,-12.01,7.96,8.59,-12.01,8.59,-12.01,-12.01,
            6.86,6.86,6.86,6.86,10.53,10.53,10.53,7.36,7.36,8.35,
            10.53,7.36,8.35,-0.73,7.36,8.35,-0.73,8.35,-0.73,-0.73,
            6.82,6.82,6.82,6.82,10.41,10.41,10.41,7.11,7.11,8.13,
            10.41,7.11,8.13,-3.25,7.11,8.13,-3.25,8.13,-3.25,-3.25,
            
            6.71,6.71,6.71,6.71,10.45,10.45,10.45,7,7,7.38,
            10.45,7,7.38,11.13,7,7.38,11.13,7.38,11.13,11.13,
            6.12,6.12,6.12,6.12,10.34,10.34,10.34,6.42,6.42,6.77,
            10.34,6.42,6.77,1.44,6.42,6.77,1.44,6.77,1.44,1.44,
            5.83,5.83,5.83,5.83,10.26,10.26,10.26,7,7,7.69,
            10.26,7,7.69,-8.34,7,7.69,-8.34,7.69,-8.34,-8.34,
            5.79,5.79,5.79,5.79,10.1,10.1,10.1,7.48,7.48,8.05,
            10.1,7.48,8.05,-2.5,7.48,8.05,-2.5,8.05,-2.5,-2.5,
            5.79,5.79,5.79,5.79,9.99,9.99,9.99,7.04,7.04,7.37,
            9.99,7.04,7.37,13.28,7.04,7.37,13.28,7.37,13.28,13.28,
            5.74,5.74,5.74,5.74,9.89,9.89,9.89,7,7,7.1,
            9.89,7,7.1,0.37,7,7.1,0.37,7.1,0.37,0.37,
            5.62,5.62,5.62,5.62,9.78,9.78,9.78,6.35,6.35,6.89,
            9.78,6.35,6.89,-8.09,6.35,6.89,-8.09,6.89,-8.09,-8.09,
            5.2,5.2,5.2,5.2,9.51,9.51,9.51,6,6,6.55,
            9.51,6,6.55,2.45,6,6.55,2.45,6.55,2.45,2.45,
            4.93,4.93,4.93,4.93,9.26,9.26,9.26,5.92,5.92,5.95,
            9.26,5.92,5.95,-11.22,5.92,5.95,-11.22,5.95,-11.22,-11.22,
            4.58,4.58,4.58,4.58,9.07,9.07,9.07,5.63,5.63,6.59,
            9.07,5.63,6.59,3.83,5.63,6.59,3.83,6.59,3.83,3.83,
            4.59,4.59,4.59,4.59,8.92,8.92,8.92,6.19,6.19,6.99,
            8.92,6.19,6.99,15.59,6.19,6.99,15.59,6.99,15.59,15.59,
            4.63,4.63,4.63,4.63,8.91,8.91,8.91,6.54,6.54,7.04,
            8.91,6.54,7.04,10.1,6.54,7.04,10.1,7.04,10.1,10.1,
            4.66,4.66,4.66,4.66,8.9,8.9,8.9,6.59,6.59,6.97,
            8.9,6.59,6.97,10.96,6.59,6.97,10.96,6.97,10.96,10.96,
            5,5,5,5,8.78,8.78,8.78,6,6,6.68,
            8.78,6,6.68,4.79,6,6.68,4.79,6.68,4.79,4.79,
            4.95,4.95,4.95,4.95,8.79,8.79,8.79,6.58,6.58,7.07,
            8.79,6.58,7.07,11.66,6.58,7.07,11.66,7.07,11.66,11.66,
            5,5,5,5,8.8,8.8,8.8,7,7,7.11,
            8.8,7,7.11,3.39,7,7.11,3.39,7.11,3.39,3.39,
            5,5,5,5,8.85,8.85,8.85,6.89,6.89,7.08,
            8.85,6.89,7.08,-5.79,6.89,7.08,-5.79,7.08,-5.79,-5.79,
            5.1,5.1,5.1,5.1,9.05,9.05,9.05,6,6,7.2,
            9.05,6,7.2,-6.88,6,7.2,-6.88,7.2,-6.88,-6.88
        };
        
        /* Data1 : Deposit - Loan
         * Data2 : Deposit - Commodity Bond
         * Data3 : Deposit - Investment Bond
         * Data4 : Deposit - Equity Bond
         * Data5 : Loan - Commodity Bond
         * Data6 : Loan - Investment Bond
         * Data7 : Loan - Equity Bond
         * Data8 : Commodity Bond - Investment Bond
         * Data9 : Commodity Bond - Equity Bond
         * Data10 : Investment Bond - Equity Bond
         */
        double[][] data1, data2, data3, data4, data5,data6, data7, data8, data9, data10;
        
        data1 = new double[N_OBSERVATIONS][N_VARIABLES];
        data2 = new double[N_OBSERVATIONS][N_VARIABLES];
        data3 = new double[N_OBSERVATIONS][N_VARIABLES];
        data4 = new double[N_OBSERVATIONS][N_VARIABLES];
        data5 = new double[N_OBSERVATIONS][N_VARIABLES];
        data6 = new double[N_OBSERVATIONS][N_VARIABLES];
        data7 = new double[N_OBSERVATIONS][N_VARIABLES];
        data8 = new double[N_OBSERVATIONS][N_VARIABLES];
        data9 = new double[N_OBSERVATIONS][N_VARIABLES];
        data10 = new double[N_OBSERVATIONS][N_VARIABLES];
        
        for (i = 0; i < N_OBSERVATIONS; i++) {
            for (j=0; j < N_VARIABLES; j++) {
                data1[i][j] = data[j*10+i*20];
                data2[i][j] = data[j*10+i*20+1];
                data3[i][j] = data[j*10+i*20+2];
                data4[i][j] = data[j*10+i*20+3];
                data5[i][j] = data[j*10+i*20+4];
                data6[i][j] = data[j*10+i*20+5];
                data7[i][j] = data[j*10+i*20+6];
                data8[i][j] = data[j*10+i*20+7];
                data9[i][j] = data[j*10+i*20+8];
                data10[i][j] = data[j*10+i*20+9];
            }
        }
        
        // Find Corelations for analysis
        Covariances co1 = new Covariances(data1);
        Covariances co2 = new Covariances(data2);
        Covariances co3 = new Covariances(data3);
        Covariances co4 = new Covariances(data4);
        Covariances co5 = new Covariances(data5);
        Covariances co6 = new Covariances(data6);
        Covariances co7 = new Covariances(data7);
        Covariances co8 = new Covariances(data8);
        Covariances co9 = new Covariances(data9);
        Covariances co10 = new Covariances(data10);
        
        try {
            w_fCorelations1 = co1.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations2 = co2.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations3 = co3.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations4 = co4.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations5 = co5.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations6 = co6.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations7 = co7.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations8 = co8.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations9 = co9.compute(Covariances.CORRELATION_MATRIX);
            w_fCorelations10 = co10.compute(Covariances.CORRELATION_MATRIX);
        } catch (Covariances.NonnegativeFreqException  e) {
            System.out.println(e.getMessage());
        } catch (Covariances.NonnegativeWeightException e) {
            System.out.println(e.getMessage());
        } catch (Covariances.TooManyObsDeletedException e) {
            System.out.println(e.getMessage());
        } catch (Covariances.MoreObsDelThanEnteredException e) {
            System.out.println(e.getMessage());
        } catch (Covariances.DiffObsDeletedException e) {
            System.out.println(e.getMessage());
        }
    }
    
    // Calculate a Minimum using LinearProgramming
    public static double minFunction(
    double i_fReturn1, double i_fReturn2, double i_fReturn3, double i_fReturn4, double i_fReturn5,
    double i_fLower1, double i_fLower2, double i_fLower3, double i_fLower4, double i_fLower5,
    double i_fUpper1, double i_fUpper2, double i_fUpper3, double i_fUpper4, double i_fUpper5) {
        double[][] a = {{1.0, 1.0, 1.0, 1.0, 1.0}};
        double[] b = {1.0};
        double xlb[] = {i_fLower1*(double)0.01, i_fLower2*(double)0.01, i_fLower3*(double)0.01, i_fLower4*(double)0.01, i_fLower5*(double)0.01};
        double xub[] = {i_fUpper1*(double)0.01, i_fUpper2*(double)0.01, i_fUpper3*(double)0.01, i_fUpper4*(double)0.01, i_fUpper5*(double)0.01};
        double[] c = {i_fReturn1, i_fReturn2, i_fReturn3, i_fReturn4, i_fReturn5};
        
        LinearProgramming zf = new LinearProgramming(a, b, c);
        
        zf.setLowerBound(xlb);
        zf.setUpperBound(xub);
        
        try {
            zf.solve();
        } catch (LinearProgramming.BoundsInconsistentException e) {
            System.out.println(e.getMessage());
        } catch (LinearProgramming.NumericDifficultyException e) {
            System.out.println(e.getMessage());
        } catch (SingularMatrixException e) {
            System.out.println(e.getMessage());
        }
        
        double obj = zf.getOptimalValue();
        return obj;
    }
    
    // Calculate a Maximum using LinearProgramming
    
    public static double maxFunction(
    double i_fReturn1, double i_fReturn2, double i_fReturn3, double i_fReturn4, double i_fReturn5,
    double i_fLower1, double i_fLower2, double i_fLower3, double i_fLower4, double i_fLower5,
    double i_fUpper1, double i_fUpper2, double i_fUpper3, double i_fUpper4, double i_fUpper5) {
        double[][] a = {{1.0, 1.0, 1.0, 1.0, 1.0}};
        double[] b = {1.0};
        double xlb[] = {i_fLower1*(double)0.01, i_fLower2*(double)0.01, i_fLower3*(double)0.01, i_fLower4*(double)0.01, i_fLower5*(double)0.01};
        double xub[] = {i_fUpper1*(double)0.01, i_fUpper2*(double)0.01, i_fUpper3*(double)0.01, i_fUpper4*(double)0.01, i_fUpper5*(double)0.01};
        double[] c = {-(i_fReturn1), -(i_fReturn2), -(i_fReturn3), -(i_fReturn4), -(i_fReturn5)};
        
        LinearProgramming zf = new LinearProgramming(a, b, c);
        
        zf.setLowerBound(xlb);
        zf.setUpperBound(xub);
        
        try {
            zf.solve();
        } catch (LinearProgramming.BoundsInconsistentException e) {
            System.out.println(e.getMessage());
        } catch (LinearProgramming.NumericDifficultyException e) {
            System.out.println(e.getMessage());
        } catch (SingularMatrixException e) {
            System.out.println(e.getMessage());
        }
        
        double obj = zf.getOptimalValue();
        return obj;
    }
}