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   event_softtimelimit.c
26   	 * @ingroup DEFPLUGINS_EVENT
27   	 * @brief  eventhdlr for soft time limit
28   	 * @author Gerald Gamrath
29   	 */
30   	
31   	/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include "scip/event_softtimelimit.h"
34   	#include "scip/pub_event.h"
35   	#include "scip/pub_message.h"
36   	#include "scip/scip_event.h"
37   	#include "scip/scip_mem.h"
38   	#include "scip/scip_message.h"
39   	#include "scip/scip_numerics.h"
40   	#include "scip/scip_param.h"
41   	#include <string.h>
42   	
43   	#define EVENTHDLR_NAME         "softtimelimit"
44   	#define EVENTHDLR_DESC         "event handler for soft time limit"
45   	
46   	/*
47   	 * Data structures
48   	 */
49   	
50   	/** event handler data */
51   	struct SCIP_EventhdlrData
52   	{
53   	   SCIP_Real softtimelimit;
54   	   int filterpos;
55   	};
56   	
57   	/*
58   	 * Callback methods of event handler
59   	 */
60   	
61   	/** copy method for event handler plugins (called when SCIP copies plugins) */
62   	/**! [SnippetEventCopySofttimelimit] */
63   	static
64   	SCIP_DECL_EVENTCOPY(eventCopySofttimelimit)
65   	{  /*lint --e{715}*/
66   	   assert(scip != NULL);
67   	   assert(eventhdlr != NULL);
68   	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
69   	
70   	   /* call inclusion method of event handler */
71   	   SCIP_CALL( SCIPincludeEventHdlrSofttimelimit(scip) );
72   	
73   	   return SCIP_OKAY;
74   	}
75   	/**! [SnippetEventCopySofttimelimit] */
76   	
77   	/** destructor of event handler to free user data (called when SCIP is exiting) */
78   	/**! [SnippetEventFreeSofttimelimit] */
79   	static
80   	SCIP_DECL_EVENTFREE(eventFreeSofttimelimit)
81   	{  /*lint --e{715}*/
82   	   SCIP_EVENTHDLRDATA* eventhdlrdata;
83   	
84   	   assert(scip != NULL);
85   	   assert(eventhdlr != NULL);
86   	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
87   	
88   	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
89   	   assert(eventhdlrdata != NULL);
90   	
91   	   SCIPfreeBlockMemory(scip, &eventhdlrdata);
92   	   SCIPeventhdlrSetData(eventhdlr, NULL);
93   	
94   	   return SCIP_OKAY;
95   	}
96   	/**! [SnippetEventFreeSofttimelimit] */
97   	
98   	
99   	
100  	/** initialization method of event handler (called after problem was transformed) */
101  	static
102  	SCIP_DECL_EVENTINIT(eventInitSofttimelimit)
103  	{  /*lint --e{715}*/
104  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
105  	
106  	   assert(scip != NULL);
107  	   assert(eventhdlr != NULL);
108  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
109  	
110  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
111  	   assert(eventhdlrdata != NULL);
112  	
113  	   if( eventhdlrdata->filterpos < 0 && !SCIPisNegative(scip, eventhdlrdata->softtimelimit) )
114  	   {
115  	      /* notify SCIP that your event handler wants to react on the event type best solution found */
116  	      SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_BESTSOLFOUND, eventhdlr, NULL, &eventhdlrdata->filterpos) );
117  	   }
118  	
119  	   return SCIP_OKAY;
120  	}
121  	
122  	/** deinitialization method of event handler (called before transformed problem is freed) */
123  	static
124  	SCIP_DECL_EVENTEXIT(eventExitSofttimelimit)
125  	{  /*lint --e{715}*/
126  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
127  	
128  	   assert(scip != NULL);
129  	   assert(eventhdlr != NULL);
130  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
131  	
132  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
133  	   assert(eventhdlrdata != NULL);
134  	
135  	   /* notify SCIP that your event handler wants to drop the event type best solution found */
136  	   if( eventhdlrdata->filterpos >= 0 )
137  	   {
138  	      SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_BESTSOLFOUND, eventhdlr, NULL, eventhdlrdata->filterpos) );
139  	      eventhdlrdata->filterpos = -1;
140  	   }
141  	
142  	   return SCIP_OKAY;
143  	}
144  	
145  	/** execution method of event handler */
146  	static
147  	SCIP_DECL_EVENTEXEC(eventExecSofttimelimit)
148  	{  /*lint --e{715}*/
149  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
150  	   SCIP_Real timelimit;
151  	
152  	   assert(eventhdlr != NULL);
153  	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
154  	   assert(event != NULL);
155  	   assert(scip != NULL);
156  	   assert(SCIPeventGetType(event) == SCIP_EVENTTYPE_BESTSOLFOUND);
157  	
158  	   eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
159  	   assert(eventhdlrdata != NULL);
160  	
161  	   SCIPdebugMsg(scip, "exec method of event handler for soft time limit\n");
162  	
163  	   SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
164  	
165  	   if( eventhdlrdata->softtimelimit < timelimit )
166  	   {
167  	      SCIP_CALL( SCIPsetRealParam(scip, "limits/time", eventhdlrdata->softtimelimit) );
168  	   }
169  	
170  	   /* notify SCIP that your event handler wants to drop the event type best solution found */
171  	   SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_BESTSOLFOUND, eventhdlr, NULL, eventhdlrdata->filterpos) );
172  	   eventhdlrdata->filterpos = -1;
173  	
174  	   /* print best solution value */
175  	   SCIPverbMessage(scip, SCIP_VERBLEVEL_FULL, NULL, "changed time limit to %.1f after first solution was found\n",
176  	      eventhdlrdata->softtimelimit);
177  	
178  	   return SCIP_OKAY;
179  	}
180  	
181  	/** includes event handler for best solution found */
182  	SCIP_RETCODE SCIPincludeEventHdlrSofttimelimit(
183  	   SCIP*                 scip                /**< SCIP data structure */
184  	   )
185  	{
186  	   SCIP_EVENTHDLRDATA* eventhdlrdata;
187  	   SCIP_EVENTHDLR* eventhdlr = NULL;
188  	
189  	   SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
190  	   eventhdlrdata->filterpos = -1;
191  	
192  	   /* create event handler for events on watched variables */
193  	   SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecSofttimelimit, eventhdlrdata) );
194  	   assert(eventhdlr != NULL);
195  	
196  	   SCIP_CALL( SCIPsetEventhdlrCopy(scip, eventhdlr, eventCopySofttimelimit) );
197  	   SCIP_CALL( SCIPsetEventhdlrFree(scip, eventhdlr, eventFreeSofttimelimit) );
198  	   SCIP_CALL( SCIPsetEventhdlrInit(scip, eventhdlr, eventInitSofttimelimit) );
199  	   SCIP_CALL( SCIPsetEventhdlrExit(scip, eventhdlr, eventExitSofttimelimit) );
200  	
201  	   SCIP_CALL( SCIPaddRealParam(scip, "limits/softtime",
202  	         "soft time limit which should be applied after first solution was found (-1.0: disabled)",
203  	         &eventhdlrdata->softtimelimit, FALSE, -1.0, -1.0, SCIP_REAL_MAX, NULL, NULL) );
204  	
205  	   return SCIP_OKAY;
206  	}
207