SCIP-SDP  3.2.0
branch_sdpmostinf.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2020 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program 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, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2020 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
42 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
43 
44 /*#define SCIP_DEBUG*/
45 
46 #include <assert.h>
47 #include <string.h>
48 
49 #include "branch_sdpmostinf.h"
50 
51 /* turn off lint warnings for whole file: */
52 /*lint --e{788,818}*/
53 
54 #define BRANCHRULE_NAME "sdpmostinf"
55 #define BRANCHRULE_DESC "branch on the most infeasible variable of the SDP"
56 #define BRANCHRULE_PRIORITY 1000000
57 #define BRANCHRULE_MAXDEPTH -1
58 #define BRANCHRULE_MAXBOUNDDIST 1.0
59 
60 
61 /*
62  * Data structures
63  */
64 
65 /*
66  * Local methods
67  */
68 
69 /* put your local methods here, and declare them static */
70 
71 
72 /*
73  * Callback methods of branching rule
74  */
75 
77 static
78 SCIP_DECL_BRANCHCOPY(branchCopySdpmostinf)
79 { /*lint --e{715}*/
80  assert(scip != NULL);
81  assert(branchrule != NULL);
82  assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
83 
84  /* call inclusion method of branchrule */
86 
87  return SCIP_OKAY;
88 }
89 
91 static
92 SCIP_DECL_BRANCHEXECEXT(branchExecextSdpmostinf)
93 {/*lint --e{715}*/
94  int i;
95  int ncands;
96  SCIP_VAR** cands = NULL;
97  SCIP_Real* candssol; /* solution values of all candidates */
98  SCIP_Real* candsscore; /* scores of all candidates */
99  SCIP_Real currentfrac; /* fractionality of the current candidate */
100  SCIP_Real currentinf; /* infeasibility of the current candidate */
101  SCIP_Real mostinfinf; /* infeasibility of the current most infeasible variable */
102  SCIP_Real mostinfscore; /* score of the current most infeasible variable */
103  SCIP_Real mostinfobj; /* objective of the current most infeasible variable */
104  SCIP_Real mostinfval; /* value of the current most infeasible variable */
105  SCIP_VAR* mostinfvar = NULL; /* variable with the highest current infeasibility */
106 
107  assert( scip != NULL );
108  assert( result != NULL );
109 
110  SCIPdebugMsg(scip, "Executing External Branching method of SDP-mostinf!\n");
111 
112  /* get the external candidates, as we use the score only as a tiebreaker, we aren't interested in the number of
113  * variables of different types with maximal score, so these return values are set to NULL */
114  SCIP_CALL( SCIPgetExternBranchCands(scip, &cands, &candssol, &candsscore, &ncands, NULL, NULL, NULL, NULL) );
115 
116  assert( ncands > 0 ); /* branchExecext should only be called if the list of external branching candidates is non-empty */
117 
118 #ifdef SCIP_DEBUG
119  SCIPdebugMsg(scip, "branching candidates for SDP-mostinf:\n");
120  for (i = 0; i < ncands; i++)
121  SCIPdebugMsg(scip, "%s, value = %f, score = %f\n", SCIPvarGetName(cands[i]), candssol[i], candsscore[i]);
122 #endif
123 
124  mostinfinf = -1.0;
125  mostinfscore = 0.0;
126  mostinfval = 0.0;
127  mostinfobj = -1.0;
128 
129  /* iterate over all solution candidates to find the one with the highest infeasibility */
130  for (i = 0; i < ncands; i++)
131  {
132  /* we skip all continuous variables, since we first want to branch on integral variables */
133  if ( SCIPvarGetType(cands[i]) == SCIP_VARTYPE_CONTINUOUS )
134  {
135  SCIPdebugMsg(scip, "skipping continuous variable %s\n", SCIPvarGetName(cands[i]));
136  continue;
137  }
138 
139  currentfrac = SCIPfeasFrac(scip, candssol[i]);
140  currentinf = (currentfrac <= 0.5) ? currentfrac : 1 - currentfrac;
141  /* a candidate is better than the current one if:
142  * - the infeasibility is (feastol-)bigger than before or
143  * - the infeasibility is (feastol-)equal and the score is (epsilon-)bigger or
144  * - the infeasibility and score are (feastol-/epsilon-)equal and the objective is (epsilon-)bigger than before
145  * - add three above are (feastol-/epsilon-)equal and the index is smaller */
146  if ( SCIPisFeasGT(scip, currentinf, mostinfinf) ||
147  (SCIPisFeasEQ(scip, currentinf, mostinfinf) && SCIPisGT(scip, candsscore[i], mostinfscore)) ||
148  (SCIPisFeasEQ(scip, currentinf, mostinfinf) && SCIPisEQ(scip, candsscore[i], mostinfscore) && SCIPisGT(scip, SCIPvarGetObj(cands[i]), mostinfobj)) ||
149  (SCIPisFeasEQ(scip, currentinf, mostinfinf) && SCIPisEQ(scip, candsscore[i], mostinfscore) && SCIPisEQ(scip, SCIPvarGetObj(cands[i]), mostinfobj) &&
150  SCIPvarGetIndex(cands[i]) < SCIPvarGetIndex(mostinfvar)) )
151  {
152  /* update the current best candidate */
153  mostinfinf = currentinf;
154  mostinfval = candssol[i];
155  mostinfobj = REALABS(SCIPvarGetObj(cands[i]));
156  mostinfscore = candsscore[i];
157  mostinfvar = cands[i];
158  }
159  }
160 
161  /* if all variables were continuous, we return DIDNOTRUN and let one of the SCIP branching rules decide */
162  if ( mostinfinf == -1.0 )
163  {
164  SCIPdebugMsg(scip, "Skipping SDP-mostinf branching rule since all branching variables are continuous\n");
165  *result = SCIP_DIDNOTFIND;
166  return SCIP_OKAY;
167  }
168 
169  assert( mostinfvar != NULL );
170  assert( SCIPisFeasGT(scip, mostinfinf, 0.0) ); /* otherwise all variables are fixed and there is nothing to branch */
171 
172  /* branch */
173  SCIPdebugMsg(scip, "branching on variable %s with value %f and score %f\n", SCIPvarGetName(mostinfvar), mostinfval, mostinfscore);
174  SCIP_CALL( SCIPbranchVarVal(scip, mostinfvar, mostinfval, NULL, NULL, NULL) );
175 
176  *result = SCIP_BRANCHED;
177 
178  return SCIP_OKAY;
179 }
180 
181 /*
182  * branching rule specific interface methods
183  */
184 
187  SCIP* scip
188  )
189 {
190  SCIP_BRANCHRULEDATA* branchruledata;
191  SCIP_BRANCHRULE* branchrule;
192 
193  /* create empty branching rule data */
194  branchruledata = NULL;
195 
196  branchrule = NULL;
197 
198  /* include branching rule */
199  SCIP_CALL( SCIPincludeBranchruleBasic(scip, &branchrule, BRANCHRULE_NAME, BRANCHRULE_DESC, BRANCHRULE_PRIORITY,
200  BRANCHRULE_MAXDEPTH, BRANCHRULE_MAXBOUNDDIST, branchruledata) );
201 
202  assert(branchrule != NULL);
203 
204  /* set non fundamental callbacks via setter functions */
205  SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopySdpmostinf) );
206  SCIP_CALL( SCIPsetBranchruleExecExt(scip, branchrule, branchExecextSdpmostinf) );
207 
208  return SCIP_OKAY;
209 }
#define BRANCHRULE_MAXBOUNDDIST
SCIP_RETCODE SCIPincludeBranchruleSdpmostinf(SCIP *scip)
most infeasible branching rule for SCIP-SDP
#define BRANCHRULE_PRIORITY
static SCIP_DECL_BRANCHEXECEXT(branchExecextSdpmostinf)
#define BRANCHRULE_NAME
#define BRANCHRULE_MAXDEPTH
static SCIP_DECL_BRANCHCOPY(branchCopySdpmostinf)
#define BRANCHRULE_DESC