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.c


xbrecurs.c
/********************************************************
  BCL Example Problems
  ====================

  file xbrecurs.c
  ```````````````
  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
      author: S.Heipcke, 2001, rev. Mar. 2011
********************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "xprb.h"
#include "xprs.h"

#define 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[T];                   /* Balance */
XPRBvar x;                      /* Interest rate */
XPRBvar dx;                     /* Change to x */
XPRBctr interest[T], ctrd;

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

void modfinnlp(XPRBprob prob)
{
 XPRBvar i[T];                  /* Interest */
 XPRBvar n[T];                  /* Net */
 XPRBvar epl[T], emn[T];        /* + and - deviations */
 XPRBctr cobj, bal, net;
 int t;

/****VARIABLES****/
 for(t=0;t<T;t++)
 {
  i[t]=XPRBnewvar(prob,XPRB_PL, "i", 0, XPRB_INFINITY);
  n[t]=XPRBnewvar(prob,XPRB_PL, "n", -XPRB_INFINITY, XPRB_INFINITY);
  b[t]=XPRBnewvar(prob,XPRB_PL, "b", -XPRB_INFINITY, XPRB_INFINITY);
  epl[t]=XPRBnewvar(prob,XPRB_PL, "epl", 0, XPRB_INFINITY);
  emn[t]=XPRBnewvar(prob,XPRB_PL, "emn", 0, XPRB_INFINITY);
 }
 x=XPRBnewvar(prob,XPRB_PL, "x", 0, XPRB_INFINITY);
 dx=XPRBnewvar(prob,XPRB_PL, "dx", -XPRB_INFINITY, XPRB_INFINITY);
 XPRBfixvar(i[0],0);
 XPRBfixvar(b[T-1],0);

/****OBJECTIVE****/
 cobj = XPRBnewctr(prob,"OBJ",XPRB_N);  /* Objective: get feasible */
 for(t=0;t<T;t++)
 {
  XPRBaddterm(cobj,epl[t],1);
  XPRBaddterm(cobj,emn[t],1);
 }
 XPRBsetobj(prob,cobj);                 /* Select objective function */
 XPRBsetsense(prob,XPRB_MINIM);         /* Choose the sense of the optimization */

/****CONSTRAINTS****/
 for(t=0;t<T;t++)
 {
  net=XPRBnewctr(prob,"net", XPRB_E);   /* net = payments - interest */
  XPRBaddterm(net, NULL, P[t]+R[t]+V[t]);
  XPRBaddterm(net, n[t], 1);
  XPRBaddterm(net, i[t], 1);
  bal=XPRBnewctr(prob,"bal", XPRB_E);   /* Money balance across periods */
  XPRBaddterm(bal, b[t], 1);
  if(t>0) XPRBaddterm(bal, b[t-1], -1);
  XPRBaddterm(bal, n[t], 1);
 }

 for(t=1;t<T;t++)
 {                   /* i(t) = (92/365)*( b(t-1)*X + B(t-1)*dx ) approx. */
  interest[t]=XPRBnewctr(prob,"int", XPRB_E);
  XPRBaddterm(interest[t], i[t], -(365/92.0));
  XPRBaddterm(interest[t], b[t-1], X);
  XPRBaddterm(interest[t], dx, B[t-1]);
  XPRBaddterm(interest[t], epl[t], 1);
  XPRBaddterm(interest[t], emn[t], -1);
 }

 ctrd=XPRBnewctr(prob,"def", XPRB_E);    /* X + dx = x */
 XPRBaddterm(ctrd, NULL, X);
 XPRBaddterm(ctrd, x, 1);
 XPRBaddterm(ctrd, dx, -1);
}

/**************************************************************************/
/*  Recursion loop (repeat until variation of x converges to 0):          */
/*    save the 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(XPRBprob prob)
{
 XPRBbasis basis;
 double variation=1.0, oldval, BC[T], XC;
 int t, ct=0;

 XPRSsetintcontrol(XPRBgetXPRSprob(prob), XPRS_CUTSTRATEGY, 0);
                                   /* Switch automatic cut generation off */

 XPRBlpoptimize(prob,"");          /* Solve the LP-problem */

 while(variation>0.000001)
 {
  ct++;
  basis=XPRBsavebasis(prob);       /* Save the current basis */

                                   /* Get the solution values for b and x */
  for(t=1;t<T;t++) BC[t-1]=XPRBgetsol(b[t-1]);
  XC=XPRBgetsol(x);
  printf("Loop %d: %s:%g  (variation:%g)\n", ct, XPRBgetvarname(x),
    XPRBgetsol(x),variation);

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

  oldval=XC;
  XPRBloadmat(prob);               /* Reload the problem */
  XPRBloadbasis(basis);            /* Load the saved basis */
  XPRBdelbasis(basis);             /* No need to keep the basis any longer */
  XPRBlpoptimize(prob,"");         /* Solve the LP-problem */
  variation=fabs(XPRBgetsol(x)-oldval);
 }

 printf("Objective: %g\n", XPRBgetobjval(prob));  /* Get objective value */
 printf("Interest rate: %g%%\nBalances:  ", XPRBgetsol(x)*100);
 for(t=0;t<T;t++)                  /* Print out the solution values */
  printf("%s:%g ", XPRBgetvarname(b[t]), XPRBgetsol(b[t]));
 printf("\n");
}

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

int main(int argc, char **argv)
{
 XPRBprob prob;

 prob=XPRBnewprob("Fin_nlp");      /* Initialize a new problem in BCL */
 modfinnlp(prob);                  /* Model the problem */
 solvefinnlp(prob);                /* Solve the problem */

 return 0;
}

© 2001-2020 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.