FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Providing initial values

Description
Demonstrates how to add initial values to nonlinear variables

Further explanation of this example: 'Xpress NonLinear Reference Manual'

PolygonInitialValue.zip[download all files]

Source Files





Polygon_initialvalue.c

/***********************************************************************
   Xpress Optimizer Examples
   =========================

   file Polygon_initialvalue.c
   ``````````````````````````
   Implement the polygon example using tokens and initial values

   Maximize the area of polygon of N vertices and diameter of 1
   The position of vertices is indicated as (rho,theta) coordinates
   where rho denotes the distance to the base point
   (vertex with number N) and theta the angle from the x-axis.
   The nonlinear expressions are described using formula tokens,
   and providing initial values to the nonlinear variables.

   This example uses the coefficients interface; see other examples
   for using the simplified formula interface.

   (c) 2017 Fair Isaac Corporation
***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "xprs.h"
#include "xslp.h"

#define MAXROW 20
#define MAXCOL 20
#define MAXELT 50
#define MAXTOKEN 200
#define MAXCOEF 20

#define PI 3.14159

void XPRS_CC XSLPMessage(XSLPprob my_prob, void* my_object, const char* msg, int len, int msg_type);

/* Perform the Xpress specified function call and check its return value. */
#define CHECK_XPRSCALL(call)                             \
  do {                                                   \
    int result_ = call;                                  \
    if ( result_ != 0 ) {                                \
      fprintf(stderr, "Line %d: Failed call to `%s`.\n", \
              __LINE__, #call);                          \
      goto returnWithError;                              \
    }                                                    \
  } while (0)

int main(int argc, char* argv[]) {
  XPRSprob xprob = NULL;
  XSLPprob sprob = NULL;

  int nRow, nCol, nSide, nElement, nToken, nCoef, nRowName, nColName;
  int iRow, Sin, Cos;
  char RowType[MAXROW];
  double RHS[MAXROW], OBJ[MAXCOL], Element[MAXELT], Lower[MAXCOL], Upper[MAXCOL];
  int ColStart[MAXCOL + 1], RowIndex[MAXELT];
  int ColIndex[MAXCOEF], FormulaStart[MAXCOEF + 1];
  int Type[MAXTOKEN];
  double Value[MAXTOKEN], Factor[MAXCOEF];

  int VarType[MAXCOL];
  double InitialValue[MAXCOL];

  int ReturnValue = 0;
  int i, j;
  char RowNames[500], ColNames[500];

  /* Initialisation */
  CHECK_XPRSCALL(XPRSinit(NULL));
  CHECK_XPRSCALL(XSLPinit());
  CHECK_XPRSCALL(XPRScreateprob(&xprob));
  CHECK_XPRSCALL(XSLPcreateprob(&sprob, &xprob));

  /* XSLPsetcbmessage */
  CHECK_XPRSCALL(XSLPsetcbmessage(sprob, XSLPMessage, NULL));

  nSide = 5;
  nRowName = 0;

  /* Rows */
  nRow = nSide - 2 + (nSide - 1) * (nSide - 2) / 2 + 1;
  for (i = 0; i < nRow; i++) RHS[i] = 0;

  nRow = 0;
  RowType[nRow++] = 'E'; /* OBJEQ */
  nRowName = nRowName + 1 + sprintf(&RowNames[nRowName], "OBJEQ");
  for (i = 1; i < nSide - 1; i++) {
    RowType[nRow++] = 'G'; /* T2T1 .. T4T3 */
    RHS[i] = 0.001;
    nRowName = nRowName + 1 + sprintf(&RowNames[nRowName], "T%dT%d", i + 1, i);
  }

  for (i = 1; i < nSide - 1; i++) {
    for (j = i + 1; j < nSide; j++) {
      RowType[nRow] = 'L';
      RHS[nRow++] = 1.0;
      nRowName = nRowName + 1 + sprintf(&RowNames[nRowName], "V%dV%d", i, j);
    }
  }
  RowType[nRow] = '\0';

  /* Columns */
  nColName = 0;
  nCol = (nSide - 1) * 2 + 2;
  nElement = 0;
  for (i = 0; i < nCol; i++) {
    OBJ[i] = 0;					  /* objective function */
    Lower[i] = 0;				  /* lower bound normally zero */
    Upper[i] = XPRS_PLUSINFINITY; /* upper bound infinity */
  }

  /* OBJX */
  nCol = 0;
  ColStart[nCol] = nElement;
  OBJ[nCol] = 1.0;
  Lower[nCol++] = XPRS_MINUSINFINITY; /* free column */
  Element[nElement] = -1.0;
  RowIndex[nElement++] = 0;
  nColName = nColName + 1 + sprintf(&ColNames[nColName], "OBJX");

  /* THETA1 - THETA 4 */
  iRow = 0;
  for (i = 1; i < nSide; i++) {
    nColName = nColName + 1 + sprintf(&ColNames[nColName], "THETA%d", i);
    InitialValue[nCol] = PI * ((double)(i)) / ((double)(nSide));
    VarType[nCol] = 4;
    ColStart[nCol++] = nElement;
    if (i < nSide - 1) {
      Element[nElement] = -1;
      RowIndex[nElement++] = iRow + 1;
    }
    if (i > 1) {
      Element[nElement] = 1;
      RowIndex[nElement++] = iRow;
    }
    iRow++;
  }

  Upper[nCol - 1] = PI;

  /* Equals column */
  nColName = nColName + 1 + sprintf(&ColNames[nColName], "=");
  ColStart[nCol] = nElement;
  Lower[nCol] = Upper[nCol] = 1.0; /* fixed at 1.0 */
  InitialValue[nCol] = 1;
  VarType[nCol] = 4 | 0x4000;
  nCol++;

  /* Remaining columns come later */
  for (i = 1; i < nSide; i++) {
    Lower[nCol] = 0.01;	  /* lower bound */
    Upper[nCol] = 1;
    InitialValue[nCol] = 1;
    VarType[nCol] = 4;
    ColStart[nCol++] = nElement;
    nColName = nColName + 1 + sprintf(&ColNames[nColName], "RHO%d", i);
  }
  ColStart[nCol] = nElement;

  CHECK_XPRSCALL(XPRSsetintcontrol(xprob, XPRS_MPSNAMELENGTH, 16));

  CHECK_XPRSCALL(XPRSloadlp(xprob, "Polygon", nCol, nRow, RowType, RHS, NULL, OBJ,
    ColStart, NULL, RowIndex, Element, Lower, Upper));
  CHECK_XPRSCALL(XPRSaddnames(xprob, 1, RowNames, 0, nRow - 1));
  CHECK_XPRSCALL(XPRSaddnames(xprob, 2, ColNames, 0, nCol - 1));

  /* Find index for SIN and COS */
  CHECK_XPRSCALL(XSLPgetindex(sprob, XSLP_INTERNALFUNCNAMES, "SIN", &Sin));
  CHECK_XPRSCALL(XSLPgetindex(sprob, XSLP_INTERNALFUNCNAMES, "COS", &Cos));


  /* Build up nonlinear coefficients */
  /* Area */
  nToken = 0;
  nCoef = 0;
  RowIndex[nCoef] = 0;
  ColIndex[nCoef] = nSide;
  Factor[nCoef] = 0.5;
  FormulaStart[nCoef++] = nToken;
  for (i = 1; i < nSide - 1; i++) {
    Type[nToken] = XSLP_COL;
    Value[nToken++] = nSide + i + 1;
    Type[nToken] = XSLP_COL;
    Value[nToken++] = nSide + i;
    Type[nToken] = XSLP_OP;
    Value[nToken++] = XSLP_MULTIPLY;
    Type[nToken] = XSLP_RB;
    Value[nToken++] = 0;
    Type[nToken] = XSLP_COL;
    Value[nToken++] = i + 1;
    Type[nToken] = XSLP_COL;
    Value[nToken++] = i;
    Type[nToken] = XSLP_OP;
    Value[nToken++] = XSLP_MINUS;
    Type[nToken] = XSLP_IFUN;
    Value[nToken++] = Sin;
    Type[nToken] = XSLP_OP;
    Value[nToken++] = XSLP_MULTIPLY;
    if (i > 1) {
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_PLUS;
    }
  }
  Type[nToken] = XSLP_EOF;
  Value[nToken++] = 0;

  /* Distances */
  for (i = 1; i < nSide - 1; i++) {
    for (j = i + 1; j < nSide; j++) {
      RowIndex[nCoef] = iRow++;
      ColIndex[nCoef] = nSide;
      Factor[nCoef] = 1.0;
      FormulaStart[nCoef++] = nToken;

      Type[nToken] = XSLP_COL;
      Value[nToken++] = nSide + i;
      Type[nToken] = XSLP_CON;
      Value[nToken++] = 2;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_EXPONENT;
      Type[nToken] = XSLP_COL;
      Value[nToken++] = nSide + j;
      Type[nToken] = XSLP_CON;
      Value[nToken++] = 2;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_EXPONENT;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_PLUS;
      Type[nToken] = XSLP_CON;
      Value[nToken++] = 2;
      Type[nToken] = XSLP_COL;
      Value[nToken++] = nSide + i;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_MULTIPLY;
      Type[nToken] = XSLP_COL;
      Value[nToken++] = nSide + j;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_MULTIPLY;
      Type[nToken] = XSLP_RB;
      Value[nToken++] = 0;
      Type[nToken] = XSLP_COL;
      Value[nToken++] = j;
      Type[nToken] = XSLP_COL;
      Value[nToken++] = i;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_MINUS;
      Type[nToken] = XSLP_IFUN;
      Value[nToken++] = Cos;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_MULTIPLY;
      Type[nToken] = XSLP_OP;
      Value[nToken++] = XSLP_MINUS;
      Type[nToken] = XSLP_EOF;
      Value[nToken++] = 0;
    }
  }
  FormulaStart[nCoef] = nToken;

  CHECK_XPRSCALL(XSLPloadcoefs(sprob, nCoef, RowIndex, ColIndex, Factor, FormulaStart, 1, Type, Value));

  for (i = 0; i < nCol; i++) {
    ColIndex[i] = i;
  }

  CHECK_XPRSCALL(XSLPloadvars(sprob, nCol - 1, &ColIndex[1], &VarType[1], NULL, NULL, NULL, &InitialValue[1], NULL));

  CHECK_XPRSCALL(XSLPwriteprob(sprob, "Polygon_initialvalue", ""));

  CHECK_XPRSCALL(XSLPmaxim(sprob, ""));
  CHECK_XPRSCALL(XSLPwriteslxsol(sprob, "Polygon_initialvalue2", ""));

  goto NormalReturn;
returnWithError:
  printf("\nError %d", ReturnValue);
  ReturnValue = -1;
NormalReturn:

  // Retrieve error from Xpress
  if (ReturnValue) {
    fprintf(stderr, "An error was detected during execution.\n");
    if (xprob && sprob) {
      int errorcode;
      char errorMessage[512];
      XSLPgetlasterror(sprob, &errorcode, errorMessage);
      if (errorcode == 0) {
        XPRSgetintattrib(xprob, XPRS_ERRORCODE, &errorcode);
        XPRSgetlasterror(xprob, errorMessage);
      }
      fprintf(stderr, "Optimizer returned error code '%i' with message:\n%s\n", errorcode, errorMessage);
    }
  }

  XSLPdestroyprob(sprob);
  XPRSdestroyprob(xprob);
  XSLPfree();
  XPRSfree();
  return(ReturnValue);
}

void XPRS_CC XSLPMessage(XSLPprob my_prob, void* my_object, const char* msg, int len, int msg_type) {
  switch (msg_type) {
  case 4: /* error */
  case 3: /* warning */
  case 2: /* dialogue */
  case 1: /* information */
    printf("%s\n", msg);
    break;
  default: /* exiting */
    fflush(stdout);
    break;
  }
}

Back to examples browserPrevious exampleNext example