All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nlpioracle.c
Go to the documentation of this file.
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
68 int* vardegrees; /**< array with maximal degree of variable over objective and all constraints */
78 int* jaccols; /**< rowwise jacobi sparsity pattern: indices of variables appearing in constraints */
80 int* heslagoffsets; /**< rowwise sparsity pattern of hessian matrix of Lagrangian: row offsets in heslagcol */
81 int* heslagcols; /**< rowwise sparsity pattern of hessian matrix of Lagrangian: column indices; sorted for each row */
84 SCIP_EXPRINT* exprinterpreter; /**< interpreter for expression trees: evaluation and derivatives */
100 /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
124 SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->varlbs, oracle->varssize, newsize) );
125 SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->varubs, oracle->varssize, newsize) );
128 SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->varnames, oracle->varssize, newsize) );
130 SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->vardegrees, oracle->varssize, newsize) );
155 SCIP_ALLOC( BMSreallocBlockMemoryArray(oracle->blkmem, &oracle->conss, oracle->consssize, newsize) );
190 /** ensures that arrays for quadratic part in a oracle constraints have at least a given length */
286 BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->heslagcols, oracle->heslagoffsets[oracle->nvars]);
349 const int* exprvaridxs, /**< indicies of variables in expression tree, or NULL if exprtree == NULL */
399 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->exprvaridxs, exprvaridxs, SCIPexprtreeGetNVars((SCIP_EXPRTREE*)exprtree)) );
438 BMSfreeBlockMemoryArrayNull(blkmem, &(*cons)->exprvaridxs, SCIPexprtreeGetNVars((*cons)->exprtree));
535 BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[i], strlen(oracle->varnames[i])+1); /*lint !e866*/
670 /** removes entries with index pair (-1,-1) (marked as deleted) from array of quadratic elements
820 SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
900 SCIPdebug( if( isnewx ) {printf("\nx ="); for( i = 0; i < nvars; ++i) printf(" %g", xx[i]); /*lint !e613*/ printf("\n");} )
902 SCIP_CALL( SCIPexprintGrad(oracle->exprinterpreter, cons->exprtree, xx, isnewx, &nlval, g) ); /*lint !e644*/
937 /** collects nonzeros entries in colnz and increases the nzcount given indices of quadratic terms */
944 int* nzcount, /**< counter for total number of nonzeros; should be increased whenever some colnnz is increased */
965 if( colnz[quadelems->idx2] == NULL || !SCIPsortedvecFindInt(colnz[quadelems->idx2], quadelems->idx1, colnnz[quadelems->idx2], &pos) )
967 SCIP_CALL( ensureIntArraySize(oracle->blkmem, &colnz[quadelems->idx2], &collen[quadelems->idx2], colnnz[quadelems->idx2]+1) );
968 SCIPsortedvecInsertInt(colnz[quadelems->idx2], quadelems->idx1, &colnnz[quadelems->idx2], NULL);
976 /** collects indices of nonzero entries in the lower-left part of the hessian matrix of an expression
984 int* nzcount, /**< counter for total number of nonzeros; should be increased when nzflag is set to 1 the first time */
1018 x[i] = 2.0; /* hope that this value does not make much trouble for the evaluation routines */ /*lint !e644*/
1020 SCIP_CALL( SCIPexprintHessianSparsityDense(oracle->exprinterpreter, exprtree, x, hesnz) ); /*lint !e644*/
1072 if( !SCIPsortedvecFindInt(&hescol[hesoffset[quadelems->idx2]], quadelems->idx1, hesoffset[quadelems->idx2 + 1] - hesoffset[quadelems->idx2], &idx) ) /*lint !e613*/
1077 values[hesoffset[quadelems->idx2] + idx] += weight * ((quadelems->idx1 == quadelems->idx2) ? 2 * quadelems->coef : quadelems->coef); /*lint !e613*/
1139 SCIP_CALL( SCIPexprintHessianDense(oracle->exprinterpreter, exprtree, xx, new_x, &val, h) ); /*lint !e644*/
1145 return SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
1161 return SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
1167 if( !SCIPsortedvecFindInt(&hescol[hesoffset[row]], col, hesoffset[row+1] - hesoffset[row], &idx) )
1186 /** prints a name, if available, makes sure it has not more than 64 characters, and adds a unique prefix if the longnames flag is set */
1192 char prefix, /**< a letter (typically 'x' or 'e') to distinguish variable and equation names, if names[idx] is not available */
1200 sprintf(buffer, "%c%05d%.*s%s", prefix, idx, suffix ? (int)(57-strlen(suffix)) : 57, name, suffix ? suffix : "");
1239 printName(namebuf, oracle->varnames != NULL ? oracle->varnames[cons->linidxs[i]] : NULL, cons->linidxs[i], 'x', NULL, longvarnames);
1248 printName(namebuf, oracle->varnames != NULL ? oracle->varnames[cons->quadelems[i].idx1] : NULL, cons->quadelems[i].idx1, 'x', NULL, longvarnames);
1250 printName(namebuf, oracle->varnames != NULL ? oracle->varnames[cons->quadelems[i].idx2] : NULL, cons->quadelems[i].idx2, 'x', NULL, longvarnames);
1259 SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &varnames, SCIPexprtreeGetNVars(cons->exprtree)) ); /*lint !e666*/
1265 SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &varnames[i], 70) ); /*lint !e866 !e506 !e644*/
1266 printName(varnames[i], oracle->varnames != NULL ? oracle->varnames[cons->exprvaridxs[i]] : NULL, cons->exprvaridxs[i], 'x', NULL, longvarnames);
1341 SCIP_CALL( createConstraint((*oracle)->blkmem, &(*oracle)->objective, 0, NULL, NULL, 0, NULL, NULL, NULL, 0.0, 0.0, NULL) );
1420 SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &oracle->name, name, strlen(name)+1) );
1442 const SCIP_Real* lbs, /**< array with lower bounds of new variables, or NULL if all -infinity */
1443 const SCIP_Real* ubs, /**< array with upper bounds of new variables, or NULL if all +infinity */
1444 const char** varnames /**< array with names of new variables, or NULL if no names should be stored */
1498 SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &oracle->varnames[oracle->nvars+i], varnames[i], strlen(varnames[i])+1) ); /*lint !e866*/
1527 const SCIP_Real* lhss, /**< array with left-hand sides of constraints, or NULL if all -infinity */
1528 const SCIP_Real* rhss, /**< array with right-hand sides of constraints, or NULL if all +infinity */
1529 const int* nlininds, /**< number of linear coefficients for each constraint, may be NULL in case of no linear part */
1530 int* const* lininds, /**< indices of variables for linear coefficients for each constraint, may be NULL in case of no linear part */
1531 SCIP_Real* const* linvals, /**< values of linear coefficient for each constraint, may be NULL in case of no linear part */
1532 const int* nquadelems, /**< number of elements in matrix of quadratic part for each constraint,
1534 SCIP_QUADELEM* const* quadelems, /**< quadratic elements specifying quadratic part for each constraint, entry of array may be NULL in case of no quadratic part,
1536 int* const* exprvaridxs, /**< NULL if no nonquadratic parts, otherwise epxrvaridxs[.] maps variable indices in expression tree to indices in nlp */
1537 SCIP_EXPRTREE* const* exprtrees, /**< NULL if no nonquadratic parts, otherwise exprtrees[.] gives nonquadratic part,
1557 invalidateJacobiSparsity(oracle); /* @TODO we could also update (extend) the sparsity pattern */
1609 const SCIP_QUADELEM* quadelems, /**< entries in matrix of quadratic part, may be NULL in case of no quadratic part */
1610 const int* exprvaridxs, /**< maps variable indices in expression tree to indices in nlp, or NULL if no nonquadratic part */
1611 const SCIP_EXPRTREE* exprtree /**< expression tree of nonquadratic part, or NULL if no nonquadratic part */
1619 if( nquadelems > 0 || oracle->objective->quadsize > 0 || exprtree != NULL || oracle->objective->exprtree != NULL )
1626 nlin, lininds, linvals, nquadelems, quadelems, exprvaridxs, exprtree, constant, constant, NULL) );
1700 assert(EPSEQ(oracle->conss[indices[i]]->lhs, oracle->conss[indices[i]]->rhs, SCIP_DEFAULT_EPSILON));
1732 assert(oracle->nconss == 0); /* we could relax this by checking that all constraints are constant */
1733 assert(oracle->objective->exprtree == NULL || SCIPexprtreeGetNVars(oracle->objective->exprtree) == 0);
1747 BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[c], strlen(oracle->varnames[c])+1); /*lint !e866*/
1766 BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[c], strlen(oracle->varnames[c])+1); /*lint !e866*/
1780 BMSfreeBlockMemoryArray(oracle->blkmem, &oracle->varnames[lastgood], strlen(oracle->varnames[lastgood])+1); /*lint !e866*/
1793 /* update indices in linear part, sort indices, and then clear elements that are marked as deleted */
1798 /* update indices in quadratic part, sort elements, and then clear elements that are marked as deleted */
1807 assert(SCIPexprtreeGetNVars(cons->exprtree) == 0 || cons->exprvaridxs[SCIPexprtreeGetNVars(cons->exprtree)-1] == -1);
1808 BMSfreeBlockMemoryArrayNull(oracle->blkmem, &cons->exprvaridxs, SCIPexprtreeGetNVars(cons->exprtree));
1821 int* delstats /**< array with deletion status of rows in input (1 if row should be deleted, 0 if not);
1899 int considx, /**< index of constraint where linear coefficients should be changed, or -1 for objective */
1901 const int* varidxs, /**< array with indices of variables which coefficients should be changed */
1933 SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->lincoefs, newcoefs, nentries) );
1950 SCIPdebugMessage("replace coefficient of var %d at pos %d by %g\n", varidxs[i], pos, newcoefs[i]); /*lint !e613*/
1960 SCIPdebugMessage("add coefficient of var %d at pos %d, value %g\n", varidxs[i], cons->nlinidxs, newcoefs[i]); /*lint !e613*/
1996 int considx, /**< index of constraint where quadratic coefficients should be changed, or -1 for objective */
1998 const SCIP_QUADELEM* quadelems /**< new elements in quadratic matrix (replacing already existing ones or adding new ones) */
2024 SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->quadelems, quadelems, nquadelems) );
2041 /* if we already have an entry for quadelems[i], then just replace the coefficient, otherwise append new entry */
2042 if( SCIPquadelemSortedFind(cons->quadelems, quadelems[i].idx1, quadelems[i].idx2, cons->nquadelems, &pos) ) /*lint !e613*/
2044 SCIPdebugMessage("replace coefficient of var%d*var%d at pos %d by %g\n", quadelems[i].idx1, quadelems[i].idx2, pos, quadelems[i].coef); /*lint !e613*/
2054 SCIPdebugMessage("add coefficient of var%d*var%d at pos %d, value %g\n", quadelems[i].idx1, quadelems[i].idx2, cons->nquadelems, quadelems[i].coef); /*lint !e613*/
2083 oracle->vardegrees[cons->quadelems[i].idx1] = MAX(2, oracle->vardegrees[cons->quadelems[i].idx1]);
2084 oracle->vardegrees[cons->quadelems[i].idx2] = MAX(2, oracle->vardegrees[cons->quadelems[i].idx2]);
2094 int considx, /**< index of constraint where expression tree should be changed, or -1 for objective */
2117 BMSfreeBlockMemoryArray(oracle->blkmem, &cons->exprvaridxs, SCIPexprtreeGetNVars(cons->exprtree));
2131 SCIP_ALLOC( BMSduplicateBlockMemoryArray(oracle->blkmem, &cons->exprvaridxs, exprvaridxs, SCIPexprtreeGetNVars(cons->exprtree)) );
2134 * could get more accurate degree via getMaxDegree function in exprtree, but no solver would use this information so far
2151 int considx, /**< index of constraint where parameter should be changed in expression tree, or -1 for objective */
2167 SCIPexprtreeSetParamVal(considx >= 0 ? oracle->conss[considx]->exprtree : oracle->objective->exprtree, paramidx, paramval);
2240 * The degree of a variable is the degree of the summand where it appears in, and is infinity for nonpolynomial terms.
2257 * The degree of a variable is the degree of the summand where it appears in, and is infinity for nonpolynomial terms.
2338 /** Gives maximum degree over all constraints and the objective (or over all variables, resp.).
2434 SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2443 SCIP_CALL_QUIET( evalFunctionGradient(oracle, oracle->objective, x, isnewx, objval, objgrad) );
2456 SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2467 SCIP_CALL_QUIET( evalFunctionGradient(oracle, oracle->conss[considx], x, isnewx, conval, congrad) );
2474 * Note that internal data is returned in *offset and *col, thus the user does not need to allocate memory there.
2475 * Adding or deleting constraints destroys the sparsity structure and make another call to this function necessary.
2479 const int** offset, /**< pointer to store pointer that stores the offsets to each rows sparsity pattern in col, can be NULL */
2480 const int** col /**< pointer to store pointer that stores the indices of variables that appear in each row, offset[nconss] gives length of col, can be NULL */
2504 SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->jacoffsets, oracle->nconss + 1) );
2532 /* for a linear constraint, we can just copy the linear indices from the constraint into the sparsity pattern */
2535 SCIP_CALL( ensureIntArraySize(oracle->blkmem, &oracle->jaccols, &maxnnz, nnz + cons->nlinidxs) );
2543 /* for a constraint with exprtree only, we can just copy the exprvaridxs from the constraint into the sparsity pattern */
2561 * @todo this could be done faster for very sparse constraint by assembling all appearing variables, sorting, and removing duplicates
2613 * The values in the Jacobi matrix are returned in the same order as specified by the offset and col arrays obtained by SCIPnlpiOracleGetJacobianSparsity.
2614 * The user need to call SCIPnlpiOracleGetJacobianSparsity at least ones before using this function.
2619 SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2656 /* for a linear constraint, we can just copy the linear coefs from the constraint into the jacobian */
2669 /* for a constraint with exprtree only, we can just copy gradient of the exprtree from the constraint into jacobian */
2692 SCIPdebug( if( isnewx ) {printf("\nx ="); for( l = 0; l < nvars; ++l) printf(" %g", xx[l]); /*lint !e613*/ printf("\n");} )
2694 SCIP_CALL( SCIPexprintGrad(oracle->exprinterpreter, cons->exprtree, xx, isnewx, &nlval, grad) ); /*lint !e644*/
2701 retcode = SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
2714 retcode = SCIP_INVALIDDATA; /* indicate that the function could not be evaluated at given point */
2735 retcode = SCIPnlpiOracleEvalConstraintGradient(oracle, i, x, isnewx, (convals ? &convals[i] : &nlval), grad);
2751 * Note that internal data is returned in *offset and *col, thus the user must not allocate memory there.
2752 * Adding or deleting variables, objective, or constraints may destroy the sparsity structure and make another call to this function necessary.
2757 const int** offset, /**< pointer to store pointer that stores the offsets to each rows sparsity pattern in col, can be NULL */
2758 const int** col /**< pointer to store pointer that stores the indices of variables that appear in each row, offset[nconss] gives length of col, can be NULL */
2783 SCIP_ALLOC( BMSallocBlockMemoryArray(oracle->blkmem, &oracle->heslagoffsets, oracle->nvars + 1) );
2795 SCIP_CALL( hessLagSparsitySetNzFlagForQuad(oracle, colnz, collen, colnnz, &nnz, oracle->objective->nquadelems, oracle->objective->quadelems) );
2800 SCIP_CALL( hessLagSparsitySetNzFlagForExprtree(oracle, colnz, collen, colnnz, &nnz, oracle->objective->exprvaridxs, oracle->objective->exprtree, oracle->nvars) );
2807 SCIP_CALL( hessLagSparsitySetNzFlagForQuad(oracle, colnz, collen, colnnz, &nnz, oracle->conss[i]->nquadelems, oracle->conss[i]->quadelems) );
2812 SCIP_CALL( hessLagSparsitySetNzFlagForExprtree(oracle, colnz, collen, colnnz, &nnz, oracle->conss[i]->exprvaridxs, oracle->conss[i]->exprtree, oracle->nvars) );
2848 * The values in the Hessian matrix are returned in the same order as specified by the offset and col arrays obtained by SCIPnlpiOracleGetHessianLagSparsity.
2849 * The user must call SCIPnlpiOracleGetHessianLagSparsity at least ones before using this function.
2855 SCIP_Bool isnewx, /**< has the point x changed since the last call to some evaluation function? */
2878 SCIP_CALL( hessLagAddQuad(objfactor, oracle->objective->nquadelems, oracle->objective->quadelems, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2879 SCIP_CALL_QUIET( hessLagAddExprtree(oracle, objfactor, x, isnewx, oracle->objective->exprvaridxs, oracle->objective->exprtree, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2886 SCIP_CALL( hessLagAddQuad(lambda[i], oracle->conss[i]->nquadelems, oracle->conss[i]->quadelems, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2887 SCIP_CALL_QUIET( hessLagAddExprtree(oracle, lambda[i], x, isnewx, oracle->conss[i]->exprvaridxs, oracle->conss[i]->exprtree, oracle->heslagoffsets, oracle->heslagcols, hessian) );
2911 SCIPmessageFPrintInfo(messagehdlr, file, "NLPI Oracle %s: %d variables and %d constraints\n", oracle->name ? oracle->name : "", oracle->nvars, oracle->nconss);
2918 SCIPmessageFPrintInfo(messagehdlr, file, ": [%8g, %8g]", oracle->varlbs[i], oracle->varubs[i]);
2959 * If there are variable (equation, resp.) names with more than 9 characters, then variable (equation, resp.) names are prefixed with an unique identifier.
2971 int nllevel; /* level of nonlinearity of problem: linear = 0, quadratic, smooth nonlinear, nonsmooth */
2989 if( oracle->varnames != NULL && oracle->varnames[i] != NULL && strlen(oracle->varnames[i]) > 9 )
3005 SCIPmessageFPrintInfo(messagehdlr, file, "* NLPI Oracle Problem %s\n", oracle->name ? oracle->name : "");
3009 printName(namebuf, oracle->varnames != NULL ? oracle->varnames[i] : NULL, i, 'x', NULL, havelongvarnames);
3052 if( oracle->conss[i]->lhs > -oracle->infinity && oracle->conss[i]->rhs < oracle->infinity && oracle->conss[i]->lhs != oracle->conss[i]->rhs )
3064 SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->objective, havelongvarnames, havelongequnames) );
3077 SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->conss[i], havelongvarnames, havelongequnames) );
3097 SCIP_CALL( printFunction(oracle, messagehdlr, file, oracle->conss[i], havelongvarnames, havelongequnames) );
3106 if( nllevel <= 2 && oracle->conss[i]->exprtree != NULL && exprIsNonSmooth(SCIPexprtreeGetRoot(oracle->conss[i]->exprtree)) )
3115 SCIPmessageFPrintInfo(messagehdlr, file, "Solve %s minimizing NLPIORACLEOBJVAR using %s;\n", problemname, nllevelname[nllevel]);
|