1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   scip_prop.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  public methods for propagator plugins
28   	 * @author Tobias Achterberg
29   	 * @author Timo Berthold
30   	 * @author Gerald Gamrath
31   	 * @author Leona Gottwald
32   	 * @author Stefan Heinz
33   	 * @author Gregor Hendel
34   	 * @author Thorsten Koch
35   	 * @author Alexander Martin
36   	 * @author Marc Pfetsch
37   	 * @author Michael Winkler
38   	 * @author Kati Wolter
39   	 *
40   	 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
41   	 */
42   	
43   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44   	
45   	#include "scip/debug.h"
46   	#include "scip/prop.h"
47   	#include "scip/pub_message.h"
48   	#include "scip/pub_misc.h"
49   	#include "scip/pub_prop.h"
50   	#include "scip/scip_prop.h"
51   	#include "scip/set.h"
52   	#include "scip/struct_mem.h"
53   	#include "scip/struct_scip.h"
54   	#include "scip/struct_set.h"
55   	
56   	/** creates a propagator and includes it in SCIP.
57   	 *
58   	 *  @note method has all propagator callbacks as arguments and is thus changed every time a new
59   	 *        callback is added in future releases; consider using SCIPincludePropBasic() and setter functions
60   	 *        if you seek for a method which is less likely to change in future releases
61   	 */
62   	SCIP_RETCODE SCIPincludeProp(
63   	   SCIP*                 scip,               /**< SCIP data structure */
64   	   const char*           name,               /**< name of propagator */
65   	   const char*           desc,               /**< description of propagator */
66   	   int                   priority,           /**< priority of the propagator (>= 0: before, < 0: after constraint handlers) */
67   	   int                   freq,               /**< frequency for calling propagator */
68   	   SCIP_Bool             delay,              /**< should propagator be delayed, if other propagators found reductions? */
69   	   SCIP_PROPTIMING       timingmask,         /**< positions in the node solving loop where propagator should be executed */
70   	   int                   presolpriority,     /**< presolving priority of the propagator (>= 0: before, < 0: after constraint handlers) */
71   	   int                   presolmaxrounds,    /**< maximal number of presolving rounds the propagator participates in (-1: no limit) */
72   	   SCIP_PRESOLTIMING     presoltiming,       /**< timing mask of the propagator's presolving method */
73   	   SCIP_DECL_PROPCOPY    ((*propcopy)),      /**< copy method of propagator or NULL if you don't want to copy your plugin into sub-SCIPs */
74   	   SCIP_DECL_PROPFREE    ((*propfree)),      /**< destructor of propagator */
75   	   SCIP_DECL_PROPINIT    ((*propinit)),      /**< initialize propagator */
76   	   SCIP_DECL_PROPEXIT    ((*propexit)),      /**< deinitialize propagator */
77   	   SCIP_DECL_PROPINITPRE ((*propinitpre)),   /**< presolving initialization method of propagator */
78   	   SCIP_DECL_PROPEXITPRE ((*propexitpre)),   /**< presolving deinitialization method of propagator */
79   	   SCIP_DECL_PROPINITSOL ((*propinitsol)),   /**< solving process initialization method of propagator */
80   	   SCIP_DECL_PROPEXITSOL ((*propexitsol)),   /**< solving process deinitialization method of propagator */
81   	   SCIP_DECL_PROPPRESOL  ((*proppresol)),    /**< presolving method */
82   	   SCIP_DECL_PROPEXEC    ((*propexec)),      /**< execution method of propagator */
83   	   SCIP_DECL_PROPRESPROP ((*propresprop)),   /**< propagation conflict resolving method */
84   	   SCIP_PROPDATA*        propdata            /**< propagator data */
85   	   )
86   	{
87   	   SCIP_PROP* prop;
88   	
89   	   SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeProp", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
90   	
91   	   /* check whether propagator is already present */
92   	   if( SCIPfindProp(scip, name) != NULL )
93   	   {
94   	      SCIPerrorMessage("propagator <%s> already included.\n", name);
95   	      return SCIP_INVALIDDATA;
96   	   }
97   	
98   	   SCIP_CALL( SCIPpropCreate(&prop, scip->set, scip->messagehdlr, scip->mem->setmem,
99   	         name, desc, priority, freq, delay, timingmask, presolpriority, presolmaxrounds, presoltiming,
100  	         propcopy, propfree, propinit, propexit, propinitpre, propexitpre, propinitsol, propexitsol,
101  	         proppresol, propexec, propresprop, propdata) );
102  	   SCIP_CALL( SCIPsetIncludeProp(scip->set, prop) );
103  	
104  	   return SCIP_OKAY;
105  	}
106  	
107  	/** creates a propagator and includes it in SCIP. All non-fundamental (or optional) callbacks will be set to NULL.
108  	 *  Optional callbacks can be set via specific setter functions, see SCIPsetPropInit(), SCIPsetPropExit(),
109  	 *  SCIPsetPropCopy(), SCIPsetPropFree(), SCIPsetPropInitsol(), SCIPsetPropExitsol(),
110  	 *  SCIPsetPropInitpre(), SCIPsetPropExitpre(), SCIPsetPropPresol(), and SCIPsetPropResprop().
111  	 *
112  	*  @note if you want to set all callbacks with a single method call, consider using SCIPincludeProp() instead
113  	 */
114  	SCIP_RETCODE SCIPincludePropBasic(
115  	   SCIP*                 scip,               /**< SCIP data structure */
116  	   SCIP_PROP**           propptr,            /**< reference to a propagator pointer, or NULL */
117  	   const char*           name,               /**< name of propagator */
118  	   const char*           desc,               /**< description of propagator */
119  	   int                   priority,           /**< priority of the propagator (>= 0: before, < 0: after constraint handlers) */
120  	   int                   freq,               /**< frequency for calling propagator */
121  	   SCIP_Bool             delay,              /**< should propagator be delayed, if other propagators found reductions? */
122  	   SCIP_PROPTIMING       timingmask,         /**< positions in the node solving loop where propagators should be executed */
123  	   SCIP_DECL_PROPEXEC    ((*propexec)),      /**< execution method of propagator */
124  	   SCIP_PROPDATA*        propdata            /**< propagator data */
125  	   )
126  	{
127  	   SCIP_PROP* prop;
128  	
129  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPincludePropBasic", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
130  	
131  	   /* check whether propagator is already present */
132  	   if( SCIPfindProp(scip, name) != NULL )
133  	   {
134  	      SCIPerrorMessage("propagator <%s> already included.\n", name);
135  	      return SCIP_INVALIDDATA;
136  	   }
137  	
138  	   SCIP_CALL( SCIPpropCreate(&prop, scip->set, scip->messagehdlr, scip->mem->setmem,
139  	         name, desc, priority, freq, delay, timingmask, 0, -1, SCIP_PRESOLTIMING_ALWAYS,
140  	         NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
141  	         NULL, propexec, NULL, propdata) );
142  	   SCIP_CALL( SCIPsetIncludeProp(scip->set, prop) );
143  	
144  	   if( propptr != NULL )
145  	      *propptr = prop;
146  	
147  	   return SCIP_OKAY;
148  	}
149  	
150  	/** sets copy method of propagator */
151  	SCIP_RETCODE SCIPsetPropCopy(
152  	   SCIP*                 scip,               /**< SCIP data structure */
153  	   SCIP_PROP*            prop,               /**< propagator */
154  	   SCIP_DECL_PROPCOPY    ((*propcopy))       /**< copy method of propagator or NULL if you don't want to copy your plugin into sub-SCIPs */
155  	   )
156  	{
157  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropCopy", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
158  	
159  	   assert(prop != NULL);
160  	
161  	   SCIPpropSetCopy(prop, propcopy);
162  	
163  	   return SCIP_OKAY;
164  	}
165  	
166  	/** sets destructor method of propagator */
167  	SCIP_RETCODE SCIPsetPropFree(
168  	   SCIP*                 scip,               /**< SCIP data structure */
169  	   SCIP_PROP*            prop,               /**< propagator */
170  	   SCIP_DECL_PROPFREE    ((*propfree))       /**< destructor of propagator */
171  	   )
172  	{
173  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropFree", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
174  	
175  	   assert(prop != NULL);
176  	
177  	   SCIPpropSetFree(prop, propfree);
178  	
179  	   return SCIP_OKAY;
180  	}
181  	
182  	/** sets initialization method of propagator */
183  	SCIP_RETCODE SCIPsetPropInit(
184  	   SCIP*                 scip,               /**< SCIP data structure */
185  	   SCIP_PROP*            prop,               /**< propagator */
186  	   SCIP_DECL_PROPINIT    ((*propinit))       /**< initialize propagator */
187  	   )
188  	{
189  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropInit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
190  	
191  	   assert(prop != NULL);
192  	
193  	   SCIPpropSetInit(prop, propinit);
194  	
195  	   return SCIP_OKAY;
196  	}
197  	
198  	/** sets deinitialization method of propagator */
199  	SCIP_RETCODE SCIPsetPropExit(
200  	   SCIP*                 scip,               /**< SCIP data structure */
201  	   SCIP_PROP*            prop,               /**< propagator */
202  	   SCIP_DECL_PROPEXIT    ((*propexit))       /**< deinitialize propagator */
203  	   )
204  	{
205  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropExit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
206  	
207  	   assert(prop != NULL);
208  	
209  	   SCIPpropSetExit(prop, propexit);
210  	
211  	   return SCIP_OKAY;
212  	}
213  	
214  	/** sets solving process initialization method of propagator */
215  	SCIP_RETCODE SCIPsetPropInitsol(
216  	   SCIP*                 scip,               /**< SCIP data structure */
217  	   SCIP_PROP*            prop,               /**< propagator */
218  	   SCIP_DECL_PROPINITSOL((*propinitsol))     /**< solving process initialization method of propagator */
219  	   )
220  	{
221  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropInitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
222  	
223  	   assert(prop != NULL);
224  	
225  	   SCIPpropSetInitsol(prop, propinitsol);
226  	
227  	   return SCIP_OKAY;
228  	}
229  	
230  	/** sets solving process deinitialization method of propagator */
231  	SCIP_RETCODE SCIPsetPropExitsol(
232  	   SCIP*                 scip,               /**< SCIP data structure */
233  	   SCIP_PROP*            prop,               /**< propagator */
234  	   SCIP_DECL_PROPEXITSOL ((*propexitsol))    /**< solving process deinitialization method of propagator */
235  	   )
236  	{
237  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropExitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
238  	
239  	   assert(prop != NULL);
240  	
241  	   SCIPpropSetExitsol(prop, propexitsol);
242  	
243  	   return SCIP_OKAY;
244  	}
245  	
246  	/** sets preprocessing initialization method of propagator */
247  	SCIP_RETCODE SCIPsetPropInitpre(
248  	   SCIP*                 scip,               /**< SCIP data structure */
249  	   SCIP_PROP*            prop,               /**< propagator */
250  	   SCIP_DECL_PROPINITPRE((*propinitpre))     /**< preprocessing initialization method of propagator */
251  	   )
252  	{
253  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropInitpre", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
254  	
255  	   assert(prop != NULL);
256  	
257  	   SCIPpropSetInitpre(prop, propinitpre);
258  	
259  	   return SCIP_OKAY;
260  	}
261  	
262  	/** sets preprocessing deinitialization method of propagator */
263  	SCIP_RETCODE SCIPsetPropExitpre(
264  	   SCIP*                 scip,               /**< SCIP data structure */
265  	   SCIP_PROP*            prop,               /**< propagator */
266  	   SCIP_DECL_PROPEXITPRE((*propexitpre))     /**< preprocessing deinitialization method of propagator */
267  	   )
268  	{
269  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropExitpre", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
270  	
271  	   assert(prop != NULL);
272  	
273  	   SCIPpropSetExitpre(prop, propexitpre);
274  	
275  	   return SCIP_OKAY;
276  	}
277  	
278  	/** sets presolving method of propagator */
279  	SCIP_RETCODE SCIPsetPropPresol(
280  	   SCIP*                 scip,               /**< SCIP data structure */
281  	   SCIP_PROP*            prop,               /**< propagator */
282  	   SCIP_DECL_PROPPRESOL((*proppresol)),      /**< presolving method of propagator */
283  	   int                   presolpriority,     /**< presolving priority of the propagator (>= 0: before, < 0: after constraint handlers) */
284  	   int                   presolmaxrounds,    /**< maximal number of presolving rounds the propagator participates in (-1: no limit) */
285  	   SCIP_PRESOLTIMING     presoltiming        /**< timing mask of the propagator's presolving method */
286  	   )
287  	{
288  	   const char* name;
289  	   char paramname[SCIP_MAXSTRLEN];
290  	
291  	   assert(scip != NULL);
292  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropPresol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
293  	
294  	   assert(prop != NULL);
295  	   SCIP_CALL( SCIPpropSetPresol(prop, proppresol, presolpriority, presolmaxrounds, presoltiming) );
296  	
297  	   name = SCIPpropGetName(prop);
298  	
299  	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "propagating/%s/maxprerounds", name);
300  	   SCIP_CALL( SCIPsetSetDefaultIntParam(scip->set, paramname, presolmaxrounds) );
301  	
302  	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "propagating/%s/presolpriority", name);
303  	   SCIP_CALL( SCIPsetSetDefaultIntParam(scip->set, paramname, presolpriority) );
304  	
305  	   (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "propagating/%s/presoltiming", name);
306  	   SCIP_CALL( SCIPsetSetDefaultIntParam(scip->set, paramname, (int) presoltiming) );
307  	
308  	   return SCIP_OKAY;
309  	}
310  	
311  	/** sets propagation conflict resolving callback of propagator */
312  	SCIP_RETCODE SCIPsetPropResprop(
313  	   SCIP*                 scip,               /**< SCIP data structure */
314  	   SCIP_PROP*            prop,               /**< propagator */
315  	   SCIP_DECL_PROPRESPROP ((*propresprop))    /**< propagation conflict resolving callback */
316  	   )
317  	{
318  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPropResprop", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
319  	
320  	   assert(prop != NULL);
321  	
322  	   SCIPpropSetResprop(prop, propresprop);
323  	
324  	   return SCIP_OKAY;
325  	}
326  	
327  	
328  	/** returns the propagator of the given name, or NULL if not existing */
329  	SCIP_PROP* SCIPfindProp(
330  	   SCIP*                 scip,               /**< SCIP data structure */
331  	   const char*           name                /**< name of propagator */
332  	   )
333  	{
334  	   assert(scip != NULL);
335  	   assert(scip->set != NULL);
336  	   assert(name != NULL);
337  	
338  	   return SCIPsetFindProp(scip->set, name);
339  	}
340  	
341  	/** returns the array of currently available propagators */
342  	SCIP_PROP** SCIPgetProps(
343  	   SCIP*                 scip                /**< SCIP data structure */
344  	   )
345  	{
346  	   assert(scip != NULL);
347  	   assert(scip->set != NULL);
348  	
349  	   SCIPsetSortProps(scip->set);
350  	
351  	   return scip->set->props;
352  	}
353  	
354  	/** returns the number of currently available propagators */
355  	int SCIPgetNProps(
356  	   SCIP*                 scip                /**< SCIP data structure */
357  	   )
358  	{
359  	   assert(scip != NULL);
360  	   assert(scip->set != NULL);
361  	
362  	   return scip->set->nprops;
363  	}
364  	
365  	/** sets the priority of a propagator */
366  	SCIP_RETCODE SCIPsetPropPriority(
367  	   SCIP*                 scip,               /**< SCIP data structure */
368  	   SCIP_PROP*            prop,               /**< propagator */
369  	   int                   priority            /**< new priority of the propagator */
370  	   )
371  	{
372  	   assert(scip != NULL);
373  	   assert(scip->set != NULL);
374  	
375  	   SCIPpropSetPriority(prop, scip->set, priority);
376  	
377  	   return SCIP_OKAY;
378  	}
379  	
380  	/** sets the presolving priority of a propagator */
381  	SCIP_RETCODE SCIPsetPropPresolPriority(
382  	   SCIP*                 scip,               /**< SCIP data structure */
383  	   SCIP_PROP*            prop,               /**< propagator */
384  	   int                   presolpriority      /**< new presol priority of the propagator */
385  	   )
386  	{
387  	   assert(scip != NULL);
388  	   assert(scip->set != NULL);
389  	
390  	   SCIPpropSetPresolPriority(prop, scip->set, presolpriority);
391  	
392  	   return SCIP_OKAY;
393  	}
394