Initializing help system before first use

Recurse - A successive linear programming model


Type: Recursion
Rating: 3 (intermediate)
Description: A non-linear problem (quadratic terms in the constraints) is modeled as a successive linear programming (SLP) model. (SLP is also known as 'recursion'.) The constraint coefficients are changed iteratively. Shows how to save and re-load an LP basis.
File(s): xbrecurs.cs


xbrecurs.cs
/*************************************************************/
/*  Xpress-BCL C# Example Problems                           */
/*  ==============================                           */
/*                                                           */
/*  file xbrecurs.cs                                         */
/*  ````````````````                                         */
/*  Example for the use of Xpress-BCL                        */
/*  (Recursion solving a non-linear financial planning       */
/*    problem)                                               */
/*  The problem is to solve                                  */
/*	net(t) = Payments(t)  - interest(t)                      */
/*	balance(t) = balance(t-1) - net(t)                       */
/*	interest(t) = (92/365) * balance(t) * interest_rate      */
/*  where                                                    */
/*	balance(0) = 0                                           */
/*	balance[T] = 0                                           */
/*  for interest_rate                                        */
/*                                                           */
/*  (c) 2008 Fair Isaac Corporation                          */
/*      authors: S.Heipcke, D.Brett.                         */
/*************************************************************/

using System;
using System.Text;
using System.IO;
using Optimizer;
using BCL;


namespace Examples
{
    public class TestAdvRecurse
    {
        int T = 6;

        /****DATA****/
        double X = 0.00;          /* An INITIAL GUESS as to interest rate x */
        double[] B = /* {796.35, 589.8918, 398.1351, 201.5451, 0.0, 0.0}; */
        {1,1,1,1,1,1};
        /* An INITIAL GUESS as to balances b(t) */
        double[] P = {-1000, 0, 0, 0, 0, 0};                 /* Payments */
        double[] R = {206.6, 206.6, 206.6, 206.6, 206.6, 0}; /*  "       */
        double[] V = {-2.95, 0, 0, 0, 0, 0};                 /*  "       */

        XPRBvar[] b;              /* Balance */
        XPRBvar x;                /* Interest rate */
        XPRBvar dx;               /* Change to x */
        XPRBctr[] interest;
        XPRBctr ctrd;

        XPRBprob p = new XPRBprob("Fin_nlp"); /* Initialize new BCL problem */

        /*********************************************************************/

        void modFinNLP()
        {
            XPRBvar[] i = new XPRBvar[T];                  /* Interest */
            XPRBvar[] n = new XPRBvar[T];                  /* Net */
            XPRBvar[] epl = new XPRBvar[T];
            XPRBvar[] emn = new XPRBvar[T];        /* + and - deviations */
            XPRBexpr cobj;
            int t;

            /****VARIABLES****/
            b = new XPRBvar[T];
            for(t=0;t<T;t++)
            {
                i[t]=p.newVar("i");
                n[t] = p.newVar("n", BCLconstant.XPRB_PL, 
                	-BCLconstant.XPRB_INFINITY, BCLconstant.XPRB_INFINITY);
                b[t] = p.newVar("b", BCLconstant.XPRB_PL, 
                	-BCLconstant.XPRB_INFINITY, BCLconstant.XPRB_INFINITY);
                epl[t]=p.newVar("epl");
                emn[t]=p.newVar("emn");
            }
            x=p.newVar("x");
            dx = p.newVar("dx", BCLconstant.XPRB_PL, 
            		-BCLconstant.XPRB_INFINITY, BCLconstant.XPRB_INFINITY);
            i[0].fix(0);
            b[T-1].fix(0);

            /****OBJECTIVE****/
            cobj = new XPRBexpr();
            for (t = 0; t < T; t++)
            {            /* Objective: get feasible */
                cobj += epl[t];
                cobj += emn[t];
            }
            p.setObj(p.newCtr("OBJ",cobj));    /* Select objective function */
            p.setSense(BCLconstant.XPRB_MINIM);/* Set sense of optimization */   

            /****CONSTRAINTS****/
            for(t=0;t<T;t++)
            {                              /* net = payments - interest */
                p.newCtr("net", new XPRBexpr(n[t]) == new XPRBexpr(P[t] + 
                	R[t] + V[t]) - new XPRBexpr(i[t]));
                
                /* Money balance across periods */
                if(t>0) 
                	p.newCtr("bal", new XPRBexpr(b[t]) == 
                				new XPRBexpr(b[t-1]-n[t]));
                else  
                	p.newCtr("bal", new XPRBexpr(b[t]) == 
                				new XPRBexpr(-n[t]));
            }

	    /* i(t) = (92/365)*( b(t-1)*X + B(t-1)*dx ) approx. */
            interest = new XPRBctr[T];
            for (t = 1; t < T; t++)    
                interest[t] = p.newCtr("int", X*b[t-1] + B[t-1]*dx + epl[t] - 
                		emn[t] == new XPRBexpr(365/92.0 * i[t]));

            ctrd = p.newCtr("def", new XPRBexpr(x) == new XPRBexpr(X) + 
            						new XPRBexpr(dx));
        }

