1 
2 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
3 
4 /*
5  *  Main authors:
6  *     Gleb Belov <gleb.belov@monash.edu>
7  */
8 
9 /* This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
12 
13 #pragma once
14 
15 #include <minizinc/plugin.hh>
16 #include <minizinc/solver_config.hh>
17 #include <minizinc/solver_instance_base.hh>
18 #include <minizinc/solvers/MIP/MIP_wrap.hh>
19 
20 #include <scip/scip.h>
21 #include <scip/scipdefplugins.h>
22 
23 #ifndef _WIN32
24 // NOLINTNEXTLINE(bugprone-reserved-identifier)
25 #define __stdcall
26 #endif
27 
28 // Workaround for SCIP replacing function calls with macros in release mode
29 #ifdef NDEBUG
30 #define SCIPinfinityPlugin(plugin, scip) SCIPinfinity(scip)
31 #else
32 #define SCIPinfinityPlugin(plugin, scip) plugin->SCIPinfinity(scip)
33 #endif
34 
35 class ScipPlugin : public MiniZinc::Plugin {
36 public:
37   ScipPlugin();
38   ScipPlugin(const std::string& dll);
39 
40   // NOLINTNEXTLINE(readability-identifier-naming)
41   int(__stdcall* SCIPmajorVersion)();
42   // NOLINTNEXTLINE(readability-identifier-naming)
43   int(__stdcall* SCIPminorVersion)();
44   // NOLINTNEXTLINE(readability-identifier-naming)
45   int(__stdcall* SCIPtechVersion)();
46   // NOLINTNEXTLINE(readability-identifier-naming)
47   int(__stdcall* SCIPsubversion)();
48   // NOLINTNEXTLINE(readability-identifier-naming)
49   void(__stdcall* SCIPprintError)(SCIP_RETCODE retcode);
50   // NOLINTNEXTLINE(readability-identifier-naming)
51   SCIP_RETCODE(__stdcall* SCIPcreate)(SCIP** scip);
52   // NOLINTNEXTLINE(readability-identifier-naming)
53   SCIP_RETCODE(__stdcall* SCIPincludeDefaultPlugins)(SCIP* scip);
54   // NOLINTNEXTLINE(readability-identifier-naming)
55   SCIP_RETCODE(__stdcall* SCIPcreateProbBasic)(SCIP* scip, const char* name);
56   // NOLINTNEXTLINE(readability-identifier-naming)
57   SCIP_RETCODE(__stdcall* SCIPfree)(SCIP** scip);
58   // NOLINTNEXTLINE(readability-identifier-naming)
59   SCIP_RETCODE(__stdcall* SCIPcreateVarBasic)
60   (SCIP* scip, SCIP_VAR** var, const char* name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj,
61    SCIP_VARTYPE vartype);
62   // NOLINTNEXTLINE(readability-identifier-naming)
63   SCIP_RETCODE(__stdcall* SCIPaddVar)(SCIP* scip, SCIP_VAR* var);
64   // NOLINTNEXTLINE(readability-identifier-naming)
65   SCIP_RETCODE(__stdcall* SCIPreleaseVar)(SCIP* scip, SCIP_VAR** var);
66   // NOLINTNEXTLINE(readability-identifier-naming)
67   SCIP_Real(__stdcall* SCIPinfinity)(SCIP* scip);
68   // NOLINTNEXTLINE(readability-identifier-naming)
69   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicLinear)
70   (SCIP* scip, SCIP_CONS** cons, const char* name, int nvars, SCIP_VAR** vars, SCIP_Real* vals,
71    SCIP_Real lhs, SCIP_Real rhs);
72   // NOLINTNEXTLINE(readability-identifier-naming)
73   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicQuadratic)
74   (SCIP* scip,           /**< SCIP data structure */
75    SCIP_CONS** cons,     /**< pointer to hold the created constraint */
76    const char* name,     /**< name of constraint */
77    int nlinvars,         /**< number of linear terms (n) */
78    SCIP_VAR** linvars,   /**< array with variables in linear part (x_i) */
79    SCIP_Real* lincoefs,  /**< array with coefficients of variables in linear part (b_i) */
80    int nquadterms,       /**< number of quadratic terms (m) */
81    SCIP_VAR** quadvars1, /**< array with first variables in quadratic terms (y_j) */
82    SCIP_VAR** quadvars2, /**< array with second variables in quadratic terms (z_j) */
83    SCIP_Real* quadcoefs, /**< array with coefficients of quadratic terms (a_j) */
84    SCIP_Real lhs,        /**< left hand side of quadratic equation (ell) */
85    SCIP_Real rhs         /**< right hand side of quadratic equation (u) */
86   );
87   // NOLINTNEXTLINE(readability-identifier-naming)
88   SCIP_RETCODE(__stdcall* SCIPaddCons)(SCIP* scip, SCIP_CONS* cons);
89   // NOLINTNEXTLINE(readability-identifier-naming)
90   SCIP_RETCODE(__stdcall* SCIPreleaseCons)(SCIP* scip, SCIP_CONS** cons);
91   // NOLINTNEXTLINE(readability-identifier-naming)
92   SCIP_RETCODE(__stdcall* SCIPchgVarLbGlobal)(SCIP* scip, SCIP_VAR* var, SCIP_Real newbound);
93   // NOLINTNEXTLINE(readability-identifier-naming)
94   SCIP_RETCODE(__stdcall* SCIPchgVarUbGlobal)(SCIP* scip, SCIP_VAR* var, SCIP_Real newbound);
95   // NOLINTNEXTLINE(readability-identifier-naming)
96   SCIP_RETCODE(__stdcall* SCIPgetNegatedVar)(SCIP* scip, SCIP_VAR* var, SCIP_VAR** negvar);
97   // NOLINTNEXTLINE(readability-identifier-naming)
98   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicIndicator)
99   (SCIP* scip, SCIP_CONS** cons, const char* name, SCIP_VAR* binvar, int nvars, SCIP_VAR** vars,
100    SCIP_Real* vals, SCIP_Real rhs);
101   // NOLINTNEXTLINE(readability-identifier-naming)
102   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicBounddisjunction)
103   (SCIP* scip, SCIP_CONS** cons, const char* name, int nvars, SCIP_VAR** vars,
104    SCIP_BOUNDTYPE* boundtypes, SCIP_Real* bounds);
105   // NOLINTNEXTLINE(readability-identifier-naming)
106   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicCumulative)
107   (SCIP* scip, SCIP_CONS** cons, const char* name, int nvars, SCIP_VAR** vars, int* durations,
108    int* demands, int capacity);
109 
110   // NOLINTNEXTLINE(readability-identifier-naming)
111   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicOrbisack)
112   (SCIP* scip, SCIP_CONS** cons, const char* name, SCIP_VAR** vars1, SCIP_VAR** vars2, int nrows,
113    SCIP_Bool ispporbisack, SCIP_Bool isparttype, SCIP_Bool ismodelcons);
114 
115   // NOLINTNEXTLINE(readability-identifier-naming)
116   SCIP_RETCODE(__stdcall* SCIPcreateConsBasicOrbitope)
117   (SCIP* scip,                     /**< SCIP data structure */
118    SCIP_CONS** cons,               /**< pointer to hold the created constraint */
119    const char* name,               /**< name of constraint */
120    SCIP_VAR*** vars,               /**< matrix of variables on which the symmetry acts */
121    SCIP_ORBITOPETYPE orbitopetype, /**< type of orbitope constraint */
122    int nspcons,                    /**< number of set partitioning/packing constraints  <=> p */
123    int nblocks,                    /**< number of symmetric variable blocks             <=> q */
124    SCIP_Bool resolveprop,          /**< should propagation be resolved? */
125    SCIP_Bool ismodelcons           /**< whether the orbitope is a model constraint */
126   );
127 
128   // NOLINTNEXTLINE(readability-identifier-naming)
129   SCIP_Longint(__stdcall* SCIPgetNSolsFound)(SCIP* scip);
130   // NOLINTNEXTLINE(readability-identifier-naming)
131   int(__stdcall* SCIPgetNSols)(SCIP* scip);
132   // NOLINTNEXTLINE(readability-identifier-naming)
133   SCIP_RETCODE(__stdcall* SCIPsetIntParam)(SCIP* scip, const char* name, int value);
134   // NOLINTNEXTLINE(readability-identifier-naming)
135   SCIP_RETCODE(__stdcall* SCIPsetRealParam)(SCIP* scip, const char* name, SCIP_Real value);
136   // NOLINTNEXTLINE(readability-identifier-naming)
137   SCIP_RETCODE(__stdcall* SCIPwriteOrigProblem)
138   (SCIP* scip, const char* filename, const char* extension, SCIP_Bool genericnames);
139   // NOLINTNEXTLINE(readability-identifier-naming)
140   void(__stdcall* SCIPsetMessagehdlrQuiet)(SCIP* scip, SCIP_Bool quiet);
141   // NOLINTNEXTLINE(readability-identifier-naming)
142   SCIP_RETCODE(__stdcall* SCIPmessagehdlrCreate)
143   (SCIP_MESSAGEHDLR** messagehdlr, SCIP_Bool bufferedoutput, const char* filename, SCIP_Bool quiet,
144    SCIP_DECL_MESSAGEWARNING((*messagewarning)), SCIP_DECL_MESSAGEDIALOG((*messagedialog)),
145    SCIP_DECL_MESSAGEINFO((*messageinfo)), SCIP_DECL_MESSAGEHDLRFREE((*messagehdlrfree)),
146    SCIP_MESSAGEHDLRDATA* messagehdlrdata);
147   // NOLINTNEXTLINE(readability-identifier-naming)
148   SCIP_RETCODE(__stdcall* SCIPsetMessagehdlr)(SCIP* scip, SCIP_MESSAGEHDLR* messagehdlr);
149   // NOLINTNEXTLINE(readability-identifier-naming)
150   SCIP_RETCODE(__stdcall* SCIPreadParams)(SCIP* scip, const char* filename);
151   // NOLINTNEXTLINE(readability-identifier-naming)
152   SCIP_RETCODE(__stdcall* SCIPwriteParams)
153   (SCIP* scip, const char* filename, SCIP_Bool comments, SCIP_Bool onlychanged);
154   // NOLINTNEXTLINE(readability-identifier-naming)
155   SCIP_RETCODE(__stdcall* SCIPsolve)(SCIP* scip);
156   // NOLINTNEXTLINE(readability-identifier-naming)
157   SCIP_STATUS(__stdcall* SCIPgetStatus)(SCIP* scip);
158   // NOLINTNEXTLINE(readability-identifier-naming)
159   SCIP_Real(__stdcall* SCIPgetPrimalbound)(SCIP* scip);
160   // NOLINTNEXTLINE(readability-identifier-naming)
161   SCIP_Real(__stdcall* SCIPgetDualbound)(SCIP* scip);
162   // NOLINTNEXTLINE(readability-identifier-naming)
163   SCIP_RETCODE(__stdcall* SCIPgetSolVals)
164   (SCIP* scip, SCIP_SOL* sol, int nvars, SCIP_VAR** vars, SCIP_Real* vals);
165   // NOLINTNEXTLINE(readability-identifier-naming)
166   SCIP_SOL*(__stdcall* SCIPgetBestSol)(SCIP* scip);
167   // NOLINTNEXTLINE(readability-identifier-naming)
168   SCIP_Longint(__stdcall* SCIPgetNTotalNodes)(SCIP* scip);
169   // NOLINTNEXTLINE(readability-identifier-naming)
170   SCIP_Longint(__stdcall* SCIPgetNNodes)(SCIP* scip);
171   // NOLINTNEXTLINE(readability-identifier-naming)
172   int(__stdcall* SCIPgetNNodesLeft)(SCIP* scip);
173   // NOLINTNEXTLINE(readability-identifier-naming)
174   SCIP_RETCODE(__stdcall* SCIPfreeTransform)(SCIP* scip);
175   // NOLINTNEXTLINE(readability-identifier-naming)
176   SCIP_RETCODE(__stdcall* SCIPsetObjsense)(SCIP* scip, SCIP_OBJSENSE objsense);
177   // NOLINTNEXTLINE(readability-identifier-naming)
178   const char*(__stdcall* SCIPeventhdlrGetName)(SCIP_EVENTHDLR* eventhdlr);
179   // NOLINTNEXTLINE(readability-identifier-naming)
180   SCIP_RETCODE(__stdcall* SCIPcatchEvent)
181   (SCIP* scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA* eventdata,
182    int* filterpos);
183   // NOLINTNEXTLINE(readability-identifier-naming)
184   SCIP_RETCODE(__stdcall* SCIPdropEvent)
185   (SCIP* scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR* eventhdlr, SCIP_EVENTDATA* eventdata,
186    int filterpos);
187   // NOLINTNEXTLINE(readability-identifier-naming)
188   SCIP_EVENTTYPE(__stdcall* SCIPeventGetType)(SCIP_EVENT* event);
189   // NOLINTNEXTLINE(readability-identifier-naming)
190   SCIP_Real(__stdcall* SCIPgetSolOrigObj)(SCIP* scip, SCIP_SOL* sol);
191   // NOLINTNEXTLINE(readability-identifier-naming)
192   SCIP_RETCODE(__stdcall* SCIPincludeEventhdlrBasic)
193   (SCIP* scip, SCIP_EVENTHDLR** eventhdlrptr, const char* name, const char* desc,
194    SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA* eventhdlrdata);
195   // NOLINTNEXTLINE(readability-identifier-naming)
196   SCIP_RETCODE(__stdcall* SCIPsetEventhdlrInit)
197   (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_DECL_EVENTINIT((*eventinit)));
198   // NOLINTNEXTLINE(readability-identifier-naming)
199   SCIP_RETCODE(__stdcall* SCIPsetEventhdlrExit)
200   (SCIP* scip, SCIP_EVENTHDLR* eventhdlr, SCIP_DECL_EVENTEXIT((*eventexit)));
201   // NOLINTNEXTLINE(readability-identifier-naming)
202   void(__stdcall* SCIPmessagePrintErrorHeader)(const char* sourcefile, int sourceline);
203   // NOLINTNEXTLINE(readability-identifier-naming)
204   void(__stdcall* SCIPmessagePrintError)(const char* formatstr, ...);
205   // NOLINTNEXTLINE(readability-identifier-naming)
206   int(__stdcall* SCIPgetNVars)(SCIP* scip);
207   // NOLINTNEXTLINE(readability-identifier-naming)
208   int(__stdcall* SCIPgetNConss)(SCIP* scip);
209   // NOLINTNEXTLINE(readability-identifier-naming)
210   SCIP_PARAM**(__stdcall* SCIPgetParams)(SCIP* scip);
211   // NOLINTNEXTLINE(readability-identifier-naming)
212   int(__stdcall* SCIPgetNParams)(SCIP* scip);
213   // NOLINTNEXTLINE(readability-identifier-naming)
214   const char*(__stdcall* SCIPparamGetName)(SCIP_PARAM* param);
215   // NOLINTNEXTLINE(readability-identifier-naming)
216   SCIP_PARAMTYPE(__stdcall* SCIPparamGetType)(SCIP_PARAM* param);
217   // NOLINTNEXTLINE(readability-identifier-naming)
218   const char*(__stdcall* SCIPparamGetDesc)(SCIP_PARAM* param);
219   // NOLINTNEXTLINE(readability-identifier-naming)
220   SCIP_Bool(__stdcall* SCIPparamGetBoolDefault)(SCIP_PARAM* param);
221   // NOLINTNEXTLINE(readability-identifier-naming)
222   char*(__stdcall* SCIPparamGetCharAllowedValues)(SCIP_PARAM* param);
223   // NOLINTNEXTLINE(readability-identifier-naming)
224   char(__stdcall* SCIPparamGetCharDefault)(SCIP_PARAM* param);
225   // NOLINTNEXTLINE(readability-identifier-naming)
226   int(__stdcall* SCIPparamGetIntDefault)(SCIP_PARAM* param);
227   // NOLINTNEXTLINE(readability-identifier-naming)
228   int(__stdcall* SCIPparamGetIntMin)(SCIP_PARAM* param);
229   // NOLINTNEXTLINE(readability-identifier-naming)
230   int(__stdcall* SCIPparamGetIntMax)(SCIP_PARAM* param);
231   // NOLINTNEXTLINE(readability-identifier-naming)
232   SCIP_Longint(__stdcall* SCIPparamGetLongintDefault)(SCIP_PARAM* param);
233   // NOLINTNEXTLINE(readability-identifier-naming)
234   SCIP_Longint(__stdcall* SCIPparamGetLongintMin)(SCIP_PARAM* param);
235   // NOLINTNEXTLINE(readability-identifier-naming)
236   SCIP_Longint(__stdcall* SCIPparamGetLongintMax)(SCIP_PARAM* param);
237   // NOLINTNEXTLINE(readability-identifier-naming)
238   SCIP_Real(__stdcall* SCIPparamGetRealDefault)(SCIP_PARAM* param);
239   // NOLINTNEXTLINE(readability-identifier-naming)
240   SCIP_Real(__stdcall* SCIPparamGetRealMin)(SCIP_PARAM* param);
241   // NOLINTNEXTLINE(readability-identifier-naming)
242   SCIP_Real(__stdcall* SCIPparamGetRealMax)(SCIP_PARAM* param);
243   // NOLINTNEXTLINE(readability-identifier-naming)
244   char*(__stdcall* SCIPparamGetStringDefault)(SCIP_PARAM* param);
245   // NOLINTNEXTLINE(readability-identifier-naming)
246   SCIP_PARAM*(__stdcall* SCIPgetParam)(SCIP* scip, const char* name);
247   // NOLINTNEXTLINE(readability-identifier-naming)
248   SCIP_RETCODE(__stdcall* SCIPchgBoolParam)(SCIP* scip, SCIP_PARAM* param, SCIP_Bool value);
249   // NOLINTNEXTLINE(readability-identifier-naming)
250   SCIP_RETCODE(__stdcall* SCIPchgIntParam)(SCIP* scip, SCIP_PARAM* param, int value);
251   // NOLINTNEXTLINE(readability-identifier-naming)
252   SCIP_RETCODE(__stdcall* SCIPchgLongintParam)(SCIP* scip, SCIP_PARAM* param, SCIP_Longint value);
253   // NOLINTNEXTLINE(readability-identifier-naming)
254   SCIP_RETCODE(__stdcall* SCIPchgRealParam)(SCIP* scip, SCIP_PARAM* param, SCIP_Real value);
255   // NOLINTNEXTLINE(readability-identifier-naming)
256   SCIP_RETCODE(__stdcall* SCIPchgCharParam)(SCIP* scip, SCIP_PARAM* param, char value);
257   // NOLINTNEXTLINE(readability-identifier-naming)
258   SCIP_RETCODE(__stdcall* SCIPchgStringParam)(SCIP* scip, SCIP_PARAM* param, const char* value);
259 
260 private:
261   void load();
262 };
263 
264 class MIPScipWrapper : public MIPWrapper {
265   SCIP* _scip = nullptr;
266   //     SCIP_Retcode           retcode = SCIP_OKAY;
267   //     char          scip_buffer[SCIP_MESSAGEBUFSIZE];
268   //     char          scip_status_buffer[SCIP_MESSAGEBUFSIZE];
269 
270   std::vector<SCIP_VAR*> _scipVars;
271   virtual SCIP_RETCODE delSCIPVars();
272 
273   std::vector<double> _x;
274 
275 public:
276   class FactoryOptions {
277   public:
278     bool processOption(int& i, std::vector<std::string>& argv, const std::string& workingDir);
279 
280     std::string scipDll;
281   };
282 
283   class Options : public MiniZinc::SolverInstanceBase::Options {
284   public:
285     int nThreads = 1;
286     std::string sExportModel;
287     int nTimeout = -1;
288     double nWorkMemLimit = -1;
289     std::string sReadParams;
290     std::string sWriteParams;
291     bool flagIntermediate = false;
292 
293     double absGap = -1;
294     double relGap = 1e-8;
295     double intTol = 1e-8;
296     double objDiff = 1.0;
297 
298     std::unordered_map<std::string, std::string> extraParams;
299 
300     bool processOption(int& i, std::vector<std::string>& argv, const std::string& workingDir);
301     static void printHelp(std::ostream& os);
302   };
303 
304 private:
305   FactoryOptions& _factoryOptions;
306   Options* _options = nullptr;
307   ScipPlugin* _plugin = nullptr;
308 
309 public:
MIPScipWrapper(FactoryOptions & factoryOpt,Options * opt)310   MIPScipWrapper(FactoryOptions& factoryOpt, Options* opt)
311       : _factoryOptions(factoryOpt), _options(opt) {
312     SCIP_PLUGIN_CALL(openSCIP());
313   }
~MIPScipWrapper()314   ~MIPScipWrapper() override {
315     SCIP_RETCODE ret = delSCIPVars();
316     assert(ret == SCIP_OKAY);
317     ret = closeSCIP();
318     assert(ret == SCIP_OKAY);
319   }
320 
321   static std::string getDescription(FactoryOptions& factoryOpt,
322                                     MiniZinc::SolverInstanceBase::Options* opt = nullptr);
323   static std::string getVersion(FactoryOptions& factoryOpt,
324                                 MiniZinc::SolverInstanceBase::Options* opt = nullptr);
325   static std::string getId();
326   static std::string getName();
327   static std::vector<std::string> getTags();
328   static std::vector<std::string> getStdFlags();
329   static std::vector<std::string> getRequiredFlags(FactoryOptions& factoryOpt);
330   static std::vector<std::string> getFactoryFlags();
331 
332   static std::vector<MiniZinc::SolverConfig::ExtraFlag> getExtraFlags(FactoryOptions& factoryOpt);
333 
334   bool processOption(int& i, int argc, const char** argv,
335                      const std::string& workingDir = std::string());
336   void printVersion(std::ostream& os);
337   void printHelp(std::ostream& os);
338   //       Statistics& getStatistics() { return _statistics; }
339 
340   //      IloConstraintArray *userCuts, *lazyConstraints;
341 
342   /// derived should overload and call the ancestor
343   //     virtual void cleanup();
344   SCIP_RETCODE openSCIP();
345   SCIP_RETCODE closeSCIP();
346 
347   SCIP_RETCODE includeEventHdlrBestsol();
348 
349   /// actual adding new variables to the solver
doAddVars(size_t n,double * obj,double * lb,double * ub,VarType * vt,std::string * names)350   void doAddVars(size_t n, double* obj, double* lb, double* ub, VarType* vt,
351                  std::string* names) override {
352     SCIP_PLUGIN_CALL(doAddVarsSCIP(n, obj, lb, ub, vt, names));
353   }
354   virtual SCIP_RETCODE doAddVarsSCIP(size_t n, double* obj, double* lb, double* ub, VarType* vt,
355                                      std::string* names);
356   void setVarBounds(int iVar, double lb, double ub) override;
357   void setVarLB(int iVar, double lb) override;
358   void setVarUB(int iVar, double ub) override;
359 
360   /// adding a linear constraint
addRow(int nnz,int * rmatind,double * rmatval,LinConType sense,double rhs,int mask=MaskConsType_Normal,const std::string & rowName="")361   void addRow(int nnz, int* rmatind, double* rmatval, LinConType sense, double rhs,
362               int mask = MaskConsType_Normal, const std::string& rowName = "") override {
363     SCIP_PLUGIN_CALL(addRowSCIP(nnz, rmatind, rmatval, sense, rhs, mask, rowName));
364   }
365   virtual SCIP_RETCODE addRowSCIP(int nnz, int* rmatind, double* rmatval, LinConType sense,
366                                   double rhs, int mask = MaskConsType_Normal,
367                                   const std::string& rowName = "");
368   /// adding an implication
369   //     virtual void addImpl() = 0;
370   /// Indicator constraint: x[iBVar]==bVal -> lin constr
371   void addIndicatorConstraint(int iBVar, int bVal, int nnz, int* rmatind, double* rmatval,
372                               LinConType sense, double rhs,
373                               const std::string& rowName = "") override;
374   /// Bounds disj for SCIP
375   void addBoundsDisj(int n, double* fUB, double* bnd, int* vars, int nF, double* fUBF, double* bndF,
376                      int* varsF, const std::string& rowName = "") override;
377 
378   /// Cumulative, currently SCIP only
379   void addCumulative(int nnz, int* rmatind, double* d, double* r, double b,
380                      const std::string& rowName = "") override;
381 
382   /// Lex-lesseq binary, currently SCIP only
383   void addLexLesseq(int nnz, int* rmatind1, int* rmatind2, bool isModelCons,
384                     const std::string& rowName = "") override;
385 
386   void addLexChainLesseq(int m, int n, int* rmatind, int nOrbitopeType, bool resolveprop,
387                          bool isModelCons, const std::string& rowName = "") override;
388 
389   /// Times constraint: var[x]*var[y] == var[z]
390   void addTimes(int x, int y, int z, const std::string& rowName = "") override;
391 
setObjSense(int s)392   void setObjSense(int s) override {  // +/-1 for max/min
393     SCIP_PLUGIN_CALL(setObjSenseSCIP(s));
394   }
395   virtual SCIP_RETCODE setObjSenseSCIP(int s);
396 
getInfBound()397   double getInfBound() override { return SCIPinfinityPlugin(_plugin, _scip); }
398 
getNCols()399   int getNCols() override { return _plugin->SCIPgetNVars(_scip); }
getNRows()400   int getNRows() override { return _plugin->SCIPgetNConss(_scip); }
401 
402   //     void setObjUB(double ub) { objUB = ub; }
403   //     void addQPUniform(double c) { qpu = c; } // also sets problem type to MIQP unless c=0
404 
solve()405   void solve() override { SCIP_PLUGIN_CALL(solveSCIP()); }
406   virtual SCIP_RETCODE solveSCIP();
407 
408   /// OUTPUT:
getValues()409   const double* getValues() override { return output.x; }
getObjValue()410   double getObjValue() override { return output.objVal; }
getBestBound()411   double getBestBound() override { return output.bestBound; }
getCPUTime()412   double getCPUTime() override { return output.dCPUTime; }
413 
getStatus()414   Status getStatus() override { return output.status; }
getStatusName()415   std::string getStatusName() override { return output.statusName; }
416 
getNNodes()417   int getNNodes() override { return output.nNodes; }
getNOpen()418   int getNOpen() override { return output.nOpenNodes; }
419 
420   //     virtual int getNNodes() = 0;
421   //     virtual double getTime() = 0;
422 
423 protected:
424   // NOLINTNEXTLINE(readability-identifier-naming)
425   void SCIP_PLUGIN_CALL(SCIP_RETCODE retcode, const std::string& msg = "", bool fTerm = true);
426 
427   /// Need to consider the 100 status codes in SCIP and change with every version? TODO
428   Status convertStatus(SCIP_STATUS scipStatus);
429 };
430