Scippy

UG

Ubiquity Generator framework

scipParaObjProp.h
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and software framework */
4 /* UG --- Ubquity Generator Framework */
5 /* */
6 /* Copyright Written by Yuji Shinano <shinano@zib.de>, */
7 /* Copyright (C) 2021 by Zuse Institute Berlin, */
8 /* licensed under LGPL version 3 or later. */
9 /* Commercial licenses are available through <licenses@zib.de> */
10 /* */
11 /* This code is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 /* */
24 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
25 
26 /**@file scipParaObjProp.h
27  * @brief C++ wrapper for propagators
28  * @author Yuji Shinano
29  */
30 
31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32 
33 #ifndef __SCIP_PARA_OBJPROP_H__
34 #define __SCIP_PARA_OBJPROP_H__
35 
36 #include <cstring>
37 #include <list>
38 
39 #include "scipParaSolver.h"
40 #include "objscip/objprop.h"
41 #include "ug/paraComm.h"
42 #ifdef UG_DEBUG_SOLUTION
43 #ifndef WITH_DEBUG_SOLUTION
44 #define WITH_DEBUG_SOLUTION
45 #endif
46 #include "scip/debug.h"
47 #endif
48 
49 namespace ParaSCIP
50 {
51 
52 struct BoundChange{
53  SCIP_BOUNDTYPE boundType;
54  int index;
55  SCIP_Real bound;
56 };
57 
58 /** @brief C++ wrapper for propagators
59  *
60  * This class defines the interface for propagators implemented in C++. Note that there is a pure virtual
61  * function (this function has to be implemented). This function is: scip_exec().
62  *
63  * - \ref PROP "Instructions for implementing a propagator"
64  * - \ref PROPAGATORS "List of available propagators"
65  * - \ref type_prop.h "Corresponding C interface"
66  */
67 class ScipParaObjProp : public scip::ObjProp
68 {
69  // UG::ParaComm *paraComm;
70  std::list<BoundChange *> boundChanges;
74 public:
75  /** default constructor */
78  ScipParaSolver *inSolver
79  ) : scip::ObjProp::ObjProp(
80  inSolver->getScip(),
81  "ScipParaObjProp",
82  "Propagator for updating variable bounds",
83  (INT_MAX/4),
84  -1,
85  0,
86  SCIP_PROPTIMING_ALWAYS,
87  (INT_MAX/4) ,
88  -1,
89  SCIP_PRESOLTIMING_FAST
90  )// , paraComm(comm)
91  , solver(inSolver), ntotaltightened(0), ntotaltightenedint(0)
92  {
93  }
94 
95  /** destructor */
96  virtual ~ScipParaObjProp()
97  {
98  std::list<BoundChange *>::iterator it = boundChanges.begin();
99  while( it != boundChanges.end() )
100  {
101  BoundChange *bc = boundChanges.front();
102  it = boundChanges.erase(it);
103  delete bc;
104  }
105  }
106 
107  /** execution method of propagator
108  *
109  * @see SCIP_DECL_PROPEXEC(x) in @ref type_prop.h
110  */
111  SCIP_RETCODE applyBoundChanges(SCIP *scip, int& ntightened, int& ntightenedint, SCIP_RESULT *result )
112  {
113  // std::cout << "#### exec propagator ##### Rank = " << paraComm->getRank() << std::endl;
114  ntightened = 0;
115  ntightenedint = 0;
116 
117  *result = SCIP_DIDNOTFIND;
118 
119  std::list<BoundChange *>::iterator it = boundChanges.begin();
120  while( it != boundChanges.end() )
121  {
122  BoundChange *bc = boundChanges.front();
123  SCIP_Var **orgVars = SCIPgetOrigVars(scip);
124  SCIP_Var *var = SCIPvarGetTransVar(orgVars[bc->index]);
125  if ( *result != SCIP_CUTOFF && var && SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR && SCIPvarGetStatus(var) != SCIP_VARSTATUS_AGGREGATED ) // Can recive bounds during presolving
126  {
127  if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
128  {
129  SCIP_Var *varNeg = 0;
130  SCIP_CALL_ABORT ( SCIPgetNegatedVar(scip, var, &varNeg) );
131  if( SCIPvarIsActive(varNeg) )
132  {
133 #ifdef UG_DEBUG_SOLUTION
134  SCIP_Real solvalue = 0.0;
135  SCIP_CALL(SCIPdebugGetSolVal(scip,orgVars[bc->index], &solvalue)); // this can happen, when there are several optimal solutions with DDP
136  std::cout << "Receiver side SolValue: " << SCIPvarGetName(orgVars[bc->index]) << " = " << solvalue << std::endl;
137  if( bc->boundType == SCIP_BOUNDTYPE_LOWER )
138  {
139  std::cout << "Receiver side (SCIP_BOUNDTYPE_LOWER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
140  SCIP_CALL_ABORT( SCIPdebugCheckLbGlobal(scip,orgVars[bc->index],bc->bound) );
141  }
142  else
143  {
144  std::cout << "Receiver side (SCIP_BOUNDTYPE_UPPER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
145  SCIP_CALL_ABORT( SCIPdebugCheckUbGlobal(scip,orgVars[bc->index],bc->bound) );
146  }
147 #endif
148  SCIP_CALL( tryToTightenBound(scip, bc->boundType, orgVars[bc->index], bc->bound, result, ntightened, ntightenedint ) );
149  }
150  }
151  else
152  {
153 #ifdef UG_DEBUG_SOLUTION
154  SCIP_Real solvalue = 0.0;
155  SCIP_CALL(SCIPdebugGetSolVal(scip,orgVars[bc->index], &solvalue)); // this can happen, when there are several optimal solutions with DDP
156  std::cout << "Receiver side SolValue: " << SCIPvarGetName(orgVars[bc->index]) << " = " << solvalue << std::endl;
157  if( bc->boundType == SCIP_BOUNDTYPE_LOWER )
158  {
159  std::cout << "Receiver side (SCIP_BOUNDTYPE_LOWER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
160  SCIP_CALL_ABORT( SCIPdebugCheckLbGlobal(scip,orgVars[bc->index],bc->bound) );
161  }
162  else
163  {
164  std::cout << "Receiver side (SCIP_BOUNDTYPE_UPPER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
165  SCIP_CALL_ABORT( SCIPdebugCheckUbGlobal(scip,orgVars[bc->index],bc->bound) );
166  }
167 #endif
168  SCIP_CALL( tryToTightenBound(scip, bc->boundType, orgVars[bc->index], bc->bound, result, ntightened, ntightenedint ) );
169  }
170  }
171  it = boundChanges.erase(it);
172  delete bc;
173  }
174 
175  return SCIP_OKAY;
176  }
177 
178  /** presolving method of propagator
179  *
180  * @see SCIP_DECL_PROPPRESOL(x) in @ref type_prop.h
181  */
182  virtual SCIP_DECL_PROPPRESOL(scip_presol)
183  {
184  int ntightened;
185  int ntightenedint;
186  *result = SCIP_DIDNOTRUN;
187 
188  if( boundChanges.empty() || SCIPinProbing(scip) )
189  return SCIP_OKAY;
190 
191  // if pending incumbent value exists, set it before apply bounds
192  if( solver->getPendingIncumbentValue() < SCIPgetObjlimit(scip) )
193  {
194  SCIPsetObjlimit(scip, solver->getPendingIncumbentValue());
195  }
196 
197  applyBoundChanges(scip, ntightened, ntightenedint, result);
198 
199  if( ntightened > 0 )
200  {
201  *nchgbds += ntightened;
202  ntotaltightened += ntightened;
203  ntotaltightenedint += ntightenedint;
204  if( *result != SCIP_CUTOFF )
205  *result = SCIP_SUCCESS;
206  // std::cout << "$$$$$ tightened " << ntightened << " var bounds in Rank " << paraComm->getRank() << " of which " << ntightenedint << " where integral vars." << std::endl;
207  }
208  SCIPpropSetFreq(prop, -1);
209  return SCIP_OKAY;
210  }
211 
212  /** execution method of propagator
213  *
214  * @see SCIP_DECL_PROPEXEC(x) in @ref type_prop.h
215  */
216  virtual SCIP_DECL_PROPEXEC(scip_exec)
217  {
218  // std::cout << "#### exec propagator ##### Rank = " << paraComm->getRank() << std::endl;
219  int ntightened;
220  int ntightenedint;
221  *result = SCIP_DIDNOTRUN;
222 
223  if( SCIPinProbing(scip) || SCIPinRepropagation(scip) )
224  return SCIP_OKAY;
225 
226  // if pending incumbent value exists, set it before apply bounds
227  if( solver->getPendingIncumbentValue() < SCIPgetObjlimit(scip) )
228  {
229  SCIPsetObjlimit(scip, solver->getPendingIncumbentValue());
230  }
231 
232  applyBoundChanges(scip, ntightened, ntightenedint, result);
233 
234  if( ntightened > 0 )
235  {
236  ntotaltightened += ntightened;
237  ntotaltightenedint += ntightenedint;
238  if( *result != SCIP_CUTOFF )
239  *result = SCIP_REDUCEDDOM;
240  // std::cout << "$$$$$ tightened " << ntightened << " var bounds in Rank " << paraComm->getRank() << " of which " << ntightenedint << " where integral vars." << std::endl;
241  }
242  SCIPpropSetFreq(prop, -1);
243  return SCIP_OKAY;
244  }
245 
246  SCIP_RETCODE tryToTightenBound(SCIP *scip, SCIP_BOUNDTYPE boundType, SCIP_VAR *var, SCIP_Real bound, SCIP_Result *result, int& ntightened, int& ntightenedint )
247  {
248  SCIP_Bool infeas, tightened;
249  if( boundType == SCIP_BOUNDTYPE_LOWER )
250  {
251  // std::cout << "### idx = " << bc->index << " Local lb = " << SCIPvarGetLbGlobal(orgVars[bc->index]) << ", bound = " << bc->bound << " #### Rank = " << paraComm->getRank() << std::endl;
252  SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, bound, FALSE, &infeas, &tightened) );
253  }
254  else
255  {
256  assert(boundType == SCIP_BOUNDTYPE_UPPER);
257  // std::cout << "### idx = " << bc->index << " Local ub = " << SCIPvarGetUbGlobal(orgVars[bc->index]) << ", bound = " << bc->bound << " #### Rank = " << paraComm->getRank() << std::endl;
258  SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, bound, FALSE, &infeas, &tightened) );
259  }
260  // std::cout << "#### call SCIPtightenVarLbGlobal or SCIPtightenVarUbGlobal ##### Rank = " << paraComm->getRank()
261  // << ", infeas = " << infeas << ", tightened = " << tightened << std::endl;
262  if( infeas )
263  {
264  ++ntightened;
265  ++ntightenedint;
266  *result = SCIP_CUTOFF;
267  return SCIP_OKAY;
268  }
269  if( tightened )
270  {
271  ++ntightened;
272  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY
273  || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
274  ++ntightenedint;
275  }
276  return SCIP_OKAY;
277  }
278 
279  void addBoundChange(SCIP *scip, SCIP_BOUNDTYPE boundType, int index, SCIP_Real bound)
280  {
281  BoundChange *bc = new BoundChange;
282  bc->boundType = boundType;
283  bc->index = index;
284  bc->bound = bound;
285  boundChanges.push_back(bc);
286  SCIPsetIntParam(scip, "propagating/ScipParaObjProp/freq", 1);
287  }
288 
289  int getNtightened(){ return ntotaltightened; }
290  int getNtightenedInt(){ return ntotaltightenedint; }
291 };
292 
293 } /* namespace ParaSCIP */
294 
295 #endif // __SCIP_PARA_OBJPROP_H__
virtual SCIP_DECL_PROPPRESOL(scip_presol)
ScipParaObjProp(UG::ParaComm *comm, ScipParaSolver *inSolver)
static ScipParaCommTh * comm
Definition: fscip.cpp:73
C++ wrapper for propagators.
std::list< BoundChange * > boundChanges
SCIP_RETCODE tryToTightenBound(SCIP *scip, SCIP_BOUNDTYPE boundType, SCIP_VAR *var, SCIP_Real bound, SCIP_Result *result, int &ntightened, int &ntightenedint)
SCIP_RETCODE applyBoundChanges(SCIP *scip, int &ntightened, int &ntightenedint, SCIP_RESULT *result)
ParaSolver extension for SCIP: Parallelized solver implementation for SCIP.
Base class of communicator for UG Framework.
double getPendingIncumbentValue()
get pending incumbent value
void addBoundChange(SCIP *scip, SCIP_BOUNDTYPE boundType, int index, SCIP_Real bound)
virtual SCIP_DECL_PROPEXEC(scip_exec)
SCIP_BOUNDTYPE boundType
Base class of communicator object.
Definition: paraComm.h:101