diff --git a/CHANGELOG b/CHANGELOG index 8ab7a2cb21..58a0b2386b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -162,6 +162,7 @@ Interface changes - added SCIPsortDownIntIntIntReal() - SCIPconshdlrSetNeedsCons() to set whether constraint handler callbacks should also be called if there are no constraints - SCIPpropSetTimingmask() to set timing mask of a propagator +- added C++ interface for expression handlers: src/objscip/objexprhdlr.h ### Changes in preprocessor macros diff --git a/Makefile b/Makefile index cfc437f1dd..db9340b91a 100644 --- a/Makefile +++ b/Makefile @@ -1130,6 +1130,7 @@ OBJSCIPLIBOBJ = objscip/objbenders.o \ objscip/objconshdlr.o \ objscip/objdialog.o \ objscip/objdisp.o \ + objscip/objexprhdlr.o \ objscip/objeventhdlr.o \ objscip/objheur.o \ objscip/objmessagehdlr.o \ diff --git a/doc/xternal.c b/doc/xternal.c index d6fd4f9ebe..b6bde2bb5f 100644 --- a/doc/xternal.c +++ b/doc/xternal.c @@ -4244,10 +4244,16 @@ * * For a complete implementation of an expression handler, take the one for exponential expressions (src/scip/expr_exp.c) as an example. * + * It is very easy to transfer the C explanation to C++; whenever a function should be implemented using the + * SCIP_DECL_EXPRHDLR... notion, reimplement the corresponding virtual member function of the abstract scip::ObjExprhdlr + * base class. + * * @section EXPRHDLR_PROPERTIES Properties of an Expression Handler * * At the top of the new file `expr_myfunc.c`, you can find the expression handler properties. * These are given as compiler defines. + * In the C++ wrapper class, you have to provide the expression handler properties by calling the constructor + * of the abstract base class scip::ObjExprhdlr from within your constructor. * The properties you have to set have the following meaning: * * \par EXPRHDLR_NAME: the name of the expression handler. @@ -4330,6 +4336,8 @@ * an operational algorithm. * They are passed to SCIP when the expression handler is created and included in SCIP via SCIPincludeExprhdlr(), * see @ref EXPRHDLR_INTERFACE. + * In the C++ wrapper class scip::ObjExprhdlr, the fundamental callback methods are virtual abstract member functions. + * You have to implement them in order to be able to construct an object of your expression handler class. * * Expression handlers have one fundamental callback, @ref EXPREVAL, that needs to be implemented. * However, expression handlers with stateful expressions (expressions that have data) need to implement also the diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a572b1a059..782dc22516 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -427,6 +427,7 @@ set(objscipsources objscip/objdialog.cpp objscip/objdisp.cpp objscip/objeventhdlr.cpp + objscip/objexprhdlr.cpp objscip/objheur.cpp objscip/objiisfinder.cpp objscip/objmessagehdlr.cpp @@ -494,6 +495,7 @@ set(objscipheaders objscip/objdialog.h objscip/objdisp.h objscip/objeventhdlr.h + objscip/objexprhdlr.h objscip/objheur.h objscip/objiisfinder.h objscip/objmessagehdlr.h diff --git a/src/objscip/objexprhdlr.cpp b/src/objscip/objexprhdlr.cpp new file mode 100644 index 0000000000..0b56930ed2 --- /dev/null +++ b/src/objscip/objexprhdlr.cpp @@ -0,0 +1,516 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* This file is part of the program and library */ +/* SCIP --- Solving Constraint Integer Programs */ +/* */ +/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* */ +/* You should have received a copy of the Apache-2.0 license */ +/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/**@file objexprhdlr.cpp + * @brief C++ wrapper for expression handlers + * @author Kevin Kofler + */ + +/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ + +#include + +#include "objexprhdlr.h" + + + + +/* + * Data structures + */ + +/** expression handler data */ +struct SCIP_ExprhdlrData +{ + scip::ObjExprhdlr* objexprhdlr; /**< expression handler object */ + SCIP_Bool deleteobject; /**< should the expression handler object be deleted when exprhdlr is freed? */ +}; + + + + +/* + * Callback methods of expression handler + */ + +extern "C" +{ + +/** copy method for expression handler plugins (called when SCIP copies plugins) */ +static +SCIP_DECL_EXPRCOPYHDLR(exprCopyhdlrObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLRDATA* exprhdlrdata; + + assert(scip != NULL); + + exprhdlrdata = SCIPexprhdlrGetData(sourceexprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + assert(exprhdlrdata->objexprhdlr->scip_ != scip); + + if( exprhdlrdata->objexprhdlr->iscloneable() ) + { + scip::ObjExprhdlr* newobjexprhdlr; + newobjexprhdlr = dynamic_cast (exprhdlrdata->objexprhdlr->clone(scip)); + + /* call include method of expression handler object */ + SCIP_CALL( SCIPincludeObjExprhdlr(scip, newobjexprhdlr, TRUE) ); + } + + return SCIP_OKAY; +} + +/** destructor of expression handler to free user data (called when SCIP is exiting) */ +static +SCIP_DECL_EXPRFREEHDLR(exprFreehdlrObj) +{ /*lint --e{715}*/ + assert(exprhdlrdata != NULL); + assert(*exprhdlrdata != NULL); + assert((*exprhdlrdata)->objexprhdlr != NULL); + assert((*exprhdlrdata)->objexprhdlr->scip_ == scip); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( (*exprhdlrdata)->objexprhdlr->scip_freehdlr(scip, exprhdlr, exprhdlrdata) ); + + /* free exprhdlr object */ + if( (*exprhdlrdata)->deleteobject ) + delete (*exprhdlrdata)->objexprhdlr; + + /* free exprhdlr data */ + delete (*exprhdlrdata); + *exprhdlrdata = NULL; + + return SCIP_OKAY; +} + + +/** point evaluation callback of expression handler */ +static +SCIP_DECL_EXPREVAL(exprEvalObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_eval(scip, expr, val, sol) ); + + return SCIP_OKAY; +} + + +/** data copy callback of expression handler */ +static +SCIP_DECL_EXPRCOPYDATA(exprCopydataObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(targetexprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_copydata(targetscip, targetexprhdlr, targetexprdata, sourcescip, sourceexpr) ); + + return SCIP_OKAY; +} + + +/** data free callback of expression handler */ +static +SCIP_DECL_EXPRFREEDATA(exprFreedataObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_freedata(scip, expr) ); + + return SCIP_OKAY; +} + + +/** simplify callback of expression handler */ +static +SCIP_DECL_EXPRSIMPLIFY(exprSimplifyObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_simplify(scip, expr, simplifiedexpr, ownercreate, ownercreatedata) ); + + return SCIP_OKAY; +} + + +/** compare callback of expression handler */ +static +SCIP_DECL_EXPRCOMPARE(exprCompareObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr1); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + return exprhdlrdata->objexprhdlr->scip_compare(scip, expr1, expr2); +} + + +/** print callback of expression handler */ +static +SCIP_DECL_EXPRPRINT(exprPrintObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_print(scip, expr, stage, currentchild, parentprecedence, file) ); + + return SCIP_OKAY; +} + + +/** parse callback of expression handler */ +static +SCIP_DECL_EXPRPARSE(exprParseObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_parse(scip, exprhdlr, string, endstring, + expr, success, ownercreate, ownercreatedata) ); + + return SCIP_OKAY; +} + + +/** backward derivative evaluation callback of expression handler */ +static +SCIP_DECL_EXPRBWDIFF(exprBwdiffObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_bwdiff(scip, expr, childidx, val) ); + + return SCIP_OKAY; +} + + +/** forward derivative evaluation callback of expression handler */ +static +SCIP_DECL_EXPRFWDIFF(exprFwdiffObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_fwdiff(scip, expr, dot, direction) ); + + return SCIP_OKAY; +} + + +/** backward over forward derivative evaluation callback of expression handler */ +static +SCIP_DECL_EXPRBWFWDIFF(exprBwfwdiffObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_bwfwdiff(scip, expr, childidx, bardot, direction) ); + + return SCIP_OKAY; +} + + +/** interval evaluation callback of expression handler */ +static +SCIP_DECL_EXPRINTEVAL(exprIntevalObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_inteval(scip, expr, interval, intevalvar, intevalvardata) ); + + return SCIP_OKAY; +} + + +/** estimation callback of expression handler */ +static +SCIP_DECL_EXPRESTIMATE(exprEstimateObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_estimate(scip, expr, localbounds, globalbounds, + refpoint, overestimate, targetvalue, coefs, constant, islocal, success, branchcand) ); + + return SCIP_OKAY; +} + + +/** initial estimators callback of expression handler */ +static +SCIP_DECL_EXPRINITESTIMATES(exprInitestimatesObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_initestimates(scip, expr, bounds, overestimate, + coefs, constant, nreturned) ); + + return SCIP_OKAY; +} + + +/** reverse propagation callback of expression handler */ +static +SCIP_DECL_EXPRREVERSEPROP(exprReversepropObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_reverseprop(scip, expr, bounds, childrenbounds, infeasible) ); + + return SCIP_OKAY; +} + + +/** hash callback of expression handler */ +static +SCIP_DECL_EXPRHASH(exprHashObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_hash(scip, expr, hashkey, childrenhashes) ); + + return SCIP_OKAY; +} + + +/** curvature callback of expression handler */ +static +SCIP_DECL_EXPRCURVATURE(exprCurvatureObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_curvature(scip, expr, exprcurvature, success, childcurv) ); + + return SCIP_OKAY; +} + + +/** monotonicity callback of expression handler */ +static +SCIP_DECL_EXPRMONOTONICITY(exprMonotonicityObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_monotonicity(scip, expr, childidx, result) ); + + return SCIP_OKAY; +} + + +/** integrality callback of expression handler */ +static +SCIP_DECL_EXPRINTEGRALITY(exprIntegralityObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_integrality(scip, expr, integrality) ); + + return SCIP_OKAY; +} + + +/** symmetry information callback of expression handler */ +static +SCIP_DECL_EXPRGETSYMDATA(exprGetsymdataObj) +{ /*lint --e{715}*/ + SCIP_EXPRHDLR* exprhdlr = SCIPexprGetHdlr(expr); + SCIP_EXPRHDLRDATA* exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + assert(exprhdlrdata->objexprhdlr != NULL); + + /* call virtual method of exprhdlr object */ + SCIP_CALL( exprhdlrdata->objexprhdlr->scip_getsymdata(scip, expr, symdata) ); + + return SCIP_OKAY; +} +} + + +/* + * expression handler specific interface methods + */ + +/** creates the expression handler for the given expression handler object and includes it in SCIP */ +SCIP_RETCODE SCIPincludeObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + scip::ObjExprhdlr* objexprhdlr, /**< expression handler object */ + SCIP_Bool deleteobject, /**< should the expression handler object be deleted when exprhdlr is freed? */ + SCIP_EXPRHDLR** cexprhdlr /**< buffer to store C plugin that corresponds to expression handler object, or 0 if not required */ + ) +{ + SCIP_EXPRHDLR* exprhdlr; + SCIP_EXPRHDLRDATA* exprhdlrdata; + + assert(scip != NULL); + assert(objexprhdlr != NULL); + assert(objexprhdlr->scip_ == scip); + + /* create obj expression handler data */ + exprhdlrdata = new SCIP_EXPRHDLRDATA; + exprhdlrdata->objexprhdlr = objexprhdlr; + exprhdlrdata->deleteobject = deleteobject; + + /* include expression handler */ + SCIP_CALL( SCIPincludeExprhdlr(scip, &exprhdlr, objexprhdlr->scip_name_, objexprhdlr->scip_desc_, + objexprhdlr->scip_precedence_, exprEvalObj, exprhdlrdata) ); /*lint !e429*/ + + SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, exprCopyhdlrObj, exprFreehdlrObj); + if( objexprhdlr->scip_has_copydata_ || objexprhdlr->scip_has_freedata_ ) + SCIPexprhdlrSetCopyFreeData(exprhdlr, + objexprhdlr->scip_has_copydata_ ? exprCopydataObj : NULL, + objexprhdlr->scip_has_freedata_ ? exprFreedataObj : NULL); + if( objexprhdlr->scip_has_simplify_ ) + SCIPexprhdlrSetSimplify(exprhdlr, exprSimplifyObj); + if( objexprhdlr->scip_has_compare_ ) + SCIPexprhdlrSetCompare(exprhdlr, exprCompareObj); + if( objexprhdlr->scip_has_print_ ) + SCIPexprhdlrSetPrint(exprhdlr, exprPrintObj); + if( objexprhdlr->scip_has_parse_ ) + SCIPexprhdlrSetParse(exprhdlr, exprParseObj); + if( objexprhdlr->scip_has_bwdiff_ || objexprhdlr->scip_has_fwdiff_ || objexprhdlr->scip_has_bwfwdiff_ ) + SCIPexprhdlrSetDiff(exprhdlr, + objexprhdlr->scip_has_bwdiff_ ? exprBwdiffObj : NULL, + objexprhdlr->scip_has_fwdiff_ ? exprFwdiffObj : NULL, + objexprhdlr->scip_has_bwfwdiff_ ? exprBwfwdiffObj : NULL); + if( objexprhdlr->scip_has_inteval_ ) + SCIPexprhdlrSetIntEval(exprhdlr, exprIntevalObj); + if( objexprhdlr->scip_has_estimate_ || objexprhdlr->scip_has_initestimates_ ) + SCIPexprhdlrSetEstimate(exprhdlr, + objexprhdlr->scip_has_initestimates_ ? exprInitestimatesObj : NULL, + objexprhdlr->scip_has_estimate_ ? exprEstimateObj : NULL); + if( objexprhdlr->scip_has_reverseprop_ ) + SCIPexprhdlrSetReverseProp(exprhdlr, exprReversepropObj); + if( objexprhdlr->scip_has_hash_ ) + SCIPexprhdlrSetHash(exprhdlr, exprHashObj); + if( objexprhdlr->scip_has_curvature_ ) + SCIPexprhdlrSetCurvature(exprhdlr, exprCurvatureObj); + if( objexprhdlr->scip_has_monotonicity_ ) + SCIPexprhdlrSetMonotonicity(exprhdlr, exprMonotonicityObj); + if( objexprhdlr->scip_has_integrality_ ) + SCIPexprhdlrSetIntegrality(exprhdlr, exprIntegralityObj); + if( objexprhdlr->scip_has_getsymdata_ ) + SCIPexprhdlrSetGetSymdata(exprhdlr, exprGetsymdataObj); + + if( cexprhdlr != NULL ) + *cexprhdlr = exprhdlr; + + return SCIP_OKAY; /*lint !e429*/ +} + +/** returns the exprhdlr object of the given name, or 0 if not existing */ +scip::ObjExprhdlr* SCIPfindObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + const char* name /**< name of expression handler */ + ) +{ + SCIP_EXPRHDLR* exprhdlr; + SCIP_EXPRHDLRDATA* exprhdlrdata; + + exprhdlr = SCIPfindExprhdlr(scip, name); + if( exprhdlr == NULL ) + return 0; + + exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + + return exprhdlrdata->objexprhdlr; +} + +/** returns the exprhdlr object for the given expression handler */ +scip::ObjExprhdlr* SCIPgetObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + SCIP_EXPRHDLR* exprhdlr /**< expression handler */ + ) +{ + SCIP_EXPRHDLRDATA* exprhdlrdata; + + assert(scip != NULL); + exprhdlrdata = SCIPexprhdlrGetData(exprhdlr); + assert(exprhdlrdata != NULL); + + return exprhdlrdata->objexprhdlr; +} diff --git a/src/objscip/objexprhdlr.h b/src/objscip/objexprhdlr.h new file mode 100644 index 0000000000..8614d9d356 --- /dev/null +++ b/src/objscip/objexprhdlr.h @@ -0,0 +1,517 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* */ +/* This file is part of the program and library */ +/* SCIP --- Solving Constraint Integer Programs */ +/* */ +/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* */ +/* You should have received a copy of the Apache-2.0 license */ +/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */ +/* */ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/**@file objexprhdlr.h + * @brief C++ wrapper for expression handlers + * @author Kevin Kofler + */ + +/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ + +#ifndef __SCIP_OBJEXPRHDLR_H__ +#define __SCIP_OBJEXPRHDLR_H__ + +#include +#include + +#include "scip/scip.h" +#include "objscip/objcloneable.h" + +namespace scip +{ + +/** @brief C++ wrapper for expression handlers + * + * This class defines the interface for expression handlers implemented in C++. Note that there is a pure virtual + * function (which has to be implemented): the function scip_eval(). + * + * - \ref EXPRHDLR "Instructions for implementing an expression handler" + * - \ref EXPRHDLRS "List of available expression handlers" + * - \ref type_expr.h "Corresponding C interface" + */ +class ObjExprhdlr : public ObjCloneable +{ +public: + /*lint --e{1540}*/ + + /** SCIP data structure */ + SCIP* scip_; + + /** name of the expression handler */ + char* scip_name_; + + /** description of the expression handler */ + char* scip_desc_; + + /** precedence of expression operation relative to other expression (used for printing) */ + const unsigned int scip_precedence_; + + /** whether scip_copydata is implemented */ + const SCIP_Bool scip_has_copydata_; + + /** whether scip_freedata is implemented */ + const SCIP_Bool scip_has_freedata_; + + /** whether scip_simplify is implemented */ + const SCIP_Bool scip_has_simplify_; + + /** whether scip_compare is implemented */ + const SCIP_Bool scip_has_compare_; + + /** whether scip_print is implemented */ + const SCIP_Bool scip_has_print_; + + /** whether scip_parse is implemented */ + const SCIP_Bool scip_has_parse_; + + /** whether scip_bwdiff is implemented */ + const SCIP_Bool scip_has_bwdiff_; + + /** whether scip_fwdiff is implemented */ + const SCIP_Bool scip_has_fwdiff_; + + /** whether scip_bwfwdiff is implemented */ + const SCIP_Bool scip_has_bwfwdiff_; + + /** whether scip_inteval is implemented */ + const SCIP_Bool scip_has_inteval_; + + /** whether scip_estimate is implemented */ + const SCIP_Bool scip_has_estimate_; + + /** whether scip_initestimates is implemented */ + const SCIP_Bool scip_has_initestimates_; + + /** whether scip_reverseprop is implemented */ + const SCIP_Bool scip_has_reverseprop_; + + /** whether scip_hash is implemented */ + const SCIP_Bool scip_has_hash_; + + /** whether scip_curvature is implemented */ + const SCIP_Bool scip_has_curvature_; + + /** whether scip_monotonicity is implemented */ + const SCIP_Bool scip_has_monotonicity_; + + /** whether scip_integrality is implemented */ + const SCIP_Bool scip_has_integrality_; + + /** whether scip_getsymdata is implemented */ + const SCIP_Bool scip_has_getsymdata_; + + /** default constructor */ + ObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + const char* name, /**< name of expression handler */ + const char* desc, /**< description of expression handler */ + unsigned int precedence, /**< precedence of expression operation */ + SCIP_Bool has_copydata, /**< whether scip_copydata is implemented */ + SCIP_Bool has_freedata, /**< whether scip_freedata is implemented */ + SCIP_Bool has_simplify, /**< whether scip_simplify is implemented */ + SCIP_Bool has_compare, /**< whether scip_compare is implemented */ + SCIP_Bool has_print, /**< whether scip_print is implemented */ + SCIP_Bool has_parse, /**< whether scip_parse is implemented */ + SCIP_Bool has_bwdiff, /**< whether scip_bwdiff is implemented */ + SCIP_Bool has_fwdiff, /**< whether scip_fwdiff is implemented */ + SCIP_Bool has_bwfwdiff, /**< whether scip_bwfwdiff is implemented */ + SCIP_Bool has_inteval, /**< whether scip_inteval is implemented */ + SCIP_Bool has_estimate, /**< whether scip_estimate is implemented */ + SCIP_Bool has_initestimates, /**< whether scip_initestimates is implemented */ + SCIP_Bool has_reverseprop, /**< whether scip_reverseprop is implemented */ + SCIP_Bool has_hash, /**< whether scip_hash is implemented */ + SCIP_Bool has_curvature, /**< whether scip_curvature is implemented */ + SCIP_Bool has_monotonicity, /**< whether scip_monotonicity is implemented */ + SCIP_Bool has_integrality, /**< whether scip_integrality is implemented */ + SCIP_Bool has_getsymdata /**< whether scip_getsymdata is implemented */ + ) + : scip_(scip), + scip_name_(0), + scip_desc_(0), + scip_precedence_(precedence), + scip_has_copydata_(has_copydata), + scip_has_freedata_(has_freedata), + scip_has_simplify_(has_simplify), + scip_has_compare_(has_compare), + scip_has_print_(has_print), + scip_has_parse_(has_parse), + scip_has_bwdiff_(has_bwdiff), + scip_has_fwdiff_(has_fwdiff), + scip_has_bwfwdiff_(has_bwfwdiff), + scip_has_inteval_(has_inteval), + scip_has_estimate_(has_estimate), + scip_has_initestimates_(has_initestimates), + scip_has_reverseprop_(has_reverseprop), + scip_has_hash_(has_hash), + scip_has_curvature_(has_curvature), + scip_has_monotonicity_(has_monotonicity), + scip_has_integrality_(has_integrality), + scip_has_getsymdata_(has_getsymdata) + { + /* the macro SCIPduplicateMemoryArray does not need the first argument: */ + SCIP_CALL_ABORT( SCIPduplicateMemoryArray(scip_, &scip_name_, name, std::strlen(name)+1) ); + SCIP_CALL_ABORT( SCIPduplicateMemoryArray(scip_, &scip_desc_, desc, std::strlen(desc)+1) ); + } + + /** copy constructor */ + ObjExprhdlr(const ObjExprhdlr& o) + : ObjExprhdlr(o.scip_, o.scip_name_, o.scip_desc_, o.scip_precedence_, + o.scip_has_copydata_, o.scip_has_freedata_, + o.scip_has_simplify_, o.scip_has_compare_, + o.scip_has_print_, o.scip_has_parse_, o.scip_has_bwdiff_, + o.scip_has_fwdiff_, o.scip_has_bwfwdiff_, + o.scip_has_inteval_, o.scip_has_estimate_, + o.scip_has_initestimates_, o.scip_has_reverseprop_, + o.scip_has_hash_, o.scip_has_curvature_, + o.scip_has_monotonicity_, o.scip_has_integrality_, + o.scip_has_getsymdata_) + { + } + + /** move constructor */ + ObjExprhdlr(ObjExprhdlr&& o) + : scip_(o.scip_), + scip_name_(0), + scip_desc_(0), + scip_precedence_(o.scip_precedence_), + scip_has_copydata_(o.scip_has_copydata_), + scip_has_freedata_(o.scip_has_freedata_), + scip_has_simplify_(o.scip_has_simplify_), + scip_has_compare_(o.scip_has_compare_), + scip_has_print_(o.scip_has_print_), + scip_has_parse_(o.scip_has_parse_), + scip_has_bwdiff_(o.scip_has_bwdiff_), + scip_has_fwdiff_(o.scip_has_fwdiff_), + scip_has_bwfwdiff_(o.scip_has_bwfwdiff_), + scip_has_inteval_(o.scip_has_inteval_), + scip_has_estimate_(o.scip_has_estimate_), + scip_has_initestimates_(o.scip_has_initestimates_), + scip_has_reverseprop_(o.scip_has_reverseprop_), + scip_has_hash_(o.scip_has_hash_), + scip_has_curvature_(o.scip_has_curvature_), + scip_has_monotonicity_(o.scip_has_monotonicity_), + scip_has_integrality_(o.scip_has_integrality_), + scip_has_getsymdata_(o.scip_has_getsymdata_) + { + std::swap(scip_name_, o.scip_name_); + std::swap(scip_desc_, o.scip_desc_); + } + + /** destructor */ + virtual ~ObjExprhdlr() + { + /* the macro SCIPfreeMemoryArray does not need the first argument: */ + /*lint --e{64}*/ + SCIPfreeMemoryArray(scip_, &scip_name_); + SCIPfreeMemoryArray(scip_, &scip_desc_); + } + + /** assignment of polymorphic classes causes slicing and is therefore disabled. */ + ObjExprhdlr& operator=(const ObjExprhdlr& o) = delete; + + /** assignment of polymorphic classes causes slicing and is therefore disabled. */ + ObjExprhdlr& operator=(ObjExprhdlr&& o) = delete; + + /** destructor of expression handler to free user data (called when SCIP is exiting) + * + * @see SCIP_DECL_EXPRFREEHDLR(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRFREEHDLR(scip_freehdlr) + { /*lint --e{715}*/ + return SCIP_OKAY; + } + + /** point evaluation callback of expression handler + * + * @see SCIP_DECL_EXPREVAL(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPREVAL(scip_eval) = 0; + + /** data copy callback of expression handler + * + * This method MUST be overridden if scip_has_copydata_ is TRUE. + * + * @see SCIP_DECL_EXPRCOPYDATA(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRCOPYDATA(scip_copydata) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_copydata_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** data free callback of expression handler + * + * This method MUST be overridden if scip_has_freedata_ is TRUE. + * + * @see SCIP_DECL_EXPRFREEDATA(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRFREEDATA(scip_freedata) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_freedata_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** simplify callback of expression handler + * + * This method MUST be overridden if scip_has_simplify_ is TRUE. + * + * @see SCIP_DECL_EXPRSIMPLIFY(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRSIMPLIFY(scip_simplify) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_simplify_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** compare callback of expression handler + * + * This method MUST be overridden if scip_has_compare_ is TRUE. + * + * @see SCIP_DECL_EXPRCOMPARE(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRCOMPARE(scip_compare) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_compare_ is TRUE. */ + return 0; + } + + /** print callback of expression handler + * + * This method MUST be overridden if scip_has_print_ is TRUE. + * + * @see SCIP_DECL_EXPRPRINT(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRPRINT(scip_print) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_print_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** parse callback of expression handler + * + * This method MUST be overridden if scip_has_parse_ is TRUE. + * + * @see SCIP_DECL_EXPRPARSE(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRPARSE(scip_parse) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_parse_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** backward derivative evaluation callback of expression handler + * + * This method MUST be overridden if scip_has_bwdiff_ is TRUE. + * + * @see SCIP_DECL_EXPRBWDIFF(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRBWDIFF(scip_bwdiff) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_bwdiff_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** forward derivative evaluation callback of expression handler + * + * This method MUST be overridden if scip_has_fwdiff_ is TRUE. + * + * @see SCIP_DECL_EXPRFWDIFF(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRFWDIFF(scip_fwdiff) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_fwdiff_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** backward over forward derivative evaluation callback of expression handler + * + * This method MUST be overridden if scip_has_bwfwdiff_ is TRUE. + * + * @see SCIP_DECL_EXPRBWFWDIFF(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRBWFWDIFF(scip_bwfwdiff) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_bwfwdiff_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** interval evaluation callback of expression handler + * + * This method MUST be overridden if scip_has_inteval_ is TRUE. + * + * @see SCIP_DECL_EXPRINTEVAL(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRINTEVAL(scip_inteval) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_inteval_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** estimation callback of expression handler + * + * This method MUST be overridden if scip_has_estimate_ is TRUE. + * + * @see SCIP_DECL_EXPRESTIMATE(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRESTIMATE(scip_estimate) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_estimate_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** initial estimators callback of expression handler + * + * This method MUST be overridden if scip_has_initestimates_ is TRUE. + * + * @see SCIP_DECL_EXPRINITESTIMATES(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRINITESTIMATES(scip_initestimates) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_initestimates_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** reverse propagation callback of expression handler + * + * This method MUST be overridden if scip_has_reverseprop_ is TRUE. + * + * @see SCIP_DECL_EXPRREVERSEPROP(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRREVERSEPROP(scip_reverseprop) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_reverseprop_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** hash callback of expression handler + * + * This method MUST be overridden if scip_has_hash_ is TRUE. + * + * @see SCIP_DECL_EXPRHASH(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRHASH(scip_hash) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_hash_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** curvature callback of expression handler + * + * This method MUST be overridden if scip_has_curvature_ is TRUE. + * + * @see SCIP_DECL_EXPRCURVATURE(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRCURVATURE(scip_curvature) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_curvature_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** monotonicity callback of expression handler + * + * This method MUST be overridden if scip_has_monotonicity_ is TRUE. + * + * @see SCIP_DECL_EXPRMONOTONICITY(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRMONOTONICITY(scip_monotonicity) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_monotonicity_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** integrality callback of expression handler + * + * This method MUST be overridden if scip_has_integrality_ is TRUE. + * + * @see SCIP_DECL_EXPRINTEGRALITY(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRINTEGRALITY(scip_integrality) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_integrality_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } + + /** symmetry information callback of expression handler + * + * This method MUST be overridden if scip_has_getsymdata_ is TRUE. + * + * @see SCIP_DECL_EXPRGETSYMDATA(x) in @ref type_expr.h + */ + virtual SCIP_DECL_EXPRGETSYMDATA(scip_getsymdata) + { /*lint --e{715}*/ + /* This method MUST be overridden if scip_has_getsymdata_ is TRUE. */ + return SCIP_NOTIMPLEMENTED; + } +}; + +} /* namespace scip */ + + + +/** creates the expression handler for the given expression handler object and includes it in SCIP + * + * The method should be called in one of the following ways: + * + * 1. The user is responsible of deleting the object: + * SCIP_CALL( SCIPcreate(&scip) ); + * ... + * SCIP_EXPRHDLR* cexprhdlr; + * MyExprhdlr* myexprhdlr = new MyExprhdlr(...); + * SCIP_CALL( SCIPincludeObjExprhdlr(scip, &myexprhdlr, FALSE, &cexprhdlr) ); + * ... + * SCIP_CALL( SCIPfree(&scip) ); + * delete myexprhdlr; // delete exprhdlr AFTER SCIPfree() ! + * + * 2. The object pointer is passed to SCIP and deleted by SCIP in the SCIPfree() call: + * SCIP_CALL( SCIPcreate(&scip) ); + * ... + * SCIP_CALL( SCIPincludeObjExprhdlr(scip, new MyExprhdlr(...), TRUE) ); + * ... + * SCIP_CALL( SCIPfree(&scip) ); // destructor of MyExprhdlr is called here + * + * Further, in case 1, the C plugin counterpart for myexprhdlr is stored in cexprhdlr. + */ +SCIP_EXPORT +SCIP_RETCODE SCIPincludeObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + scip::ObjExprhdlr* objexprhdlr, /**< expression handler object */ + SCIP_Bool deleteobject, /**< should the expression handler object be deleted when exprhdlr is freed? */ + SCIP_EXPRHDLR** cexprhdlr = 0 /**< buffer to store C plugin that corresponds to expression handler object, or 0 if not required */ + ); + +/** returns the exprhdlr object of the given name, or 0 if not existing */ +SCIP_EXPORT +scip::ObjExprhdlr* SCIPfindObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + const char* name /**< name of expression handler */ + ); + +/** returns the exprhdlr object for the given expression handler */ +SCIP_EXPORT +scip::ObjExprhdlr* SCIPgetObjExprhdlr( + SCIP* scip, /**< SCIP data structure */ + SCIP_EXPRHDLR* exprhdlr /**< expression handler */ + ); + +#endif diff --git a/src/objscip/objscip.h b/src/objscip/objscip.h index 2741e6fa22..20d39a92c9 100644 --- a/src/objscip/objscip.h +++ b/src/objscip/objscip.h @@ -41,6 +41,7 @@ #include "objscip/objdialog.h" #include "objscip/objdisp.h" #include "objscip/objeventhdlr.h" +#include "objscip/objexprhdlr.h" #include "objscip/objheur.h" #include "objscip/objiisfinder.h" #include "objscip/objmessagehdlr.h"