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-2024 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
49namespace ParaSCIP
50{
51
53 SCIP_BOUNDTYPE boundType;
54 int index;
55 SCIP_Real bound;
56};
57
58class ScipParaObjProp : public scip::ObjProp
59{
60 // UG::ParaComm *paraComm;
61 std::list<BoundChange *> boundChanges;
65public:
66 /** default constructor */
69 ScipParaSolver *inSolver
70 ) : scip::ObjProp::ObjProp(
71 inSolver->getScip(),
72 "ScipParaObjProp",
73 "Propagator for updating variable bounds",
74 (INT_MAX/4),
75 -1,
76 0,
77 SCIP_PROPTIMING_ALWAYS,
78 (INT_MAX/4) ,
79 -1,
80 SCIP_PRESOLTIMING_FAST
81 )// , paraComm(comm)
82 , solver(inSolver), ntotaltightened(0), ntotaltightenedint(0)
83 {
84 }
85
86 /** destructor */
88 {
89 std::list<BoundChange *>::iterator it = boundChanges.begin();
90 while( it != boundChanges.end() )
91 {
92 BoundChange *bc = boundChanges.front();
93 it = boundChanges.erase(it);
94 delete bc;
95 }
96 }
97
98 /** execution method of propagator
99 */
100 SCIP_RETCODE applyBoundChanges(SCIP *scip, int& ntightened, int& ntightenedint, SCIP_RESULT *result )
101 {
102 // std::cout << "#### exec propagator ##### Rank = " << paraComm->getRank() << std::endl;
103 ntightened = 0;
104 ntightenedint = 0;
105
106 *result = SCIP_DIDNOTFIND;
107
108 std::list<BoundChange *>::iterator it = boundChanges.begin();
109 while( it != boundChanges.end() )
110 {
111 BoundChange *bc = boundChanges.front();
112 SCIP_Var **orgVars = SCIPgetOrigVars(scip);
113 SCIP_Var *var = SCIPvarGetTransVar(orgVars[bc->index]);
114 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
115 {
116 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
117 {
118 SCIP_Var *varNeg = 0;
119 SCIP_CALL_ABORT ( SCIPgetNegatedVar(scip, var, &varNeg) );
120 if( SCIPvarIsActive(varNeg) )
121 {
122#ifdef UG_DEBUG_SOLUTION
123 SCIP_Real solvalue = 0.0;
124 SCIP_CALL(SCIPdebugGetSolVal(scip,orgVars[bc->index], &solvalue)); // this can happen, when there are several optimal solutions with DDP
125 std::cout << "Receiver side SolValue: " << SCIPvarGetName(orgVars[bc->index]) << " = " << solvalue << std::endl;
126 if( bc->boundType == SCIP_BOUNDTYPE_LOWER )
127 {
128 std::cout << "Receiver side (SCIP_BOUNDTYPE_LOWER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
129 SCIP_CALL_ABORT( SCIPdebugCheckLbGlobal(scip,orgVars[bc->index],bc->bound) );
130 }
131 else
132 {
133 std::cout << "Receiver side (SCIP_BOUNDTYPE_UPPER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
134 SCIP_CALL_ABORT( SCIPdebugCheckUbGlobal(scip,orgVars[bc->index],bc->bound) );
135 }
136#endif
137 SCIP_CALL( tryToTightenBound(scip, bc->boundType, orgVars[bc->index], bc->bound, result, ntightened, ntightenedint ) );
138 }
139 }
140 else
141 {
142#ifdef UG_DEBUG_SOLUTION
143 SCIP_Real solvalue = 0.0;
144 SCIP_CALL(SCIPdebugGetSolVal(scip,orgVars[bc->index], &solvalue)); // this can happen, when there are several optimal solutions with DDP
145 std::cout << "Receiver side SolValue: " << SCIPvarGetName(orgVars[bc->index]) << " = " << solvalue << std::endl;
146 if( bc->boundType == SCIP_BOUNDTYPE_LOWER )
147 {
148 std::cout << "Receiver side (SCIP_BOUNDTYPE_LOWER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
149 SCIP_CALL_ABORT( SCIPdebugCheckLbGlobal(scip,orgVars[bc->index],bc->bound) );
150 }
151 else
152 {
153 std::cout << "Receiver side (SCIP_BOUNDTYPE_UPPER): " << SCIPvarGetName(orgVars[bc->index]) << " = " << bc->bound << std::endl;
154 SCIP_CALL_ABORT( SCIPdebugCheckUbGlobal(scip,orgVars[bc->index],bc->bound) );
155 }
156#endif
157 SCIP_CALL( tryToTightenBound(scip, bc->boundType, orgVars[bc->index], bc->bound, result, ntightened, ntightenedint ) );
158 }
159 }
160 it = boundChanges.erase(it);
161 delete bc;
162 }
163
164 return SCIP_OKAY;
165 }
166
167 /** presolving method of propagator
168 */
169 virtual SCIP_DECL_PROPPRESOL(scip_presol)
170 {
171 int ntightened;
172 int ntightenedint;
173 *result = SCIP_DIDNOTRUN;
174
175 if( boundChanges.empty() || SCIPinProbing(scip) )
176 return SCIP_OKAY;
177
178 // if pending incumbent value exists, set it before apply bounds
179 if( solver->getPendingIncumbentValue() < SCIPgetObjlimit(scip) )
180 {
181 SCIPsetObjlimit(scip, solver->getPendingIncumbentValue());
182 }
183
184 applyBoundChanges(scip, ntightened, ntightenedint, result);
185
186 if( ntightened > 0 )
187 {
188 *nchgbds += ntightened;
189 ntotaltightened += ntightened;
190 ntotaltightenedint += ntightenedint;
191 if( *result != SCIP_CUTOFF )
192 *result = SCIP_SUCCESS;
193 // std::cout << "$$$$$ tightened " << ntightened << " var bounds in Rank " << paraComm->getRank() << " of which " << ntightenedint << " where integral vars." << std::endl;
194 }
195 SCIPpropSetFreq(prop, -1);
196 return SCIP_OKAY;
197 }
198
199 /** execution method of propagator
200 */
201 virtual SCIP_DECL_PROPEXEC(scip_exec)
202 {
203 // std::cout << "#### exec propagator ##### Rank = " << paraComm->getRank() << std::endl;
204 int ntightened;
205 int ntightenedint;
206 *result = SCIP_DIDNOTRUN;
207
208 if( SCIPinProbing(scip) || SCIPinRepropagation(scip) )
209 return SCIP_OKAY;
210
211 // if pending incumbent value exists, set it before apply bounds
212 if( solver->getPendingIncumbentValue() < SCIPgetObjlimit(scip) )
213 {
214 SCIPsetObjlimit(scip, solver->getPendingIncumbentValue());
215 }
216
217 applyBoundChanges(scip, ntightened, ntightenedint, result);
218
219 if( ntightened > 0 )
220 {
221 ntotaltightened += ntightened;
222 ntotaltightenedint += ntightenedint;
223 if( *result != SCIP_CUTOFF )
224 *result = SCIP_REDUCEDDOM;
225 // std::cout << "$$$$$ tightened " << ntightened << " var bounds in Rank " << paraComm->getRank() << " of which " << ntightenedint << " where integral vars." << std::endl;
226 }
227 SCIPpropSetFreq(prop, -1);
228 return SCIP_OKAY;
229 }
230
231 SCIP_RETCODE tryToTightenBound(SCIP *scip, SCIP_BOUNDTYPE boundType, SCIP_VAR *var, SCIP_Real bound, SCIP_Result *result, int& ntightened, int& ntightenedint )
232 {
233 SCIP_Bool infeas, tightened;
234 if( boundType == SCIP_BOUNDTYPE_LOWER )
235 {
236 // std::cout << "### idx = " << bc->index << " Local lb = " << SCIPvarGetLbGlobal(orgVars[bc->index]) << ", bound = " << bc->bound << " #### Rank = " << paraComm->getRank() << std::endl;
237 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, bound, FALSE, &infeas, &tightened) );
238 }
239 else
240 {
241 assert(boundType == SCIP_BOUNDTYPE_UPPER);
242 // std::cout << "### idx = " << bc->index << " Local ub = " << SCIPvarGetUbGlobal(orgVars[bc->index]) << ", bound = " << bc->bound << " #### Rank = " << paraComm->getRank() << std::endl;
243 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, bound, FALSE, &infeas, &tightened) );
244 }
245 // std::cout << "#### call SCIPtightenVarLbGlobal or SCIPtightenVarUbGlobal ##### Rank = " << paraComm->getRank()
246 // << ", infeas = " << infeas << ", tightened = " << tightened << std::endl;
247 if( infeas )
248 {
249 ++ntightened;
250 ++ntightenedint;
251 *result = SCIP_CUTOFF;
252 return SCIP_OKAY;
253 }
254 if( tightened )
255 {
256 ++ntightened;
257 if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY
258 || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER )
259 ++ntightenedint;
260 }
261 return SCIP_OKAY;
262 }
263
264 void addBoundChange(SCIP *scip, SCIP_BOUNDTYPE boundType, int index, SCIP_Real bound)
265 {
266 BoundChange *bc = new BoundChange;
267 bc->boundType = boundType;
268 bc->index = index;
269 bc->bound = bound;
270 boundChanges.push_back(bc);
271 SCIPsetIntParam(scip, "propagating/ScipParaObjProp/freq", 1);
272 }
273
276};
277
278} /* namespace ParaSCIP */
279
280#endif // __SCIP_PARA_OBJPROP_H__
virtual SCIP_DECL_PROPPRESOL(scip_presol)
virtual SCIP_DECL_PROPEXEC(scip_exec)
SCIP_RETCODE tryToTightenBound(SCIP *scip, SCIP_BOUNDTYPE boundType, SCIP_VAR *var, SCIP_Real bound, SCIP_Result *result, int &ntightened, int &ntightenedint)
std::list< BoundChange * > boundChanges
SCIP_RETCODE applyBoundChanges(SCIP *scip, int &ntightened, int &ntightenedint, SCIP_RESULT *result)
void addBoundChange(SCIP *scip, SCIP_BOUNDTYPE boundType, int index, SCIP_Real bound)
ScipParaObjProp(UG::ParaComm *comm, ScipParaSolver *inSolver)
double getPendingIncumbentValue()
get pending incumbent value
Base class of communicator object.
Definition: paraComm.h:102
static ScipParaCommTh * comm
Definition: fscip.cpp:73
Base class of communicator for UG Framework.
ParaSolver extension for SCIP: Parallelized solver implementation for SCIP.
SCIP_BOUNDTYPE boundType