| |||||||||||||
Recurse - A successive linear programming model 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.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
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-2024 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; } } } | |||||||||||||
© Copyright 2024 Fair Isaac Corporation. |