Scippy

GCG

Branch-and-Price & Column Generation for Everyone

clsvar_gamsdomain.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program */
4 /* GCG --- Generic Column Generation */
5 /* a Dantzig-Wolfe decomposition based extension */
6 /* of the branch-cut-and-price framework */
7 /* SCIP --- Solving Constraint Integer Programs */
8 /* */
9 /* Copyright (C) 2010-2021 Operations Research, RWTH Aachen University */
10 /* Zuse Institute Berlin (ZIB) */
11 /* */
12 /* This program is free software; you can redistribute it and/or */
13 /* modify it under the terms of the GNU Lesser General Public License */
14 /* as published by the Free Software Foundation; either version 3 */
15 /* of the License, or (at your option) any later version. */
16 /* */
17 /* This program is distributed in the hope that it will be useful, */
18 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
19 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
20 /* GNU Lesser General Public License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with this program; if not, write to the Free Software */
24 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
25 /* */
26 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27 
28 /**@file clsvar_gamsdomain.cpp
29  * @ingroup CLASSIFIERS
30  * @brief Classifies by domains from which variables are created TODO: what is together in one class?
31  * @author Stefanie Koß
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include "clsvar_gamsdomain.h"
37 #include "cons_decomp.h"
38 #include "cons_decomp.hpp"
39 #include <map>
40 #include <set>
41 #include <stdio.h>
42 #include <sstream>
43 #include <vector>
44 
45 #include "class_detprobdata.h"
46 
47 #include "class_varpartition.h"
48 #include "scip_misc.h"
49 
50 /* classifier properties */
51 #define DEC_CLASSIFIERNAME "gamsdomain" /**< name of classifier */
52 #define DEC_DESC "domain in gams file" /**< short description of classification */
53 #define DEC_PRIORITY 0 /**< priority of this classifier */
54 
55 #define DEC_ENABLED TRUE
56 
57 
58 /*
59  * Data structures
60  */
61 
62 /** classifier handler data */
63 struct DEC_ClassifierData
64 {
65  std::map<std::string, std::set<int>>* vartodomain; /**< maps variable name to the corresponding set of domain indices */
66 };
67 
68 /*
69  * Local methods
70  */
71 
72 /* put your local methods here, and declare them static */
73 
74 
75 /*
76  * classifier callback methods
77  */
78 
79 /** destructor of classifier to free user data (called when GCG is exiting) */
80 static
82 {
83  assert(scip != NULL);
84 
85  DEC_CLASSIFIERDATA* classifierdata = DECvarClassifierGetData(classifier);
86  assert(classifierdata != NULL);
87  assert(strcmp(DECvarClassifierGetName(classifier), DEC_CLASSIFIERNAME) == 0);
88 
89  delete classifierdata->vartodomain;
90 
91  SCIPfreeMemory(scip, &classifierdata);
92 
93  return SCIP_OKAY;
94 }
95 
96 static
97 DEC_DECL_VARCLASSIFY(classifierClassify)
98 {
99  gcg::DETPROBDATA* detprobdata;
100  if( transformed )
101  {
102  detprobdata = GCGconshdlrDecompGetDetprobdataPresolved(scip);
103  }
104  else
105  {
106  detprobdata = GCGconshdlrDecompGetDetprobdataOrig(scip);
107  }
108 
109  int nvar = detprobdata->getNVars();
110  std::vector<int> nvarsForClass( 0 ); // [i] holds number of variables for class i
111  std::vector<std::set<int>> domainForClass( 0 ); // [i] holds domain for class i
112  std::vector<int> classForVar( nvar, - 1 ); // [i] holds class index for variable i -> indexing over detection internal variable array!
113  int counterClasses = 0;
114 
116  assert(classifier != NULL);
117 
118  DEC_CLASSIFIERDATA* classdata = DECvarClassifierGetData(classifier);
119  assert(classdata != NULL);
120 
121  /* firstly, assign all variables to classindices */
122  // iterate over variables in detection and lookup in classdata->vartodomain
123  // iterating over classdata->vartosymbol and lookup variables with getIndexForVar fails with assertion if variable is not found -> should return error value?
124  for( int varid = 0; varid < detprobdata->getNVars(); ++ varid )
125  {
126  SCIP_VAR* var = detprobdata->getVar(varid);
127  std::string varname = std::string( SCIPvarGetName( var ) );
128  auto domainiter = classdata->vartodomain->find(varname);
129  std::set<int> domain;
130  if( domainiter != classdata->vartodomain->end() )
131  {
132  domain = domainiter->second;
133  }
134  else
135  {
136  domain = std::set<int>();
137  domain.insert(-1);
138  }
139 
140  bool classfound = false;
141 
142  /* check if class for domain exists */
143  for( size_t classid = 0; classid < domainForClass.size(); ++classid )
144  {
145  if( domain == domainForClass[classid] )
146  {
147  classfound = true;
148  classForVar[varid] = classid;
149  ++nvarsForClass[classid];
150  break;
151  }
152  }
153 
154  /* if not, create a new class index */
155  if( !classfound )
156  {
157  classForVar[varid] = counterClasses;
158  ++counterClasses;
159  domainForClass.push_back( domain );
160  nvarsForClass.push_back( 1 );
161  }
162  }
163  assert( counterClasses == (int) domainForClass.size() );
164 
165  /* secondly, use these information to create a ConsPartition */
166  gcg::VarPartition* partition = new gcg::VarPartition(scip, "gamsdomain", counterClasses, detprobdata->getNVars() );
167 
168  /* set class names and descriptions of every class */
169  for( int c = 0; c < partition->getNClasses(); ++ c )
170  {
171  std::stringstream text;
172  text << "{";
173  for( auto iter : domainForClass[c] )
174  {
175  text << iter;
176 
177  }
178  text << "}";
179  partition->setClassName( c, text.str().c_str() );
180  text.str( "" );
181  text.clear();
182  //text << "This class contains all variables with gams domain" << domainForClass[c] << ".";
183  partition->setClassDescription( c, text.str().c_str() );
184  }
185 
186  /* copy the constraint assignment information found in first step */
187  for( int i = 0; i < partition->getNVars(); ++ i )
188  {
189  partition->assignVarToClass( i, classForVar[i] );
190  }
191  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, " Varclassifier \"%s\" yields a classification with %d different variable classes \n", partition->getName(), partition->getNClasses() );
192 
193  detprobdata->addVarPartition(partition);
194  return SCIP_OKAY;
195 }
196 
197 /*
198  * classifier specific interface methods
199  */
200 
201 /** adds an entry to clsdata->vartodomain */
203  DEC_VARCLASSIFIER* classifier,
204  SCIP_VAR* var,
205  int symDomIdx[],
206  int* symDim
207 )
208 {
209  assert(classifier != NULL);
210  DEC_CLASSIFIERDATA* classdata = DECvarClassifierGetData(classifier);
211  assert(classdata != NULL);
212 
213  std::string varname = SCIPvarGetName( var );
214  char varnametrans[SCIP_MAXSTRLEN];
215  (void) SCIPsnprintf(varnametrans, SCIP_MAXSTRLEN, "t_%s", varname.c_str());
216  std::string nametrans(varnametrans);
217  std::set<int> domainset;
218  for( int i = 0; i < *symDim; ++i)
219  {
220  domainset.insert(symDomIdx[i]);
221  }
222  classdata->vartodomain->insert({varname, domainset});
223  classdata->vartodomain->insert({varnametrans, domainset});
224 
225  return SCIP_OKAY;
226 }
227 
228 /** creates the handler for gamsdomain classifier and includes it in SCIP */
230  SCIP* scip /**< SCIP data structure */
231 )
232 {
233  DEC_CLASSIFIERDATA* classifierdata = NULL;
234 
235  SCIP_CALL( SCIPallocMemory(scip, &classifierdata) );
236  assert(classifierdata != NULL);
237  classifierdata->vartodomain = new std::map<std::string, std::set<int>>();
238 
239  SCIP_CALL( DECincludeVarClassifier(scip, DEC_CLASSIFIERNAME, DEC_DESC, DEC_PRIORITY, DEC_ENABLED, classifierdata, classifierFree, classifierClassify) );
240 
241  return SCIP_OKAY;
242 }
class representing a partition of a set of variables
constraint handler for structure detection
DETPROBDATA * GCGconshdlrDecompGetDetprobdataOrig(SCIP *scip)
help method to access detprobdata for unpresolved problem
SCIP_RETCODE DECincludeVarClassifier(SCIP *scip, const char *name, const char *description, int priority, SCIP_Bool enabled, DEC_CLASSIFIERDATA *classifierdata, DEC_DECL_FREEVARCLASSIFIER((*freeClassifier)),)
std::map< std::string, std::set< int > > * vartodomain
DEC_CLASSIFIERDATA * DECvarClassifierGetData(DEC_VARCLASSIFIER *classifier)
returns the data of the provided varclassifier
various SCIP helper methods
#define classifierFree
static SCIP_RETCODE partition(SCIP *scip, SCIP_VAR **J, int *Jsize, SCIP_Longint *priority, SCIP_VAR **F, int Fsize, SCIP_VAR **origvar, SCIP_Real *median)
int getNVars()
return the number of variables considered in the detprobdata
SCIP_RETCODE DECvarClassifierGamsdomainAddEntry(DEC_VARCLASSIFIER *classifier, SCIP_VAR *var, int symDomIdx[], int *symDim)
#define DEC_CLASSIFIERNAME
C++ interface of cons_decomp.
static DEC_DECL_FREEVARCLASSIFIER(classifierFree)
SCIP_RETCODE SCIPincludeVarClassifierGamsdomain(SCIP *scip)
#define DEC_PRIORITY
const char * DECvarClassifierGetName(DEC_VARCLASSIFIER *classifier)
returns the name of the provided classifier
static DEC_DECL_VARCLASSIFY(classifierClassify)
void addVarPartition(VarPartition *partition)
adds a variable partition if it is no duplicate of an existing variable partition
#define DEC_DESC
DETPROBDATA * GCGconshdlrDecompGetDetprobdataPresolved(SCIP *scip)
help method to access detprobdata for transformed problem
Classifies by domains from which variables are created TODO: what is together in one class?
SCIP_VAR * getVar(int varIndex)
returns SCIP variable related to a variable index
DEC_VARCLASSIFIER * DECfindVarClassifier(SCIP *scip, const char *name)
searches for the varclassifier with the given name and returns it or NULL if classifier is not found
class storing partialdecs and the problem matrix
#define DEC_ENABLED