static int CPXPUBLIC timelimcallback (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle) { int status = 0; TIMELIMINFOptr info = (TIMELIMINFOptr) cbhandle; int hasincumbent = 0; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIP_FEAS, &hasincumbent); if ( status ) goto TERMINATE; if ( !info->aborted && hasincumbent ) { double gap; double timenow; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIP_REL_GAP, &gap); if ( status ) goto TERMINATE; /* Turn the gap into a percentage */ gap *= 100.0; status = CPXgettime (env, &timenow); if ( status ) goto TERMINATE; if ( timenow - info->timestart > info->timelim && gap < info->acceptablegap ) { fprintf (stderr, "Good enough solution at time %.2fsec, gap = %g%%, quitting\n", timenow - info->timestart, gap); /* callback may be called again during the clean up phase after the abort has been issued, so remember that abort processing has already occurred. */ info->aborted = 1; /* nonzero status causes abort */ status = 1; } } TERMINATE: return (status); } /* END timelimcallback */
static int CPXPUBLIC userselectnode (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle, int *nodenum_p, int *useraction_p) { int status = 0; int thisnode; int nodesleft; int bestnode = 0; int depth; int maxdepth = -1; double siinf; double maxsiinf = 0.0; /* Initialize useraction to indicate no user node selection */ *useraction_p = CPX_CALLBACK_DEFAULT; /* Choose the node with the largest sum of infeasibilities among those at the greatest depth */ status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_NODES_LEFT, &nodesleft); if ( status ) goto TERMINATE; for (thisnode = 0; thisnode < nodesleft; thisnode++) { status = CPXgetcallbacknodeinfo (env, cbdata, wherefrom, thisnode, CPX_CALLBACK_INFO_NODE_DEPTH, &depth); if ( !status ) { status = CPXgetcallbacknodeinfo (env, cbdata, wherefrom, thisnode, CPX_CALLBACK_INFO_NODE_SIINF, &siinf); } if ( status ) break; if ( (depth >= maxdepth) && (depth > maxdepth || siinf > maxsiinf) ) { bestnode = thisnode; maxdepth = depth; maxsiinf = siinf; } } *nodenum_p = bestnode; *useraction_p = CPX_CALLBACK_SET; TERMINATE: return (status); } /* END userselectnode */
static int CPXPUBLIC mycallback (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle) { int status = 0; int phase = -1; double suminf_or_objective; int itcnt = -1; if ( wherefrom == CPX_CALLBACK_PRIMAL ) { status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_ITCOUNT, &itcnt); if ( status ) goto TERMINATE; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_PRIMAL_FEAS, &phase); if ( status ) goto TERMINATE; if ( phase == 0 ) { status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_PRIMAL_INFMEAS, &suminf_or_objective); if ( status ) goto TERMINATE; printf ("Iteration %d: Infeasibility measure = %f\n", itcnt, suminf_or_objective); } else { status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_PRIMAL_OBJ, &suminf_or_objective); if ( status ) goto TERMINATE; printf ("Iteration %d: Objective = %f\n", itcnt, suminf_or_objective); } } TERMINATE: return (status); } /* END mycallback */
static int CPXPUBLIC SetInfoCallbackFunc(CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle) { // Documentation: // http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r3/index.jsp?topic=%2Filog.odms.cplex.help%2FContent%2FOptimization%2FDocumentation%2FOptimization_Studio%2F_pubskel%2Fps_usrmancplex2082.html // http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r3/index.jsp?topic=%2Filog.odms.cplex.help%2Fhtml%2Frefcallablelibrary%2Fhtml%2Ffunctions%2FCPXgetcallbackinfo.html CplexData* d = (CplexData*)cbhandle; double objval = 0, bestBound = 0, feasibleSolution = 0; CPXgetcallbackinfo(env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_INTEGER, &objval); CPXgetcallbackinfo(env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_REMAINING, &bestBound); CPXgetcallbackinfo(env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIP_FEAS, &feasibleSolution); if (d->callbackFunction(objval, bestBound, feasibleSolution >= 1)) { return 1; } return 0; }
static int CPXPUBLIC usersolve (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle, int *useraction_p) { int status = 0; int nodecount; CPXLPptr nodelp; *useraction_p = CPX_CALLBACK_DEFAULT; /* Get pointer to LP subproblem */ status = CPXgetcallbacknodelp (env, cbdata, wherefrom, &nodelp); if ( status ) goto TERMINATE; /* Find out what node is being processed */ status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_NODE_COUNT, &nodecount); if ( status ) goto TERMINATE; /* Solve initial node with primal, others with dual */ if ( nodecount < 1 ) status = CPXprimopt (env, nodelp); else status = CPXdualopt (env, nodelp); /* If the solve was OK, set return to say optimization has been done in callback, otherwise return the CPLEX error code */ if ( !status ) *useraction_p = CPX_CALLBACK_SET; TERMINATE: return (status); } /* END usersolve */
//******************************************************************* // callback stuff /////////////////////////////////////////////////// //******************************************************************* // cplex callback function int CPXPUBLIC CSolver:: lpcallback(CPXCENVptr env, void* lpinfo, int wherefrom, void* cbhandle) { int status; CLogger* pLogger; CSolver* pSolver; CcbData* pMyEnv; pMyEnv = (CcbData*)(cbhandle); if (pMyEnv == NULL ) { return 0; } pSolver = (CSolver*)pMyEnv->pThis; pLogger = pSolver->GetLogger(); if ( pMyEnv->abort == 1 ) return 1; if (pMyEnv->bMip == true && wherefrom == CPX_CALLBACK_MIP) { // MIP status = CPXgetcallbackinfo(env, lpinfo, wherefrom, CPX_CALLBACK_INFO_BEST_INTEGER, &pMyEnv->objval); if ( status ) { pLogger->write("getcallbackinfo failed for BEST_INTEGER"); return 0; } status = CPXgetcallbackinfo(env, lpinfo, wherefrom, CPX_CALLBACK_INFO_NODE_COUNT, &pMyEnv->mipNodeCnt); if ( status ) { pLogger->write("getcallbackinfo failed for NODE COUNT"); return 0; } status = CPXgetcallbackinfo(env, lpinfo, wherefrom, CPX_CALLBACK_INFO_MIP_ITERATIONS, &pMyEnv->itcnt); if ( status ) { pLogger->write("getcallbackinfo failed for MIP ITERATIONS"); return 0; } status = CPXgetcallbackinfo(env, lpinfo, wherefrom, CPX_CALLBACK_INFO_NODES_LEFT, &pMyEnv->mipNodesLeft); if ( status ) { pLogger->write("getcallbackinfo failed for NODES LEFT"); return 0; } char buff[1000]; if ( pMyEnv->objval > INFBOUND ) { sprintf(buff,"Iteration = %d Objective = %s NodeCnt = %d NodesLeft = %d", pMyEnv->itcnt, "INFBOUND", pMyEnv->mipNodeCnt, pMyEnv->mipNodesLeft); } else sprintf(buff,"Iteration = %d Objective = %.2f NodeCnt = %d NodesLeft = %d", pMyEnv->itcnt, pMyEnv->objval, pMyEnv->mipNodeCnt, pMyEnv->mipNodesLeft); if ( pMyEnv->pFunc != NULL) pMyEnv->pFunc(buff, pMyEnv->pSelf); } else { // LP status = CPXgetcallbackinfo (env, lpinfo, wherefrom, CPX_CALLBACK_INFO_ITCOUNT, &pMyEnv->itcnt); if ( status ) { pLogger->write("getcallbackinfo failed for ITCOUNT"); return 0; } status = CPXgetcallbackinfo( env, lpinfo, wherefrom, CPX_CALLBACK_INFO_PRIMAL_OBJ, &pMyEnv->objval); if ( status ) { pLogger->write("getcallbackinfo failed for PRIMAL_OBJ"); return 0; } char buff[1000]; sprintf(buff,"Iteration = %d Objective = %.2f ", pMyEnv->itcnt, pMyEnv->objval); if ( pMyEnv->pFunc != NULL) pMyEnv->pFunc(buff, pMyEnv->pSelf); } return 0; }
static int CPXPUBLIC logcallback (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle) { int status = 0; LOGINFOptr info = (LOGINFOptr) cbhandle; int hasincumbent = 0; int newincumbent = 0; int nodecnt; int nodesleft; double objval; double bound; double *x = NULL; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_NODE_COUNT, &nodecnt); if ( status ) goto TERMINATE; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_NODES_LEFT, &nodesleft); if ( status ) goto TERMINATE; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIP_FEAS, &hasincumbent); if ( status ) goto TERMINATE; if ( hasincumbent ) { status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_INTEGER, &objval); if ( status ) goto TERMINATE; if ( fabs(info->lastincumbent - objval) > 1e-5*(1.0 + fabs(objval)) ) { newincumbent = 1; info->lastincumbent = objval; } } if ( nodecnt >= info->lastlog + 100 || newincumbent ) { double walltime; double dettime; status = CPXgetcallbackinfo (env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_REMAINING, &bound); if ( status ) goto TERMINATE; if ( !newincumbent ) info->lastlog = nodecnt; status = CPXgettime (env, &walltime); if ( status ) goto TERMINATE; status = CPXgetdettime (env, &dettime); if ( status ) goto TERMINATE; printf ("Time = %.2f Dettime = %.2f Nodes = %d(%d) Best objective = %g", walltime - info->timestart, dettime - info->dettimestart, nodecnt, nodesleft, bound); if ( hasincumbent ) printf (" Incumbent objective = %g\n", objval); else printf ("\n"); } if ( newincumbent ) { int j; int numcols = info->numcols; x = (double *) malloc (numcols*sizeof(double)); if ( x == NULL ) { status = CPXERR_NO_MEMORY; goto TERMINATE; } status = CPXgetcallbackincumbent (env, cbdata, wherefrom, x, 0, numcols-1); if ( status ) goto TERMINATE; printf ("New incumbent values:\n"); for (j = 0; j < numcols; j++) { if ( fabs(x[j]) > 1e-6 ) { printf (" Column %d: %g\n", j, x[j]); } } } TERMINATE: free_and_null ((char **) &x); return (status); } /* END logcallback */