-
Notifications
You must be signed in to change notification settings - Fork 3
/
presol_trivial.c
209 lines (175 loc) · 7.18 KB
/
presol_trivial.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* This file is part of the program and library */
/* SCIP --- Solving Constraint Integer Programs */
/* */
/* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
/* fuer Informationstechnik Berlin */
/* */
/* SCIP is distributed under the terms of the ZIB Academic License. */
/* */
/* You should have received a copy of the ZIB Academic License */
/* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**@file presol_trivial.c
* @brief trivial presolver: round fractional bounds on integer variables, fix variables with equal bounds
* @author Tobias Achterberg
*/
/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
#include <assert.h>
#include <string.h>
#include "scip/presol_trivial.h"
#define PRESOL_NAME "trivial"
#define PRESOL_DESC "trivial presolver: round fractional bounds on integers, fix variables with equal bounds"
#define PRESOL_PRIORITY +9000000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
#define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
#define PRESOL_DELAY FALSE /**< should presolver be delayed, if other presolvers found reductions? */
#ifdef FIXSIMPLEVALUE
#define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
#endif
/*
* Callback methods of presolver
*/
/** copy method for constraint handler plugins (called when SCIP copies plugins) */
static
SCIP_DECL_PRESOLCOPY(presolCopyTrivial)
{ /*lint --e{715}*/
assert(scip != NULL);
assert(presol != NULL);
assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
/* call inclusion method of presolver */
SCIP_CALL( SCIPincludePresolTrivial(scip) );
return SCIP_OKAY;
}
/** presolving execution method */
static
SCIP_DECL_PRESOLEXEC(presolExecTrivial)
{ /*lint --e{715}*/
SCIP_VAR** vars;
int nvars;
int v;
assert(result != NULL);
*result = SCIP_DIDNOTFIND;
/* get the problem variables */
vars = SCIPgetVars(scip);
nvars = SCIPgetNVars(scip);
/* scan the variables for trivial bound reductions
* (loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array)
*/
for( v = nvars-1; v >= 0; --v )
{
SCIP_Real lb;
SCIP_Real ub;
SCIP_Bool infeasible;
SCIP_Bool fixed;
/* get variable's bounds */
lb = SCIPvarGetLbGlobal(vars[v]);
ub = SCIPvarGetUbGlobal(vars[v]);
/* is variable integral? */
if( SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS )
{
SCIP_Real newlb;
SCIP_Real newub;
/* round fractional bounds on integer variables */
newlb = SCIPfeasCeil(scip, lb);
newub = SCIPfeasFloor(scip, ub);
/* check bounds on variable for infeasibility */
if( newlb > newub + 0.5 )
{
SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,
"problem infeasible: integral variable <%s> has bounds [%.17f,%.17f] rounded to [%.17f,%.17f]\n",
SCIPvarGetName(vars[v]), lb, ub, newlb, newub);
*result = SCIP_CUTOFF;
return SCIP_OKAY;
}
/* fix variables with equal bounds */
if( newlb > newub - 0.5 )
{
SCIPdebugMessage("fixing integral variable <%s>: [%.17f,%.17f] -> [%.17f,%.17f]\n",
SCIPvarGetName(vars[v]), lb, ub, newlb, newub);
SCIP_CALL( SCIPfixVar(scip, vars[v], newlb, &infeasible, &fixed) );
if( infeasible )
{
SCIPdebugMessage(" -> infeasible fixing\n");
*result = SCIP_CUTOFF;
return SCIP_OKAY;
}
assert(fixed);
(*nfixedvars)++;
}
else
{
/* round fractional bounds */
if( !SCIPisFeasEQ(scip, lb, newlb) )
{
SCIPdebugMessage("rounding lower bound of integral variable <%s>: [%.17f,%.17f] -> [%.17f,%.17f]\n",
SCIPvarGetName(vars[v]), lb, ub, newlb, ub);
SCIP_CALL( SCIPchgVarLb(scip, vars[v], newlb) );
(*nchgbds)++;
}
if( !SCIPisFeasEQ(scip, ub, newub) )
{
SCIPdebugMessage("rounding upper bound of integral variable <%s>: [%.17f,%.17f] -> [%.17f,%.17f]\n",
SCIPvarGetName(vars[v]), newlb, ub, newlb, newub);
SCIP_CALL( SCIPchgVarUb(scip, vars[v], newub) );
(*nchgbds)++;
}
}
}
else
{
/* check bounds on continuous variable for infeasibility */
if( SCIPisFeasGT(scip, lb, ub) )
{
SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,
"problem infeasible: continuous variable <%s> has bounds [%.17f,%.17f]\n",
SCIPvarGetName(vars[v]), lb, ub);
*result = SCIP_CUTOFF;
return SCIP_OKAY;
}
/* fix variables with equal bounds */
if( SCIPisEQ(scip, lb, ub) )
{
SCIP_Real fixval;
#ifdef FIXSIMPLEVALUE
fixval = SCIPselectSimpleValue(lb - 0.9 * SCIPepsilon(scip), ub + 0.9 * SCIPepsilon(scip), MAXDNOM);
#else
fixval = (lb + ub)/2;
#endif
SCIPdebugMessage("fixing continuous variable <%s>[%.17f,%.17f] to %.17f\n",
SCIPvarGetName(vars[v]), lb, ub, fixval);
SCIP_CALL( SCIPfixVar(scip, vars[v], fixval, &infeasible, &fixed) );
if( infeasible )
{
SCIPdebugMessage(" -> infeasible fixing\n");
*result = SCIP_CUTOFF;
return SCIP_OKAY;
}
assert(fixed);
(*nfixedvars)++;
}
}
}
return SCIP_OKAY;
}
/*
* presolver specific interface methods
*/
/** creates the trivial presolver and includes it in SCIP */
SCIP_RETCODE SCIPincludePresolTrivial(
SCIP* scip /**< SCIP data structure */
)
{
SCIP_PRESOLDATA* presoldata;
SCIP_PRESOL* presolptr;
/* create trivial presolver data */
presoldata = NULL;
/* include presolver */
SCIP_CALL( SCIPincludePresolBasic(scip, &presolptr, PRESOL_NAME, PRESOL_DESC, PRESOL_PRIORITY, PRESOL_MAXROUNDS, PRESOL_DELAY,
presolExecTrivial,
presoldata) );
assert(presolptr != NULL);
SCIP_CALL( SCIPsetPresolCopy(scip, presolptr, presolCopyTrivial) );
return SCIP_OKAY;
}