![]() | |||||||||||
| |||||||||||
Implementing the polygon examples as a black box function Description Demonstrates how black box functions may be optimized using Xpress NonLinear, using tokeanised input Further explanation of this example: 'Xpress NonLinear Reference Manual'
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
Polygon_userfunc.c /*********************************************************************** Xpress Optimizer Examples ========================= file Polygon_userfunc.c ``````````````````````` Implement the polygon example using a user function. 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. A user (black box) function is used to implement the problem. (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 MAXFORMULA 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) double XPRS_CC MyFunc(double* Values, void* Context); int main(int argc, char* argv[]) { XPRSprob xprob = NULL; XSLPprob sprob = NULL; int nRow, nCol, nSide, nElement, nToken, nformula, 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], ColIndex[MAXCOL]; int FormulaStart[MAXFORMULA + 1]; int Type[MAXTOKEN]; double Value[MAXTOKEN]; int VarType[MAXCOL]; double InitialValue[MAXCOL]; int functionID; int ReturnValue = 1; int i, j; char RowNames[500], ColNames[500]; void* Func; int nMyFuncArguments; /* 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; /* 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_CSTYLE, 1)); 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)); /* Define user function */ nToken = 0; nMyFuncArguments = 2 * (nSide - 1); CHECK_XPRSCALL(XSLPadduserfunction(sprob, "MyArea", XSLP_USERFUNCTION_VECMAP, 2 * (nSide - 1), 1, 0, (XPRSfunctionptr) &MyFunc, &nMyFuncArguments, &functionID)); /* Build up nonlinear coefficients */ /* Area */ nToken = 0; nformula = 0; RowIndex[nformula] = 0; FormulaStart[nformula++] = nToken; Type[nToken] = XSLP_RB; Value[nToken++] = 0; for (i = nSide - 1; i > 0; i--) { Type[nToken] = XSLP_COL; Value[nToken++] = i; Type[nToken] = XSLP_COL; Value[nToken++] = nSide + i - 1; } Type[nToken] = XSLP_FUN; Value[nToken++] = functionID; Type[nToken] = XSLP_EOF; Value[nToken++] = 0; /* Distances */ for (i = 1; i < nSide - 1; i++) { for (j = i + 1; j < nSide; j++) { RowIndex[nformula] = iRow++; FormulaStart[nformula++] = nToken; Type[nToken] = XSLP_COL; Value[nToken++] = nSide + i - 1; Type[nToken] = XSLP_CON; Value[nToken++] = 2; Type[nToken] = XSLP_OP; Value[nToken++] = XSLP_EXPONENT; Type[nToken] = XSLP_COL; Value[nToken++] = nSide + j - 1; 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 - 1; Type[nToken] = XSLP_OP; Value[nToken++] = XSLP_MULTIPLY; Type[nToken] = XSLP_COL; Value[nToken++] = nSide + j - 1; 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[nformula] = nToken; CHECK_XPRSCALL(XSLPloadformulas(sprob, nformula, RowIndex, 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_userfunc", "")); CHECK_XPRSCALL(XSLPmaxim(sprob, "")); CHECK_XPRSCALL(XSLPwriteslxsol(sprob, "Polygon_userfunc", "")); 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; } } double XPRS_CC MyFunc(double* Values, void* Context) { int i; double Area; int* nMyFuncArguments = (int*)Context; Area = 0; for (i = 3; i < (*nMyFuncArguments); i = i + 2) { Area = Area + 0.5 * Values[i - 3] * Values[i - 1] * sin(Values[i] - Values[i - 2]); } return Area; }
| |||||||||||
© Copyright 2022 Fair Isaac Corporation. |