Scippy

GCG

Branch-and-Price & Column Generation for Everyone

clscons_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 clscons_gamsdomain.cpp
29  * @ingroup CLASSIFIERS
30  * @brief Classifies by domains from which constraints 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 #define SCIP_DEBUG
36 
37 #include "clscons_gamsdomain.h"
38 #include "cons_decomp.h"
39 #include "cons_decomp.hpp"
40 #include <vector>
41 #include <string>
42 #include <set>
43 #include <stdio.h>
44 #include <sstream>
45 
46 #include "class_detprobdata.h"
47 
48 #include "class_conspartition.h"
49 #include "scip_misc.h"
50 
51 /* classifier properties */
52 #define DEC_CLASSIFIERNAME "gamsdomain" /**< name of classifier */
53 #define DEC_DESC "domain in GAMS file" /**< short description of classification*/
54 #define DEC_PRIORITY 0
55 
56 #define DEC_ENABLED TRUE
57 
58 
59 /*
60  * Data structures
61  */
62 struct DEC_ClassifierData
63 {
64  std::map<std::string, std::set<int>>* constodomain; /**< maps constraint name to the corresponding set of domain indices */
65 };
66 
67 /*
68  * Local methods
69  */
70 
71 /* put your local methods here, and declare them static */
72 
73 
74 /*
75  * classifier callback methods
76  */
77 
78 /** destructor of classifier to free user data (called when GCG is exiting) */
79 static
81 {
82  DEC_CLASSIFIERDATA* classifierdata;
83 
84  assert(scip != NULL);
85 
86  classifierdata = DECconsClassifierGetData(classifier);
87  assert(classifierdata != NULL);
88  assert(strcmp(DECconsClassifierGetName(classifier), DEC_CLASSIFIERNAME) == 0);
89 
90  delete classifierdata->constodomain;
91 
92  SCIPfreeMemory(scip, &classifierdata);
93 
94  return SCIP_OKAY;
95 }
96 
97 static
98 DEC_DECL_CONSCLASSIFY(classifierClassify) {
99  gcg::DETPROBDATA* detprobdata;
100  if( transformed )
101  {
102  detprobdata = GCGconshdlrDecompGetDetprobdataPresolved(scip);
103  }
104  else
105  {
106  detprobdata = GCGconshdlrDecompGetDetprobdataOrig(scip);
107  }
108 
109  int ncons = detprobdata->getNConss();
110  std::vector<int> nconssForClass( 0 ); // [i] holds number of constraints for class i
111  std::vector<std::set<int>> domainForClass( 0 ); // [i] holds domain for class i
112  std::vector<int> classForCons( ncons, - 1 ); // [i] holds class index for constraint i -> indexing over detection internal constraint array!
113  int counterClasses = 0;
114 
116  assert(classifier != NULL);
117 
118  DEC_CLASSIFIERDATA* classdata = DECconsClassifierGetData(classifier);
119  assert(classdata != NULL);
120 
121  /* firstly, assign all constraints to classindices */
122  // iterate over constraints in detection and lookup in classdata->constodomain
123  for( int consid = 0; consid < detprobdata->getNConss(); ++ consid )
124  {
125  SCIP_CONS* cons = detprobdata->getCons(consid);
126  std::string consname = std::string( SCIPconsGetName( cons ) );
127 
128  auto domainiter = classdata->constodomain->find(consname);
129  std::set<int> domain;
130  if( domainiter != classdata->constodomain->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  classForCons[consid] = classid;
149  ++nconssForClass[classid];
150  break;
151  }
152  }
153 
154  /* if not, create a new class index */
155  if( !classfound )
156  {
157  classForCons[consid] = counterClasses;
158  ++counterClasses;
159  domainForClass.push_back( domain );
160  nconssForClass.push_back( 1 );
161  }
162  }
163  assert( counterClasses == (int) domainForClass.size() );
164 
165  /* secondly, use these information to create a ConsPartition */
166  gcg::ConsPartition* partition = new gcg::ConsPartition(scip, "gamsdomain", counterClasses, detprobdata->getNConss() );
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 constraints 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->getNConss(); ++ i )
188  {
189  partition->assignConsToClass( i, classForCons[i] );
190  }
191  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, " Consclassifier \"%s\" yields a classification with %d different constraint classes \n", partition->getName(), partition->getNClasses() );
192 
193  detprobdata->addConsPartition(partition);
194 
195  return SCIP_OKAY;
196 }
197 
198 /*
199  * classifier specific interface methods
200  */
201 
202 /** adds an entry to clsdata->constodomain */
204  DEC_CONSCLASSIFIER* classifier,
205  SCIP_CONS* cons,
206  int symDomIdx[],
207  int* symDim
208 )
209 {
210  assert(classifier != NULL);
211  DEC_CLASSIFIERDATA* classdata = DECconsClassifierGetData(classifier);
212  assert(classdata != NULL);
213 
214  std::string consname = SCIPconsGetName( cons );
215  std::set<int> domainset;
216  for( int i = 0; i < *symDim; ++i)
217  {
218  domainset.insert(symDomIdx[i]);
219  }
220  classdata->constodomain->insert({consname, domainset});
221 
222  return SCIP_OKAY;
223 }
224 
225 /** creates the handler for gamsdomain classifier and includes it in SCIP */
227  SCIP* scip /**< SCIP data structure */
228 )
229 {
230  DEC_CLASSIFIERDATA* classifierdata = NULL;
231 
232  SCIP_CALL( SCIPallocMemory(scip, &classifierdata) );
233  assert(classifierdata != NULL);
234  classifierdata->constodomain = new std::map<std::string, std::set<int>>();
235 
236  SCIP_CALL( DECincludeConsClassifier(scip, DEC_CLASSIFIERNAME, DEC_DESC, DEC_PRIORITY, DEC_ENABLED, classifierdata, classifierFree, classifierClassify) );
237 
238  return SCIP_OKAY;
239 }
int getNConss()
returns the number of variables considered in the detprobdata
DEC_CONSCLASSIFIER * DECfindConsClassifier(SCIP *scip, const char *name)
searches for the consclassifier with the given name and returns it or NULL if classifier is not found
#define DEC_ENABLED
constraint handler for structure detection
class representing a partition of a set of constraints
DETPROBDATA * GCGconshdlrDecompGetDetprobdataOrig(SCIP *scip)
help method to access detprobdata for unpresolved problem
SCIP_RETCODE DECconsClassifierGamsdomainAddEntry(DEC_CONSCLASSIFIER *classifier, SCIP_CONS *cons, int symDomIdx[], int *symDim)
DEC_CLASSIFIERDATA * DECconsClassifierGetData(DEC_CONSCLASSIFIER *classifier)
returns the data of the provided consclassifier
static DEC_DECL_CONSCLASSIFY(classifierClassify)
various SCIP helper methods
#define DEC_DESC
#define classifierFree
Classifies by domains from which constraints are created TODO: what is together in one class?
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)
SCIP_CONS * getCons(int consIndex)
returns the SCIP constraint related to a constraint index
C++ interface of cons_decomp.
std::map< std::string, std::set< int > > * constodomain
#define DEC_CLASSIFIERNAME
static DEC_DECL_FREECONSCLASSIFIER(classifierFree)
DETPROBDATA * GCGconshdlrDecompGetDetprobdataPresolved(SCIP *scip)
help method to access detprobdata for transformed problem
#define DEC_PRIORITY
SCIP_RETCODE SCIPincludeConsClassifierGamsdomain(SCIP *scip)
const char * DECconsClassifierGetName(DEC_CONSCLASSIFIER *classifier)
returns the name of the provided classifier
void addConsPartition(ConsPartition *partition)
adds a constraint partition if it is no duplicate of an existing constraint partition
SCIP_RETCODE DECincludeConsClassifier(SCIP *scip, const char *name, const char *description, int priority, SCIP_Bool enabled, DEC_CLASSIFIERDATA *classifierdata, DEC_DECL_FREECONSCLASSIFIER((*freeClassifier)),)
class storing partialdecs and the problem matrix