        /*********************************************************************/
        /*  Recursion loop (repeat until variation of x converges to 0):     */
        /*    save current basis and the solutions for variables b[t] and x  */
        /*    set the balance estimates B[t] to the value of b[t]            */
        /*    set the interest rate estimate X to the value of x             */
        /*    reload the problem and the saved basis                         */
        /*    solve the LP and calculate the variation of x                  */
        /*********************************************************************/
        void solveFinNLP()
        {
            XPRBbasis basis;
            double variation=1.0, oldval, XC; 
            double[] BC = new double[T];
            int t, ct=0;
            XPRSprob xprsp = p.getXPRSprob();

            xprsp.CutStrategy = 0;
            /* Switch automatic cut generation off */

            p.lpOptimize();                    /* Solve the LP-problem */

            while(variation>0.000001)
            {
                ct++;
                basis=p.saveBasis();           /* Save the current basis */

                /* Get the solution values for b and x */
                for(t=1;t<T;t++) BC[t-1]=b[t-1].getSol();
                XC=x.getSol();
                System.Console.Write("Loop " + ct + ": " + x.getName() + ":" + 
                	x.getSol() + "  (variation:" + variation + ")\n");

                for(t=1;t<T;t++)      /* Change coefficients in interest[t] */
                {   
                    interest[t].setTerm(dx, BC[t-1]);
                    B[t-1]=BC[t-1];
                    interest[t].setTerm(b[t-1], XC);
                }
                ctrd.setTerm(XC);    /* Change constant term of ctrd */ 
                X=XC;

                oldval=XC;
                p.loadMat();         /* Reload the problem */
                p.loadBasis(basis);  /* Load the saved basis */
                basis.reset();       /* No need to keep the basis any longer */

                p.lpOptimize();         /* Solve the LP-problem */
                
                variation=System.Math.Abs(x.getSol()-oldval);
            }

 	    /* Get objective value */
            System.Console.Write("Objective: " + p.getObjVal() + "\n");
            System.Console.Write("Interest rate: " + x.getSol() + 
            					 "\nBalances:  ");
            
            /* Print out the solution values */					
            for(t=0;t<T;t++)                
                System.Console.Write(b[t].getName() + ":" + 
                		     b[t].getSol() + " ");
            System.Console.Write("\n");
        } 

        /*********************************************************************/

        public static void Main()
        {
           XPRB.init();
           TestAdvRecurse InitClassInstance = new TestAdvRecurse();

            InitClassInstance.b = new XPRBvar[InitClassInstance.T];
            InitClassInstance.ctrd = new XPRBctr();

            InitClassInstance.modFinNLP();             /* Model the problem */
            InitClassInstance.solveFinNLP();           /* Solve the problem */

            return;
        } 

    }

}

© 2001-2019 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.